/* * 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 visited bool DefaultObjectMarker::visited(oop o) { return o->mark().is_marked(); }