< prev index next >

src/hotspot/share/prims/jvmtiTagMap.cpp

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

@@ -26,10 +26,11 @@
 #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,11 +45,10 @@
 #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"

@@ -1610,141 +1610,25 @@
     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();
+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,10 +1737,12 @@
 // 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,20 +1764,21 @@
 
   // 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 (!ObjectMarker::visited(obj)) visit_stack()->push(obj);
+    if (!_object_marker->visited(obj)) visit_stack()->push(obj);
     return true;
   }
 
   // invoke basic style callbacks
   static inline bool invoke_basic_heap_root_callback

@@ -1957,10 +1844,11 @@
 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,10 +2435,29 @@
   } 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,14 +3097,10 @@
 // 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

@@ -3222,30 +3125,34 @@
 }
 
 void VM_HeapWalkOperation::doit() {
   ResourceMark rm;
   ObjectMarkerController marker;
-  ClassFieldMapCacheMark cm;
+  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
     // 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);
+    object_marker->set_needs_reset(true);
   } else {
     visit_stack()->push(initial_object()());
   }
 
   // object references required

@@ -3253,11 +3160,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 (object_marker->mark(o)) {
         if (!visit(o)) {
           break;
         }
       }
     }
< prev index next >