< prev index next >

src/hotspot/share/prims/jvmtiTagMap.cpp

Print this page
rev 58143 : 8238633: JVMTI heap walk should consult GC for marking oops

*** 26,35 **** --- 26,36 ---- #include "classfile/classLoaderDataGraph.hpp" #include "classfile/javaClasses.inline.hpp" #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" #include "memory/resourceArea.hpp" #include "memory/universe.hpp"
*** 44,54 **** #include "prims/jvmtiEventController.hpp" #include "prims/jvmtiEventController.inline.hpp" #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" #include "runtime/jniHandles.inline.hpp" #include "runtime/mutex.hpp" --- 45,54 ----
*** 1610,1750 **** entry_iterate(&collector); } 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<oop>* _saved_oop_stack; - static GrowableArray<markWord>* _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<oop>* ObjectMarker::_saved_oop_stack = NULL; - GrowableArray<markWord>* 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<markWord>(4000, true); - _saved_oop_stack = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<oop>(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(); } }; // helper to map a jvmtiHeapReferenceKind to an old style jvmtiHeapRootKind --- 1610,1634 ---- entry_iterate(&collector); } return collector.result(count_ptr, object_result_ptr, tag_result_ptr); } // 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 { ! private: ! ObjectMarker* _marker; ! ! public: ! ObjectMarkerController(); ! ~ObjectMarkerController(); ! ! bool init(); ! ! inline ObjectMarker* object_marker() const { ! return _marker; } }; // helper to map a jvmtiHeapReferenceKind to an old style jvmtiHeapRootKind
*** 1853,1862 **** --- 1737,1748 ---- // into to invoke callbacks. It works in one of two modes. The "basic" mode is // used for the deprecated IterateOverReachableObjects functions. The "advanced" // 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 }; static int _heap_walk_type; static bool is_basic_heap_walk() { return _heap_walk_type == basic; }
*** 1878,1897 **** // context needed for all heap walks static JvmtiTagMap* _tag_map; static const void* _user_data; static GrowableArray<oop>* _visit_stack; // accessors static JvmtiTagMap* tag_map() { return _tag_map; } static const void* user_data() { return _user_data; } static GrowableArray<oop>* visit_stack() { return _visit_stack; } // 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); return true; } // invoke basic style callbacks static inline bool invoke_basic_heap_root_callback --- 1764,1784 ---- // context needed for all heap walks static JvmtiTagMap* _tag_map; static const void* _user_data; static GrowableArray<oop>* _visit_stack; + static ObjectMarker* _object_marker; // accessors static JvmtiTagMap* tag_map() { return _tag_map; } static const void* user_data() { return _user_data; } static GrowableArray<oop>* visit_stack() { return _visit_stack; } // 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 (!_object_marker->marked(obj)) visit_stack()->push(obj); return true; } // invoke basic style callbacks static inline bool invoke_basic_heap_root_callback
*** 1957,1966 **** --- 1844,1854 ---- BasicHeapWalkContext CallbackInvoker::_basic_context; AdvancedHeapWalkContext CallbackInvoker::_advanced_context; JvmtiTagMap* CallbackInvoker::_tag_map; const void* CallbackInvoker::_user_data; GrowableArray<oop>* 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, GrowableArray<oop>* visit_stack, const void* user_data,
*** 2547,2556 **** --- 2435,2463 ---- } else { return invoke_advanced_object_reference_callback(JVMTI_HEAP_REFERENCE_CONSTANT_POOL, referrer, referree, index); } } + + 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: jvmtiHeapReferenceKind _kind; bool _continue;
*** 3190,3203 **** // first mark the object as visited // second get all the outbound references from this object (in other words, all // 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()) { if (!java_lang_Class::is_primitive(o)) { // a java.lang.Class --- 3097,3106 ----
*** 3222,3251 **** } void VM_HeapWalkOperation::doit() { ResourceMark rm; ObjectMarkerController marker; ! ClassFieldMapCacheMark cm; assert(visit_stack()->is_empty(), "visit stack must be empty"); // 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); // Calling collect_stack_roots() before collect_simple_roots() // can result in a big performance boost for an agent that is // focused on analyzing references in the thread stacks. if (!collect_stack_roots()) return; if (!collect_simple_roots()) return; // no early return so enable heap traversal to reset the mark bits ! ObjectMarker::set_needs_reset(true); } else { visit_stack()->push(initial_object()()); } // object references required --- 3125,3158 ---- } 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. ! 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 // focused on analyzing references in the thread stacks. if (!collect_stack_roots()) return; if (!collect_simple_roots()) return; // no early return so enable heap traversal to reset the mark bits ! object_marker->set_needs_reset(true); } else { visit_stack()->push(initial_object()()); } // object references required
*** 3253,3263 **** // visit each object until all reachable objects have been // visited or the callback asked to terminate the iteration. while (!visit_stack()->is_empty()) { oop o = visit_stack()->pop(); ! if (!ObjectMarker::visited(o)) { if (!visit(o)) { break; } } } --- 3160,3170 ---- // visit each object until all reachable objects have been // visited or the callback asked to terminate the iteration. while (!visit_stack()->is_empty()) { oop o = visit_stack()->pop(); ! if (object_marker->mark(o)) { if (!visit(o)) { break; } } }
< prev index next >