< prev index next >

src/hotspot/share/prims/jvmtiTagMap.cpp

Print this page
*** 64,12 ***
--- 64,15 ---
  #include "runtime/thread.inline.hpp"
  #include "runtime/threadSMR.hpp"
  #include "runtime/vframe.hpp"
  #include "runtime/vmThread.hpp"
  #include "runtime/vmOperations.hpp"
+ #include "utilities/objectBitSet.inline.hpp"
  #include "utilities/macros.hpp"
  
+ typedef ObjectBitSet<mtServiceability> JVMTIBitSet;
+ 
  bool JvmtiTagMap::_has_object_free_events = false;
  
  // create a JvmtiTagMap
  JvmtiTagMap::JvmtiTagMap(JvmtiEnv* env) :
    _env(env),

*** 1351,146 ***
      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");
-   assert(SafepointSynchronize::is_at_safepoint(), "must be at a safepoint");
- 
-   // 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, mtServiceability) GrowableArray<markWord>(4000, mtServiceability);
-   _saved_oop_stack = new (ResourceObj::C_HEAP, mtServiceability) GrowableArray<oop>(4000, mtServiceability);
- 
-   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
  // (not performance critical as only used for roots)
  static jvmtiHeapRootKind toJvmtiHeapRootKind(jvmtiHeapReferenceKind kind) {
    switch (kind) {
      case JVMTI_HEAP_REFERENCE_JNI_GLOBAL:   return JVMTI_HEAP_ROOT_JNI_GLOBAL;
--- 1354,10 ---

*** 1619,20 ***
  
    // 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
--- 1486,21 ---
  
    // context needed for all heap walks
    static JvmtiTagMap* _tag_map;
    static const void* _user_data;
    static GrowableArray<oop>* _visit_stack;
+   static JVMTIBitSet* _bitset;
  
    // 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 (!_bitset->is_marked(obj)) visit_stack()->push(obj);
      return true;
    }
  
    // invoke basic style callbacks
    static inline bool invoke_basic_heap_root_callback

*** 1659,17 ***
   public:
    // initialize for basic mode
    static void initialize_for_basic_heap_walk(JvmtiTagMap* tag_map,
                                               GrowableArray<oop>* visit_stack,
                                               const void* user_data,
!                                              BasicHeapWalkContext context);
  
    // initialize for advanced mode
    static void initialize_for_advanced_heap_walk(JvmtiTagMap* tag_map,
                                                  GrowableArray<oop>* visit_stack,
                                                  const void* user_data,
!                                                 AdvancedHeapWalkContext context);
  
     // functions to report roots
    static inline bool report_simple_root(jvmtiHeapReferenceKind kind, oop o);
    static inline bool report_jni_local_root(jlong thread_tag, jlong tid, jint depth,
      jmethodID m, oop o);
--- 1527,19 ---
   public:
    // initialize for basic mode
    static void initialize_for_basic_heap_walk(JvmtiTagMap* tag_map,
                                               GrowableArray<oop>* visit_stack,
                                               const void* user_data,
!                                              BasicHeapWalkContext context,
+                                              JVMTIBitSet* bitset);
  
    // initialize for advanced mode
    static void initialize_for_advanced_heap_walk(JvmtiTagMap* tag_map,
                                                  GrowableArray<oop>* visit_stack,
                                                  const void* user_data,
!                                                 AdvancedHeapWalkContext context,
+                                                 JVMTIBitSet* bitset);
  
     // functions to report roots
    static inline bool report_simple_root(jvmtiHeapReferenceKind kind, oop o);
    static inline bool report_jni_local_root(jlong thread_tag, jlong tid, jint depth,
      jmethodID m, oop o);

*** 1698,35 ***
  BasicHeapWalkContext CallbackInvoker::_basic_context;
  AdvancedHeapWalkContext CallbackInvoker::_advanced_context;
  JvmtiTagMap* CallbackInvoker::_tag_map;
  const void* CallbackInvoker::_user_data;
  GrowableArray<oop>* CallbackInvoker::_visit_stack;
  
  // 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,
!                                                      BasicHeapWalkContext context) {
    _tag_map = tag_map;
    _visit_stack = visit_stack;
    _user_data = user_data;
    _basic_context = context;
    _advanced_context.invalidate();       // will trigger assertion if used
    _heap_walk_type = basic;
  }
  
  // initialize for advanced heap walk (FollowReferences)
  void CallbackInvoker::initialize_for_advanced_heap_walk(JvmtiTagMap* tag_map,
                                                          GrowableArray<oop>* visit_stack,
                                                          const void* user_data,
!                                                         AdvancedHeapWalkContext context) {
    _tag_map = tag_map;
    _visit_stack = visit_stack;
    _user_data = user_data;
    _advanced_context = context;
    _basic_context.invalidate();      // will trigger assertion if used
    _heap_walk_type = advanced;
  }
  
  
  // invoke basic style heap root callback
  inline bool CallbackInvoker::invoke_basic_heap_root_callback(jvmtiHeapRootKind root_kind, oop obj) {
--- 1568,40 ---
  BasicHeapWalkContext CallbackInvoker::_basic_context;
  AdvancedHeapWalkContext CallbackInvoker::_advanced_context;
  JvmtiTagMap* CallbackInvoker::_tag_map;
  const void* CallbackInvoker::_user_data;
  GrowableArray<oop>* CallbackInvoker::_visit_stack;
+ JVMTIBitSet* CallbackInvoker::_bitset;
  
  // 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,
!                                                      BasicHeapWalkContext context,
+                                                      JVMTIBitSet* bitset) {
    _tag_map = tag_map;
    _visit_stack = visit_stack;
    _user_data = user_data;
    _basic_context = context;
    _advanced_context.invalidate();       // will trigger assertion if used
    _heap_walk_type = basic;
+   _bitset = bitset;
  }
  
  // initialize for advanced heap walk (FollowReferences)
  void CallbackInvoker::initialize_for_advanced_heap_walk(JvmtiTagMap* tag_map,
                                                          GrowableArray<oop>* visit_stack,
                                                          const void* user_data,
!                                                         AdvancedHeapWalkContext context,
+                                                         JVMTIBitSet* bitset) {
    _tag_map = tag_map;
    _visit_stack = visit_stack;
    _user_data = user_data;
    _advanced_context = context;
    _basic_context.invalidate();      // will trigger assertion if used
    _heap_walk_type = advanced;
+   _bitset = bitset;
  }
  
  
  // invoke basic style heap root callback
  inline bool CallbackInvoker::invoke_basic_heap_root_callback(jvmtiHeapRootKind root_kind, oop obj) {

*** 2394,10 ***
--- 2269,12 ---
    bool _is_advanced_heap_walk;                      // indicates FollowReferences
    JvmtiTagMap* _tag_map;
    Handle _initial_object;
    GrowableArray<oop>* _visit_stack;                 // the visit stack
  
+   JVMTIBitSet _bitset;
+ 
    // Dead object tags in JvmtiTagMap
    GrowableArray<jlong>* _dead_objects;
  
    bool _following_object_refs;                      // are we following object references
  

*** 2470,11 ***
    _reporting_string_values = false;
    _visit_stack = create_visit_stack();
    _dead_objects = objects;
  
  
!   CallbackInvoker::initialize_for_basic_heap_walk(tag_map, _visit_stack, user_data, callbacks);
  }
  
  VM_HeapWalkOperation::VM_HeapWalkOperation(JvmtiTagMap* tag_map,
                                             Handle initial_object,
                                             AdvancedHeapWalkContext callbacks,
--- 2347,11 ---
    _reporting_string_values = false;
    _visit_stack = create_visit_stack();
    _dead_objects = objects;
  
  
!   CallbackInvoker::initialize_for_basic_heap_walk(tag_map, _visit_stack, user_data, callbacks, &_bitset);
  }
  
  VM_HeapWalkOperation::VM_HeapWalkOperation(JvmtiTagMap* tag_map,
                                             Handle initial_object,
                                             AdvancedHeapWalkContext callbacks,

*** 2488,11 ***
    _reporting_primitive_array_values = (callbacks.array_primitive_value_callback() != NULL);;
    _reporting_string_values = (callbacks.string_primitive_value_callback() != NULL);;
    _visit_stack = create_visit_stack();
    _dead_objects = objects;
  
!   CallbackInvoker::initialize_for_advanced_heap_walk(tag_map, _visit_stack, user_data, callbacks);
  }
  
  VM_HeapWalkOperation::~VM_HeapWalkOperation() {
    if (_following_object_refs) {
      assert(_visit_stack != NULL, "checking");
--- 2365,11 ---
    _reporting_primitive_array_values = (callbacks.array_primitive_value_callback() != NULL);;
    _reporting_string_values = (callbacks.string_primitive_value_callback() != NULL);;
    _visit_stack = create_visit_stack();
    _dead_objects = objects;
  
!   CallbackInvoker::initialize_for_advanced_heap_walk(tag_map, _visit_stack, user_data, callbacks, &_bitset);
  }
  
  VM_HeapWalkOperation::~VM_HeapWalkOperation() {
    if (_following_object_refs) {
      assert(_visit_stack != NULL, "checking");

*** 2924,12 ***
  // 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() == vmClasses::Class_klass()) {
        if (!java_lang_Class::is_primitive(o)) {
--- 2801,12 ---
  // 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(!_bitset.is_marked(o), "can't visit same object more than once");
!   _bitset.mark_obj(o);
  
    // instance
    if (o->is_instance()) {
      if (o->klass() == vmClasses::Class_klass()) {
        if (!java_lang_Class::is_primitive(o)) {

*** 2954,33 ***
    return true;
  }
  
  void VM_HeapWalkOperation::doit() {
    ResourceMark rm;
-   ObjectMarkerController marker;
    ClassFieldMapCacheMark cm;
  
    JvmtiTagMap::check_hashmaps_for_heapwalk(_dead_objects);
  
    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
--- 2831,23 ---

*** 2988,11 ***
  
      // 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;
          }
        }
      }
--- 2855,11 ---
  
      // 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 (!_bitset.is_marked(o)) {
          if (!visit(o)) {
            break;
          }
        }
      }
< prev index next >