< prev index next >

src/share/vm/classfile/metadataOnStackMark.cpp

Print this page
rev 6875 : 8056240: Investigate increased GC remark time after class unloading changes in CRM Fuse
Reviewed-by: mgerdin, coleenp, bdelsart


  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #include "precompiled.hpp"
  26 #include "classfile/metadataOnStackMark.hpp"
  27 #include "code/codeCache.hpp"
  28 #include "compiler/compileBroker.hpp"
  29 #include "oops/metadata.hpp"
  30 #include "prims/jvmtiImpl.hpp"
  31 #include "runtime/synchronizer.hpp"
  32 #include "runtime/thread.hpp"
  33 #include "services/threadService.hpp"
  34 #include "utilities/growableArray.hpp"
  35 


  36 
  37 // Keep track of marked on-stack metadata so it can be cleared.
  38 GrowableArray<Metadata*>* _marked_objects = NULL;
  39 NOT_PRODUCT(bool MetadataOnStackMark::_is_active = false;)
  40 
  41 // Walk metadata on the stack and mark it so that redefinition doesn't delete
  42 // it.  Class unloading also walks the previous versions and might try to
  43 // delete it, so this class is used by class unloading also.
  44 MetadataOnStackMark::MetadataOnStackMark() {
  45   assert(SafepointSynchronize::is_at_safepoint(), "sanity check");

  46   NOT_PRODUCT(_is_active = true;)
  47   if (_marked_objects == NULL) {
  48     _marked_objects = new (ResourceObj::C_HEAP, mtClass) GrowableArray<Metadata*>(1000, true);
  49   }
  50 
  51   Threads::metadata_do(Metadata::mark_on_stack);
  52   if (JvmtiExport::has_redefined_a_class()) {
  53     CodeCache::alive_nmethods_do(nmethod::mark_on_stack);
  54   }
  55   CompileBroker::mark_on_stack();
  56   JvmtiCurrentBreakpoints::metadata_do(Metadata::mark_on_stack);
  57   ThreadService::metadata_do(Metadata::mark_on_stack);
  58 }
  59 
  60 MetadataOnStackMark::~MetadataOnStackMark() {
  61   assert(SafepointSynchronize::is_at_safepoint(), "sanity check");
  62   // Unmark everything that was marked.   Can't do the same walk because
  63   // redefine classes messes up the code cache so the set of methods
  64   // might not be the same.
  65   for (int i = 0; i< _marked_objects->length(); i++) {
  66     _marked_objects->at(i)->set_on_stack(false);




















  67   }
  68   _marked_objects->clear();   // reuse growable array for next time.


  69   NOT_PRODUCT(_is_active = false;)
  70 }
  71 











































  72 // Record which objects are marked so we can unmark the same objects.
  73 void MetadataOnStackMark::record(Metadata* m) {
  74   assert(_is_active, "metadata on stack marking is active");
  75   _marked_objects->push(m);













  76 }


  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #include "precompiled.hpp"
  26 #include "classfile/metadataOnStackMark.hpp"
  27 #include "code/codeCache.hpp"
  28 #include "compiler/compileBroker.hpp"
  29 #include "oops/metadata.hpp"
  30 #include "prims/jvmtiImpl.hpp"
  31 #include "runtime/synchronizer.hpp"
  32 #include "runtime/thread.hpp"
  33 #include "services/threadService.hpp"
  34 #include "utilities/chunkedList.hpp"
  35 
  36 volatile MetadataOnStackBuffer* MetadataOnStackMark::_used_buffers = NULL;
  37 volatile MetadataOnStackBuffer* MetadataOnStackMark::_free_buffers = NULL;
  38 


  39 NOT_PRODUCT(bool MetadataOnStackMark::_is_active = false;)
  40 
  41 // Walk metadata on the stack and mark it so that redefinition doesn't delete
  42 // it.  Class unloading also walks the previous versions and might try to
  43 // delete it, so this class is used by class unloading also.
  44 MetadataOnStackMark::MetadataOnStackMark(bool visit_code_cache) {
  45   assert(SafepointSynchronize::is_at_safepoint(), "sanity check");
  46   assert(_used_buffers == NULL, "sanity check");
  47   NOT_PRODUCT(_is_active = true;)



  48 
  49   Threads::metadata_do(Metadata::mark_on_stack);
  50   if (visit_code_cache) {
  51     CodeCache::alive_nmethods_do(nmethod::mark_on_stack);
  52   }
  53   CompileBroker::mark_on_stack();
  54   JvmtiCurrentBreakpoints::metadata_do(Metadata::mark_on_stack);
  55   ThreadService::metadata_do(Metadata::mark_on_stack);
  56 }
  57 
  58 MetadataOnStackMark::~MetadataOnStackMark() {
  59   assert(SafepointSynchronize::is_at_safepoint(), "sanity check");
  60   // Unmark everything that was marked.   Can't do the same walk because
  61   // redefine classes messes up the code cache so the set of methods
  62   // might not be the same.
  63 
  64   retire_buffer_for_thread(Thread::current());
  65 
  66   MetadataOnStackBuffer* buffer = const_cast<MetadataOnStackBuffer* >(_used_buffers);
  67   while (buffer != NULL) {
  68     // Clear on stack state for all metadata.
  69     size_t size = buffer->size();
  70     for (size_t i  = 0; i < size; i++) {
  71       Metadata* md = buffer->at(i);
  72       md->set_on_stack(false);
  73     }
  74 
  75     MetadataOnStackBuffer* next = buffer->next_used();
  76 
  77     // Move the buffer to the free list.
  78     buffer->clear();
  79     buffer->set_next_used(NULL);
  80     buffer->set_next_free(const_cast<MetadataOnStackBuffer*>(_free_buffers));
  81     _free_buffers = buffer;
  82 
  83     // Step to next used buffer.
  84     buffer = next;
  85   }
  86 
  87   _used_buffers = NULL;
  88 
  89   NOT_PRODUCT(_is_active = false;)
  90 }
  91 
  92 void MetadataOnStackMark::retire_buffer(MetadataOnStackBuffer* buffer) {
  93   if (buffer == NULL) {
  94     return;
  95   }
  96 
  97   MetadataOnStackBuffer* old_head;
  98 
  99   do {
 100     old_head = const_cast<MetadataOnStackBuffer*>(_used_buffers);
 101     buffer->set_next_used(old_head);
 102   } while (Atomic::cmpxchg_ptr(buffer, &_used_buffers, old_head) != old_head);
 103 }
 104 
 105 void MetadataOnStackMark::retire_buffer_for_thread(Thread* thread) {
 106   retire_buffer(thread->metadata_on_stack_buffer());
 107   thread->set_metadata_on_stack_buffer(NULL);
 108 }
 109 
 110 bool MetadataOnStackMark::has_buffer_for_thread(Thread* thread) {
 111   return thread->metadata_on_stack_buffer() != NULL;
 112 }
 113 
 114 MetadataOnStackBuffer* MetadataOnStackMark::allocate_buffer() {
 115   MetadataOnStackBuffer* allocated;
 116   MetadataOnStackBuffer* new_head;
 117 
 118   do {
 119     allocated = const_cast<MetadataOnStackBuffer*>(_free_buffers);
 120     if (allocated == NULL) {
 121       break;
 122     }
 123     new_head = allocated->next_free();
 124   } while (Atomic::cmpxchg_ptr(new_head, &_free_buffers, allocated) != allocated);
 125 
 126   if (allocated == NULL) {
 127     allocated = new MetadataOnStackBuffer();
 128   }
 129 
 130   assert(!allocated->is_full(), err_msg("Should not be full: " PTR_FORMAT, p2i(allocated)));
 131 
 132   return allocated;
 133 }
 134 
 135 // Record which objects are marked so we can unmark the same objects.
 136 void MetadataOnStackMark::record(Metadata* m, Thread* thread) {
 137   assert(_is_active, "metadata on stack marking is active");
 138 
 139   MetadataOnStackBuffer* buffer =  thread->metadata_on_stack_buffer();
 140 
 141   if (buffer != NULL && buffer->is_full()) {
 142     retire_buffer(buffer);
 143     buffer = NULL;
 144   }
 145 
 146   if (buffer == NULL) {
 147     buffer = allocate_buffer();
 148     thread->set_metadata_on_stack_buffer(buffer);
 149   }
 150 
 151   buffer->push(m);
 152 }
< prev index next >