--- /dev/null 2020-01-14 10:13:11.907818291 +0100 +++ new/src/hotspot/share/gc/shared/objectMarker.cpp 2020-02-21 11:14:40.152195526 +0100 @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * 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. + * + */ + +#include "precompiled.hpp" + +#include "gc/shared/objectMarker.hpp" +#include "memory/iterator.hpp" +#include "oops/oop.inline.hpp" +#include "runtime/biasedLocking.hpp" + +// This implementation uses the existing mark bits in an object for +// marking. Objects that are marked must later have their headers restored. +// As most objects are unlocked and don't have their identity hash computed +// we don't have to save their headers. Instead we save the headers that +// are "interesting". Later when the headers are restored this implementation +// restores all headers to their initial value and then restores the few +// objects that had interesting headers. +// +// Future work: This implementation currently uses growable arrays to save +// the oop and header of interesting objects. As an optimization we could +// use the same technique as the GC and make use of the unused area +// between top() and end(). +// + +// An ObjectClosure used to restore the mark bits of an object +class RestoreMarksClosure : public ObjectClosure { + public: + void do_object(oop o) { + if (o != NULL) { + markWord mark = o->mark(); + if (mark.is_marked()) { + o->init_mark(); + } + } + } +}; + +DefaultObjectMarker::DefaultObjectMarker() : + _saved_oop_stack(NULL), + _saved_mark_stack(NULL) { + set_needs_reset(true); +} + +// initialize ObjectMarker - prepares for object marking +bool DefaultObjectMarker::init() { + assert(Thread::current()->is_VM_thread(), "must be VMThread"); + + // prepare heap for iteration + Universe::heap()->ensure_parsability(false); // no need to retire TLABs + + // create stacks for interesting headers + _saved_mark_stack = new (ResourceObj::C_HEAP, mtInternal) GrowableArray(4000, true); + _saved_oop_stack = new (ResourceObj::C_HEAP, mtInternal) GrowableArray(4000, true); + + if (UseBiasedLocking) { + BiasedLocking::preserve_marks(); + } + + return true; +} + +// Object marking is done so restore object headers +void DefaultObjectMarker::done() { + // iterate over all objects and restore the mark bits to + // their initial value + RestoreMarksClosure blk; + if (needs_reset()) { + Universe::heap()->object_iterate(&blk); + } else { + // We don't need to reset mark bits on this call, but reset the + // flag to the default for the next call. + set_needs_reset(true); + } + + // now restore the interesting headers + for (int i = 0; i < _saved_oop_stack->length(); i++) { + oop o = _saved_oop_stack->at(i); + markWord mark = _saved_mark_stack->at(i); + o->set_mark(mark); + } + + if (UseBiasedLocking) { + BiasedLocking::restore_marks(); + } + + // free the stacks + delete _saved_oop_stack; + delete _saved_mark_stack; + + delete this; +} + +// mark an object +bool DefaultObjectMarker::mark(oop o) { + assert(Universe::heap()->is_in(o), "sanity check"); + + // object's mark word + markWord mark = o->mark(); + if (mark.is_marked()) { + return false; + } + + if (o->mark_must_be_preserved(mark)) { + _saved_mark_stack->push(mark); + _saved_oop_stack->push(o); + } + + // mark the object + o->set_mark(markWord::prototype().set_marked()); + return true; +} + +// return true if object is marked +bool DefaultObjectMarker::marked(oop o) { + return o->mark().is_marked(); +}