--- /dev/null 2015-10-06 23:29:51.451421828 +0200 +++ new/src/share/vm/gc/shenandoah/shenandoahConcurrentMark.inline.hpp 2015-10-14 13:54:48.764054141 +0200 @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2015, Red Hat, Inc. and/or its affiliates. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_GC_SHENANDOAH_SHENANDOAHCONCURRENTMARK_INLINE_HPP +#define SHARE_VM_GC_SHENANDOAH_SHENANDOAHCONCURRENTMARK_INLINE_HPP + +#include "gc/shenandoah/brooksPointer.hpp" +#include "gc/shenandoah/shenandoahConcurrentMark.hpp" +#include "memory/iterator.inline.hpp" +#include "oops/oop.inline.hpp" +#include "runtime/prefetch.inline.hpp" + +void ShenandoahMarkRefsClosure::do_oop(oop* p) { + // We piggy-back reference updating to the marking tasks. +#ifdef ASSERT + oop* old = p; +#endif + oop obj; + if (_update_refs) { + obj = _heap->maybe_update_oop_ref(p); + } else { + obj = oopDesc::load_heap_oop(p); + } + assert(obj == ShenandoahBarrierSet::resolve_oop_static(obj), "need to-space object here"); + +#ifdef ASSERT + if (ShenandoahTraceUpdates) { + if (p != old) + tty->print_cr("Update "PTR_FORMAT" => "PTR_FORMAT" to "PTR_FORMAT" => "PTR_FORMAT, p2i(p), p2i((HeapWord*) *p), p2i(old), p2i((HeapWord*) *old)); + else + tty->print_cr("Not updating "PTR_FORMAT" => "PTR_FORMAT" to "PTR_FORMAT" => "PTR_FORMAT, p2i(p), p2i((HeapWord*) *p), p2i(old), p2i((HeapWord*) *old)); + } +#endif + + // NOTE: We used to assert the following here. This does not always work because + // a concurrent Java thread could change the the field after we updated it. + // oop obj = oopDesc::load_heap_oop(p); + // assert(oopDesc::bs()->resolve_oop(obj) == *p, "we just updated the referrer"); + // assert(obj == NULL || ! _heap->heap_region_containing(obj)->is_dirty(), "must not point to dirty region"); + + // ShenandoahExtendedMarkObjsClosure cl(_heap->ref_processor(), _worker_id); + // ShenandoahMarkObjsClosure mocl(cl, _worker_id); + + if (obj != NULL) { + if (_update_refs) { + Prefetch::write(obj, 128); + } else { + Prefetch::read(obj, 128); + } + +#ifdef ASSERT + uint region_idx = _heap->heap_region_index_containing(obj); + ShenandoahHeapRegion* r = _heap->heap_regions()[region_idx]; + assert(r->bottom() < (HeapWord*) obj && r->top() > (HeapWord*) obj, "object must be in region"); +#endif + if (_heap->mark_current(obj)) { + if (ShenandoahTraceConcurrentMarking) { + tty->print_cr("marked obj: "PTR_FORMAT, p2i((HeapWord*) obj)); + } + bool pushed = _queue->push(obj); + assert(pushed, "overflow queue should always succeed pushing"); + } +#ifdef ASSERT + else { + if (ShenandoahTraceConcurrentMarking) { + tty->print_cr("failed to mark obj (already marked): "PTR_FORMAT, p2i((HeapWord*) obj)); + } + assert(_heap->is_marked_current(obj), "make sure object is marked"); + } +#endif + } +} + +void ShenandoahMarkObjsClosure::do_object(oop obj) { + + assert(obj != NULL, "expect non-null object"); + + assert(obj == ShenandoahBarrierSet::resolve_oop_static_not_null(obj), "expect forwarded obj in queue"); + +#ifdef ASSERT + if (_heap->heap_region_containing(obj)->is_in_collection_set()) { + tty->print_cr("trying to mark obj: "PTR_FORMAT" (%s) in dirty region: ", p2i((HeapWord*) obj), BOOL_TO_STR(_heap->is_marked_current(obj))); + // _heap->heap_region_containing(obj)->print(); + // _heap->print_heap_regions(); + } +#endif + assert(_heap->cancelled_concgc() + || ! _heap->heap_region_containing(obj)->is_in_collection_set(), + "we don't want to mark objects in from-space"); + assert(_heap->is_in(obj), "referenced objects must be in the heap. No?"); + assert(_heap->is_marked_current(obj), "only marked objects on task queue"); + + // Calculate liveness of heap region containing object. + uint region_idx = _heap->heap_region_index_containing(obj); +#ifdef ASSERT + ShenandoahHeapRegion* r = _heap->heap_regions()[region_idx]; + assert(r->bottom() < (HeapWord*) obj && r->top() > (HeapWord*) obj, "object must be in region"); +#endif + _live_data[region_idx] += (obj->size() + BrooksPointer::BROOKS_POINTER_OBJ_SIZE) * HeapWordSize; + obj->oop_iterate(&_mark_refs); + +} + +inline bool ShenandoahConcurrentMark::try_queue(SCMObjToScanQueue* q, ShenandoahMarkObjsClosure* cl) { + oop obj; + if (q->pop_local(obj)) { + assert(obj != NULL, "Can't mark null"); + cl->do_object(obj); + return true; + } else if (q->pop_overflow(obj)) { + cl->do_object(obj); + return true; + } else { + return false; + } +} + +inline bool ShenandoahConcurrentMark::try_to_steal(uint worker_id, ShenandoahMarkObjsClosure* cl, int *seed) { + oop obj; + if (task_queues()->steal(worker_id, seed, obj)) { + cl->do_object(obj); + return true; + } else + return false; +} + +inline bool ShenandoahConcurrentMark:: try_draining_an_satb_buffer(uint worker_id) { + return drain_one_satb_buffer(worker_id); +} + +#endif // SHARE_VM_GC_SHENANDOAH_SHENANDOAHCONCURRENTMARK_INLINE_HPP