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_implementation/shenandoah/brooksPointer.hpp"
28 #include "gc_implementation/shenandoah/shenandoahAsserts.hpp"
29 #include "gc_implementation/shenandoah/shenandoahBarrierSet.inline.hpp"
30 #include "gc_implementation/shenandoah/shenandoahConcurrentMark.hpp"
31 #include "gc_implementation/shenandoah/shenandoahHeap.inline.hpp"
32 #include "gc_implementation/shenandoah/shenandoahTaskqueue.inline.hpp"
33 #include "memory/iterator.inline.hpp"
34 #include "oops/oop.inline.hpp"
35 #include "runtime/prefetch.inline.hpp"
36
37 template <class T, bool COUNT_LIVENESS>
38 void ShenandoahConcurrentMark::do_task(ShenandoahObjToScanQueue* q, T* cl, jushort* live_data, ShenandoahMarkTask* task) {
39 oop obj = task->obj();
40
41 shenandoah_assert_not_forwarded(NULL, obj);
42 shenandoah_assert_marked_next(NULL, obj);
43 shenandoah_assert_not_in_cset_except(NULL, obj, _heap->cancelled_concgc());
44
45 if (task->is_not_chunked()) {
46 if (COUNT_LIVENESS) count_liveness(live_data, obj);
47 if (obj->is_instance()) {
48 // Case 1: Normal oop, process as usual.
49 obj->oop_iterate(cl);
50 } else if (obj->is_objArray()) {
51 // Case 2: Object array instance and no chunk is set. Must be the first
52 // time we visit it, start the chunked processing.
53 do_chunked_array_start<T>(q, cl, obj);
54 } else {
55 // Case 3: Primitive array. Do nothing, no oops there. We use the same
56 // performance tweak TypeArrayKlass::oop_oop_iterate_impl is using:
57 // We skip iterating over the klass pointer since we know that
58 // Universe::TypeArrayKlass never moves.
59 assert (obj->is_typeArray(), "should be type array");
60 }
61 } else {
62 // Case 4: Array chunk, has sensible chunk id. Process it.
63 do_chunked_array<T>(q, cl, obj, task->chunk(), task->pow());
64 }
65 }
66
189
190 #ifdef ASSERT
191 int len = array->length();
192 assert (0 <= from && from < len, err_msg("from is sane: %d/%d", from, len));
193 assert (0 < to && to <= len, err_msg("to is sane: %d/%d", to, len));
194 #endif
195
196 array->oop_iterate_range(cl, from, to);
197 }
198
199 inline bool ShenandoahConcurrentMark::try_queue(ShenandoahObjToScanQueue* q, ShenandoahMarkTask &task) {
200 return (q->pop_buffer(task) ||
201 q->pop_local(task) ||
202 q->pop_overflow(task));
203 }
204
205 class ShenandoahSATBBufferClosure : public SATBBufferClosure {
206 private:
207 ShenandoahObjToScanQueue* _queue;
208 ShenandoahHeap* _heap;
209 public:
210 ShenandoahSATBBufferClosure(ShenandoahObjToScanQueue* q) :
211 _queue(q), _heap(ShenandoahHeap::heap())
212 {
213 }
214
215 void do_buffer(void** buffer, size_t size) {
216 for (size_t i = 0; i < size; ++i) {
217 oop* p = (oop*) &buffer[i];
218 ShenandoahConcurrentMark::mark_through_ref<oop, RESOLVE>(p, _heap, _queue);
219 }
220 }
221 };
222
223 inline bool ShenandoahConcurrentMark::try_draining_satb_buffer(ShenandoahObjToScanQueue *q, ShenandoahMarkTask &task) {
224 ShenandoahSATBBufferClosure cl(q);
225 SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set();
226 bool had_refs = satb_mq_set.apply_closure_to_completed_buffer(&cl);
227 return had_refs && try_queue(q, task);
228 }
229
230 template<class T, UpdateRefsMode UPDATE_REFS>
231 inline void ShenandoahConcurrentMark::mark_through_ref(T *p, ShenandoahHeap* heap, ShenandoahObjToScanQueue* q) {
232 T o = oopDesc::load_heap_oop(p);
233 if (! oopDesc::is_null(o)) {
234 oop obj = oopDesc::decode_heap_oop_not_null(o);
235 switch (UPDATE_REFS) {
236 case NONE:
237 break;
238 case RESOLVE:
239 obj = ShenandoahBarrierSet::resolve_forwarded_not_null(obj);
240 break;
241 case SIMPLE:
242 // We piggy-back reference updating to the marking tasks.
243 obj = heap->update_with_forwarded_not_null(p, obj);
244 break;
245 case CONCURRENT:
246 obj = heap->maybe_update_with_forwarded_not_null(p, obj);
247 break;
248 default:
249 ShouldNotReachHere();
250 }
251
252 // Note: Only when concurrently updating references can obj become NULL here.
253 // It happens when a mutator thread beats us by writing another value. In that
254 // case we don't need to do anything else.
255 if (UPDATE_REFS != CONCURRENT || !oopDesc::is_null(obj)) {
256 shenandoah_assert_not_forwarded(p, obj);
257 shenandoah_assert_not_in_cset_except(p, obj, heap->cancelled_concgc());
258
259 if (heap->mark_next(obj)) {
260 bool pushed = q->push(ShenandoahMarkTask(obj));
261 assert(pushed, "overflow queue should always succeed pushing");
262 }
263
264 shenandoah_assert_marked_next(p, obj);
265 }
266 }
267 }
268
269 #endif // SHARE_VM_GC_SHENANDOAH_SHENANDOAHCONCURRENTMARK_INLINE_HPP
|
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_implementation/shenandoah/brooksPointer.hpp"
28 #include "gc_implementation/shenandoah/shenandoahAsserts.hpp"
29 #include "gc_implementation/shenandoah/shenandoahBarrierSet.inline.hpp"
30 #include "gc_implementation/shenandoah/shenandoahConcurrentMark.hpp"
31 #include "gc_implementation/shenandoah/shenandoahMarkingContext.inline.hpp"
32 #include "gc_implementation/shenandoah/shenandoahHeap.inline.hpp"
33 #include "gc_implementation/shenandoah/shenandoahStringDedup.hpp"
34 #include "gc_implementation/shenandoah/shenandoahTaskqueue.inline.hpp"
35 #include "memory/iterator.inline.hpp"
36 #include "oops/oop.inline.hpp"
37 #include "runtime/prefetch.inline.hpp"
38
39 template <class T>
40 void ShenandoahConcurrentMark::do_task(ShenandoahObjToScanQueue* q, T* cl, jushort* live_data, ShenandoahMarkTask* task) {
41 oop obj = task->obj();
42
43 shenandoah_assert_not_forwarded(NULL, obj);
44 shenandoah_assert_marked_next(NULL, obj);
45 shenandoah_assert_not_in_cset_except(NULL, obj, _heap->cancelled_gc());
46
47 if (task->is_not_chunked()) {
48 count_liveness(live_data, obj);
49 if (obj->is_instance()) {
50 // Case 1: Normal oop, process as usual.
51 obj->oop_iterate(cl);
52 } else if (obj->is_objArray()) {
53 // Case 2: Object array instance and no chunk is set. Must be the first
54 // time we visit it, start the chunked processing.
55 do_chunked_array_start<T>(q, cl, obj);
56 } else {
57 // Case 3: Primitive array. Do nothing, no oops there. We use the same
58 // performance tweak TypeArrayKlass::oop_oop_iterate_impl is using:
59 // We skip iterating over the klass pointer since we know that
60 // Universe::TypeArrayKlass never moves.
61 assert (obj->is_typeArray(), "should be type array");
62 }
63 } else {
64 // Case 4: Array chunk, has sensible chunk id. Process it.
65 do_chunked_array<T>(q, cl, obj, task->chunk(), task->pow());
66 }
67 }
68
191
192 #ifdef ASSERT
193 int len = array->length();
194 assert (0 <= from && from < len, err_msg("from is sane: %d/%d", from, len));
195 assert (0 < to && to <= len, err_msg("to is sane: %d/%d", to, len));
196 #endif
197
198 array->oop_iterate_range(cl, from, to);
199 }
200
201 inline bool ShenandoahConcurrentMark::try_queue(ShenandoahObjToScanQueue* q, ShenandoahMarkTask &task) {
202 return (q->pop_buffer(task) ||
203 q->pop_local(task) ||
204 q->pop_overflow(task));
205 }
206
207 class ShenandoahSATBBufferClosure : public SATBBufferClosure {
208 private:
209 ShenandoahObjToScanQueue* _queue;
210 ShenandoahHeap* _heap;
211 ShenandoahMarkingContext* const _mark_context;
212 public:
213 ShenandoahSATBBufferClosure(ShenandoahObjToScanQueue* q) :
214 _queue(q),
215 _heap(ShenandoahHeap::heap()),
216 _mark_context(_heap->next_marking_context())
217 {
218 }
219
220 void do_buffer(void **buffer, size_t size) {
221 if (_heap->has_forwarded_objects()) {
222 do_buffer_impl<RESOLVE>(buffer, size);
223 } else {
224 do_buffer_impl<NONE>(buffer, size);
225 }
226 }
227
228 template<UpdateRefsMode UPDATE_REFS>
229 void do_buffer_impl(void **buffer, size_t size) {
230 for (size_t i = 0; i < size; ++i) {
231 oop *p = (oop *) &buffer[i];
232 ShenandoahConcurrentMark::mark_through_ref<oop, UPDATE_REFS>(p, _heap, _queue, _mark_context);
233 }
234 }
235 };
236
237 template<class T, UpdateRefsMode UPDATE_REFS>
238 inline void ShenandoahConcurrentMark::mark_through_ref(T *p, ShenandoahHeap* heap, ShenandoahObjToScanQueue* q, ShenandoahMarkingContext* const mark_context) {
239 ShenandoahConcurrentMark::mark_through_ref<T, UPDATE_REFS, false /* string dedup */>(p, heap, q, mark_context, NULL);
240 }
241
242 template<class T, UpdateRefsMode UPDATE_REFS, bool STRING_DEDUP>
243 inline void ShenandoahConcurrentMark::mark_through_ref(T *p, ShenandoahHeap* heap, ShenandoahObjToScanQueue* q, ShenandoahMarkingContext* const mark_context, ShenandoahStrDedupQueue* dq) {
244 T o = oopDesc::load_heap_oop(p);
245 if (! oopDesc::is_null(o)) {
246 oop obj = oopDesc::decode_heap_oop_not_null(o);
247 switch (UPDATE_REFS) {
248 case NONE:
249 break;
250 case RESOLVE:
251 obj = ShenandoahBarrierSet::resolve_forwarded_not_null(obj);
252 break;
253 case SIMPLE:
254 // We piggy-back reference updating to the marking tasks.
255 obj = heap->update_with_forwarded_not_null(p, obj);
256 break;
257 case CONCURRENT:
258 obj = heap->maybe_update_with_forwarded_not_null(p, obj);
259 break;
260 default:
261 ShouldNotReachHere();
262 }
263
264 // Note: Only when concurrently updating references can obj become NULL here.
265 // It happens when a mutator thread beats us by writing another value. In that
266 // case we don't need to do anything else.
267 if (UPDATE_REFS != CONCURRENT || !oopDesc::is_null(obj)) {
268 shenandoah_assert_not_forwarded(p, obj);
269 shenandoah_assert_not_in_cset_except(p, obj, heap->cancelled_gc());
270
271 if (mark_context->mark(obj)) {
272 bool pushed = q->push(ShenandoahMarkTask(obj));
273 assert(pushed, "overflow queue should always succeed pushing");
274
275 if (STRING_DEDUP && ShenandoahStringDedup::is_candidate(obj)) {
276 assert(ShenandoahStringDedup::is_enabled(), "Must be enabled");
277 assert(dq != NULL, "Dedup queue not set");
278 ShenandoahStringDedup::enqueue_candidate(obj, dq);
279 }
280 }
281
282 shenandoah_assert_marked_next(p, obj);
283 }
284 }
285 }
286
287 #endif // SHARE_VM_GC_SHENANDOAH_SHENANDOAHCONCURRENTMARK_INLINE_HPP
|