# HG changeset patch # User zgu # Date 1581946405 18000 # Mon Feb 17 08:33:25 2020 -0500 # Node ID b512362fa39b08a9ef3b6ed1ca4efeadf58e586e # Parent 6308389bdc83442c99cc70b04574a9e39ae290d9 8238633: JVMTI heap walk should consult GC for marking oops diff --git a/src/hotspot/share/gc/shared/collectedHeap.cpp b/src/hotspot/share/gc/shared/collectedHeap.cpp --- a/src/hotspot/share/gc/shared/collectedHeap.cpp +++ b/src/hotspot/share/gc/shared/collectedHeap.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -331,6 +331,9 @@ return MemoryUsage(InitialHeapSize, used(), capacity(), max_capacity()); } +ObjectMarker* CollectedHeap::object_marker() { + return new DefaultObjectMarker(); +} #ifndef PRODUCT void CollectedHeap::check_for_non_bad_heap_word_value(HeapWord* addr, size_t size) { diff --git a/src/hotspot/share/gc/shared/collectedHeap.hpp b/src/hotspot/share/gc/shared/collectedHeap.hpp --- a/src/hotspot/share/gc/shared/collectedHeap.hpp +++ b/src/hotspot/share/gc/shared/collectedHeap.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -27,6 +27,7 @@ #include "gc/shared/gcCause.hpp" #include "gc/shared/gcWhen.hpp" +#include "gc/shared/objectMarker.hpp" #include "gc/shared/verifyOption.hpp" #include "memory/allocation.hpp" #include "runtime/handles.hpp" @@ -383,6 +384,9 @@ virtual GrowableArray memory_managers() = 0; virtual GrowableArray memory_pools() = 0; + // ObjectMarker for JVMTI heap walk + virtual ObjectMarker* object_marker(); + // Iterate over all objects, calling "cl.do_object" on each. virtual void object_iterate(ObjectClosure* cl) = 0; diff --git a/src/hotspot/share/gc/shared/objectMarker.cpp b/src/hotspot/share/gc/shared/objectMarker.cpp new file mode 100644 --- /dev/null +++ b/src/hotspot/share/gc/shared/objectMarker.cpp @@ -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 visited +bool DefaultObjectMarker::visited(oop o) { + return o->mark().is_marked(); +} diff --git a/src/hotspot/share/gc/shared/objectMarker.hpp b/src/hotspot/share/gc/shared/objectMarker.hpp new file mode 100644 --- /dev/null +++ b/src/hotspot/share/gc/shared/objectMarker.hpp @@ -0,0 +1,66 @@ +/* + * 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. + * + */ + +#ifndef SHARE_GC_SHARED_OBJECTMARKER_HPP +#define SHARE_GC_SHARED_OBJECTMARKER_HPP + +#include "memory/allocation.hpp" +#include "oops/markWord.hpp" +#include "utilities/growableArray.hpp" + +// ObjectMarker is used to support JVMTI for marking objects when walking the +// heap. +class ObjectMarker : public CHeapObj { +protected: + bool _needs_reset; +public: + virtual bool init() = 0; // initialize + virtual void done() = 0; // clean-up + + // mark an object if not yet marked. + // return true if the oop is marked by this call + virtual bool mark(oop o) = 0; + virtual bool visited(oop o) = 0; // check if object has been visited + + bool needs_reset() const { return _needs_reset; } + void set_needs_reset(bool v) { _needs_reset = v; } +}; + +// ObjectMarker provides the mark and visited functions +class DefaultObjectMarker : public ObjectMarker { + private: + // saved headers + GrowableArray* _saved_oop_stack; + GrowableArray* _saved_mark_stack; + + public: + DefaultObjectMarker(); + bool init(); + void done(); + + bool mark(oop o); + bool visited(oop o); +}; + +#endif // SHARE_GC_SHARED_OBJECTMARKER_HPP diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp @@ -53,6 +53,7 @@ #include "gc/shenandoah/shenandoahMetrics.hpp" #include "gc/shenandoah/shenandoahMonitoringSupport.hpp" #include "gc/shenandoah/shenandoahNormalMode.hpp" +#include "gc/shenandoah/shenandoahObjectMarker.hpp" #include "gc/shenandoah/shenandoahOopClosures.inline.hpp" #include "gc/shenandoah/shenandoahPacer.inline.hpp" #include "gc/shenandoah/shenandoahParallelCleaning.inline.hpp" @@ -1276,6 +1277,24 @@ // No-op. } +ObjectMarker* ShenandoahHeap::object_marker() { + return new ShenandoahObjectMarker(this, &_aux_bit_map); +} + +bool ShenandoahHeap::commit_aux_bitmap() { + if (!_aux_bitmap_region_special && !os::commit_memory((char*)_aux_bitmap_region.start(), _aux_bitmap_region.byte_size(), false)) { + log_warning(gc)("Could not commit native memory for auxiliary marking bitmap for heap iteration"); + return false; + } + return true; +} + +void ShenandoahHeap::uncommit_aux_bit_map() { + if (!_aux_bitmap_region_special && !os::uncommit_memory((char*)_aux_bitmap_region.start(), _aux_bitmap_region.byte_size())) { + log_warning(gc)("Could not uncommit native memory for auxiliary marking bitmap for heap iteration"); + } +} + /* * Iterates objects in the heap. This is public API, used for, e.g., heap dumping. * @@ -1293,10 +1312,7 @@ */ void ShenandoahHeap::object_iterate(ObjectClosure* cl) { assert(SafepointSynchronize::is_at_safepoint(), "safe iteration is only available during safepoints"); - if (!_aux_bitmap_region_special && !os::commit_memory((char*)_aux_bitmap_region.start(), _aux_bitmap_region.byte_size(), false)) { - log_warning(gc)("Could not commit native memory for auxiliary marking bitmap for heap iteration"); - return; - } + if (!commit_aux_bitmap()) return; // Reset bitmap _aux_bit_map.clear(); @@ -1325,9 +1341,7 @@ assert(oop_stack.is_empty(), "should be empty"); - if (!_aux_bitmap_region_special && !os::uncommit_memory((char*)_aux_bitmap_region.start(), _aux_bitmap_region.byte_size())) { - log_warning(gc)("Could not uncommit native memory for auxiliary marking bitmap for heap iteration"); - } + uncommit_aux_bit_map(); } // Keep alive an object that was loaded with AS_NO_KEEPALIVE. diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp @@ -57,6 +57,7 @@ class ShenandoahConcurrentMark; class ShenandoahMarkCompact; class ShenandoahMonitoringSupport; +class ShenandoahObjectMarker; class ShenandoahPacer; class ShenandoahTraversalGC; class ShenandoahVerifier; @@ -119,6 +120,7 @@ friend class VMStructs; friend class ShenandoahGCSession; friend class ShenandoahGCStateResetter; + friend class ShenandoahObjectMarker; // ---------- Locks that guard important data structures in Heap // @@ -561,6 +563,7 @@ bool block_is_obj(const HeapWord* addr) const; bool print_location(outputStream* st, void* addr) const; + ObjectMarker* object_marker(); // Used for native heap walkers: heap dumpers, mostly void object_iterate(ObjectClosure* cl); @@ -654,6 +657,10 @@ // too many atomic updates. size_t/jint is too large, jbyte is too small. jushort** _liveness_cache; +private: + bool commit_aux_bitmap(); + void uncommit_aux_bit_map(); + public: inline ShenandoahMarkingContext* complete_marking_context() const; inline ShenandoahMarkingContext* marking_context() const; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahObjectMarker.cpp b/src/hotspot/share/gc/shenandoah/shenandoahObjectMarker.cpp new file mode 100644 --- /dev/null +++ b/src/hotspot/share/gc/shenandoah/shenandoahObjectMarker.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2020, Red Hat, Inc. 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/markBitMap.inline.hpp" +#include "gc/shenandoah/shenandoahObjectMarker.hpp" + + bool ShenandoahObjectMarker::init() { + assert(SafepointSynchronize::is_at_safepoint(), "safe iteration is only available during safepoints"); + // Bailout if failed to commit aux bitmap + if (!_heap->commit_aux_bitmap()) { + _bit_map = NULL; + return false; + } + _bit_map->clear(); + return true; + } + + void ShenandoahObjectMarker::done() { + if (_bit_map != NULL) { + _heap->uncommit_aux_bit_map(); + } + delete this; + } + + bool ShenandoahObjectMarker::mark(oop o) { + assert(_bit_map != NULL, "Should have been bailed out"); + if (_bit_map->is_marked(o)) return false; + _bit_map->mark(o); + return true; + } + + bool ShenandoahObjectMarker::visited(oop o) { + assert(_bit_map != NULL, "Should have been bailed out"); + return _bit_map->is_marked(o); + } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahObjectMarker.hpp b/src/hotspot/share/gc/shenandoah/shenandoahObjectMarker.hpp new file mode 100644 --- /dev/null +++ b/src/hotspot/share/gc/shenandoah/shenandoahObjectMarker.hpp @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2020, Red Hat, Inc. 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. + * + */ + +#ifndef SHARE_GC_SHENANDOAH_SHENANDOAHOBJECTMARKER_HPP +#define SHARE_GC_SHENANDOAH_SHENANDOAHOBJECTMARKER_HPP + +#include "gc/shared/markBitMap.hpp" +#include "gc/shared/objectMarker.hpp" +#include "gc/shenandoah/shenandoahHeap.hpp" + +class ShenandoahObjectMarker : public ObjectMarker { +private: + ShenandoahHeap* const _heap; + MarkBitMap* _bit_map; + +public: + ShenandoahObjectMarker(ShenandoahHeap* heap, MarkBitMap* bitmap) : + _heap(heap), _bit_map(bitmap) { + } + + bool init(); + void done(); + + bool mark(oop o); + bool visited(oop o); +}; + +#endif // SHARE_GC_SHENANDOAH_SHENANDOAHOBJECTMARKER_HPP diff --git a/src/hotspot/share/prims/jvmtiTagMap.cpp b/src/hotspot/share/prims/jvmtiTagMap.cpp --- a/src/hotspot/share/prims/jvmtiTagMap.cpp +++ b/src/hotspot/share/prims/jvmtiTagMap.cpp @@ -28,6 +28,7 @@ #include "classfile/symbolTable.hpp" #include "classfile/systemDictionary.hpp" #include "classfile/vmSymbols.hpp" +#include "gc/shared/collectedHeap.hpp" #include "jvmtifiles/jvmtiEnv.hpp" #include "logging/log.hpp" #include "memory/allocation.inline.hpp" @@ -46,7 +47,6 @@ #include "prims/jvmtiExport.hpp" #include "prims/jvmtiImpl.hpp" #include "prims/jvmtiTagMap.hpp" -#include "runtime/biasedLocking.hpp" #include "runtime/frame.inline.hpp" #include "runtime/handles.inline.hpp" #include "runtime/javaCalls.hpp" @@ -1612,137 +1612,21 @@ return collector.result(count_ptr, object_result_ptr, tag_result_ptr); } - -// ObjectMarker is used to support the marking objects when walking the -// heap. -// -// 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(); - } - } - } -}; - -// ObjectMarker provides the mark and visited functions -class ObjectMarker : AllStatic { - private: - // saved headers - static GrowableArray* _saved_oop_stack; - static GrowableArray* _saved_mark_stack; - static bool _needs_reset; // do we need to reset mark bits? - - public: - static void init(); // initialize - static void done(); // clean-up - - static inline void mark(oop o); // mark an object - static inline bool visited(oop o); // check if object has been visited - - static inline bool needs_reset() { return _needs_reset; } - static inline void set_needs_reset(bool v) { _needs_reset = v; } -}; - -GrowableArray* ObjectMarker::_saved_oop_stack = NULL; -GrowableArray* ObjectMarker::_saved_mark_stack = NULL; -bool ObjectMarker::_needs_reset = true; // need to reset mark bits by default - -// initialize ObjectMarker - prepares for object marking -void ObjectMarker::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(); - } -} - -// Object marking is done so restore object headers -void ObjectMarker::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; -} - -// mark an object -inline void ObjectMarker::mark(oop o) { - assert(Universe::heap()->is_in(o), "sanity check"); - assert(!o->mark().is_marked(), "should only mark an object once"); - - // object's mark word - markWord mark = o->mark(); - - 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 if object is marked -inline bool ObjectMarker::visited(oop o) { - return o->mark().is_marked(); -} - // Stack allocated class to help ensure that ObjectMarker is used // correctly. Constructor initializes ObjectMarker, destructor calls // ObjectMarker's done() function to restore object headers. class ObjectMarkerController : public StackObj { - public: - ObjectMarkerController() { - ObjectMarker::init(); - } - ~ObjectMarkerController() { - ObjectMarker::done(); +private: + ObjectMarker* _marker; + +public: + ObjectMarkerController(); + ~ObjectMarkerController(); + + bool init(); + + inline ObjectMarker* object_marker() const { + return _marker; } }; @@ -1855,6 +1739,8 @@ // mode is for the newer FollowReferences function which supports a lot of // additional callbacks. class CallbackInvoker : AllStatic { + friend class ObjectMarkerController; + private: // heap walk styles enum { basic, advanced }; @@ -1880,6 +1766,7 @@ static JvmtiTagMap* _tag_map; static const void* _user_data; static GrowableArray* _visit_stack; + static ObjectMarker* _object_marker; // accessors static JvmtiTagMap* tag_map() { return _tag_map; } @@ -1889,7 +1776,7 @@ // if the object hasn't been visited then push it onto the visit stack // so that it will be visited later static inline bool check_for_visit(oop obj) { - if (!ObjectMarker::visited(obj)) visit_stack()->push(obj); + if (!_object_marker->visited(obj)) visit_stack()->push(obj); return true; } @@ -1959,6 +1846,7 @@ JvmtiTagMap* CallbackInvoker::_tag_map; const void* CallbackInvoker::_user_data; GrowableArray* CallbackInvoker::_visit_stack; +ObjectMarker* CallbackInvoker::_object_marker; // initialize for basic heap walk (IterateOverReachableObjects et al) void CallbackInvoker::initialize_for_basic_heap_walk(JvmtiTagMap* tag_map, @@ -2549,6 +2437,25 @@ } } + +ObjectMarkerController::ObjectMarkerController() { + _marker = Universe::heap()->object_marker(); +} + +bool ObjectMarkerController::init() { + if (_marker->init()) { + CallbackInvoker::_object_marker = _marker; + return true; + } else { + return false; + } +} + +ObjectMarkerController::~ObjectMarkerController() { + CallbackInvoker::_object_marker = NULL; + _marker->done(); +} + // A supporting closure used to process simple roots class SimpleRootsClosure : public OopClosure { private: @@ -3192,10 +3099,6 @@ // the objects referenced by this object). // bool VM_HeapWalkOperation::visit(oop o) { - // mark object as visited - assert(!ObjectMarker::visited(o), "can't visit same object more than once"); - ObjectMarker::mark(o); - // instance if (o->is_instance()) { if (o->klass() == SystemDictionary::Class_klass()) { @@ -3224,16 +3127,20 @@ void VM_HeapWalkOperation::doit() { ResourceMark rm; ObjectMarkerController marker; + if (!marker.init()) { + return; + } + ClassFieldMapCacheMark cm; - assert(visit_stack()->is_empty(), "visit stack must be empty"); + ObjectMarker* const object_marker = marker.object_marker(); // the heap walk starts with an initial object or the heap roots if (initial_object().is_null()) { // If either collect_stack_roots() or collect_simple_roots() // returns false at this point, then there are no mark bits // to reset. - ObjectMarker::set_needs_reset(false); + object_marker->set_needs_reset(false); // Calling collect_stack_roots() before collect_simple_roots() // can result in a big performance boost for an agent that is @@ -3243,7 +3150,7 @@ if (!collect_simple_roots()) return; // no early return so enable heap traversal to reset the mark bits - ObjectMarker::set_needs_reset(true); + object_marker->set_needs_reset(true); } else { visit_stack()->push(initial_object()()); } @@ -3255,7 +3162,7 @@ // visited or the callback asked to terminate the iteration. while (!visit_stack()->is_empty()) { oop o = visit_stack()->pop(); - if (!ObjectMarker::visited(o)) { + if (object_marker->mark(o)) { if (!visit(o)) { break; }