hotspot/src/share/vm/classfile/metadataOnStackMark.cpp
changeset 29576 c223b0a9872e
parent 27247 99db666dbe8e
child 33160 c59f1676d27e
child 33105 294e48b4f704
equal deleted inserted replaced
29574:ab0121071f54 29576:c223b0a9872e
     1 /*
     1 /*
     2  * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     7  * published by the Free Software Foundation.
    31 #include "runtime/synchronizer.hpp"
    31 #include "runtime/synchronizer.hpp"
    32 #include "runtime/thread.hpp"
    32 #include "runtime/thread.hpp"
    33 #include "services/threadService.hpp"
    33 #include "services/threadService.hpp"
    34 #include "utilities/chunkedList.hpp"
    34 #include "utilities/chunkedList.hpp"
    35 
    35 
    36 volatile MetadataOnStackBuffer* MetadataOnStackMark::_used_buffers = NULL;
    36 MetadataOnStackBuffer* MetadataOnStackMark::_used_buffers = NULL;
    37 volatile MetadataOnStackBuffer* MetadataOnStackMark::_free_buffers = NULL;
    37 MetadataOnStackBuffer* MetadataOnStackMark::_free_buffers = NULL;
    38 
    38 
       
    39 MetadataOnStackBuffer* MetadataOnStackMark::_current_buffer = NULL;
    39 NOT_PRODUCT(bool MetadataOnStackMark::_is_active = false;)
    40 NOT_PRODUCT(bool MetadataOnStackMark::_is_active = false;)
    40 
    41 
    41 // Walk metadata on the stack and mark it so that redefinition doesn't delete
    42 // 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 // it.  Class unloading only deletes in-error class files, methods created by
    43 // delete it, so this class is used by class unloading also.
    44 // the relocator and dummy constant pools.  None of these appear anywhere except
    44 MetadataOnStackMark::MetadataOnStackMark(bool visit_code_cache) {
    45 // in metadata Handles.
       
    46 MetadataOnStackMark::MetadataOnStackMark(bool redefinition_walk) {
    45   assert(SafepointSynchronize::is_at_safepoint(), "sanity check");
    47   assert(SafepointSynchronize::is_at_safepoint(), "sanity check");
    46   assert(_used_buffers == NULL, "sanity check");
    48   assert(_used_buffers == NULL, "sanity check");
       
    49   assert(!_is_active, "MetadataOnStackMarks do not nest");
    47   NOT_PRODUCT(_is_active = true;)
    50   NOT_PRODUCT(_is_active = true;)
    48 
    51 
    49   Threads::metadata_do(Metadata::mark_on_stack);
    52   Threads::metadata_handles_do(Metadata::mark_on_stack);
    50   if (visit_code_cache) {
    53 
       
    54   if (redefinition_walk) {
       
    55     Threads::metadata_do(Metadata::mark_on_stack);
    51     CodeCache::alive_nmethods_do(nmethod::mark_on_stack);
    56     CodeCache::alive_nmethods_do(nmethod::mark_on_stack);
       
    57     CompileBroker::mark_on_stack();
       
    58     JvmtiCurrentBreakpoints::metadata_do(Metadata::mark_on_stack);
       
    59     ThreadService::metadata_do(Metadata::mark_on_stack);
    52   }
    60   }
    53   CompileBroker::mark_on_stack();
       
    54   JvmtiCurrentBreakpoints::metadata_do(Metadata::mark_on_stack);
       
    55   ThreadService::metadata_do(Metadata::mark_on_stack);
       
    56 }
    61 }
    57 
    62 
    58 MetadataOnStackMark::~MetadataOnStackMark() {
    63 MetadataOnStackMark::~MetadataOnStackMark() {
    59   assert(SafepointSynchronize::is_at_safepoint(), "sanity check");
    64   assert(SafepointSynchronize::is_at_safepoint(), "sanity check");
    60   // Unmark everything that was marked.   Can't do the same walk because
    65   // 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
    66   // redefine classes messes up the code cache so the set of methods
    62   // might not be the same.
    67   // might not be the same.
       
    68   retire_current_buffer();
    63 
    69 
    64   retire_buffer_for_thread(Thread::current());
    70   MetadataOnStackBuffer* buffer = _used_buffers;
    65 
       
    66   MetadataOnStackBuffer* buffer = const_cast<MetadataOnStackBuffer* >(_used_buffers);
       
    67   while (buffer != NULL) {
    71   while (buffer != NULL) {
    68     // Clear on stack state for all metadata.
    72     // Clear on stack state for all metadata.
    69     size_t size = buffer->size();
    73     size_t size = buffer->size();
    70     for (size_t i  = 0; i < size; i++) {
    74     for (size_t i  = 0; i < size; i++) {
    71       Metadata* md = buffer->at(i);
    75       Metadata* md = buffer->at(i);
    75     MetadataOnStackBuffer* next = buffer->next_used();
    79     MetadataOnStackBuffer* next = buffer->next_used();
    76 
    80 
    77     // Move the buffer to the free list.
    81     // Move the buffer to the free list.
    78     buffer->clear();
    82     buffer->clear();
    79     buffer->set_next_used(NULL);
    83     buffer->set_next_used(NULL);
    80     buffer->set_next_free(const_cast<MetadataOnStackBuffer*>(_free_buffers));
    84     buffer->set_next_free(_free_buffers);
    81     _free_buffers = buffer;
    85     _free_buffers = buffer;
    82 
    86 
    83     // Step to next used buffer.
    87     // Step to next used buffer.
    84     buffer = next;
    88     buffer = next;
    85   }
    89   }
    91 
    95 
    92 void MetadataOnStackMark::retire_buffer(MetadataOnStackBuffer* buffer) {
    96 void MetadataOnStackMark::retire_buffer(MetadataOnStackBuffer* buffer) {
    93   if (buffer == NULL) {
    97   if (buffer == NULL) {
    94     return;
    98     return;
    95   }
    99   }
    96 
   100   buffer->set_next_used(_used_buffers);
    97   MetadataOnStackBuffer* old_head;
   101   _used_buffers = buffer;
    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 }
   102 }
   104 
   103 
   105 void MetadataOnStackMark::retire_buffer_for_thread(Thread* thread) {
   104 // Current buffer is full or we're ready to walk them, add it to the used list.
   106   retire_buffer(thread->metadata_on_stack_buffer());
   105 void MetadataOnStackMark::retire_current_buffer() {
   107   thread->set_metadata_on_stack_buffer(NULL);
   106   retire_buffer(_current_buffer);
       
   107   _current_buffer = NULL;
   108 }
   108 }
   109 
   109 
   110 bool MetadataOnStackMark::has_buffer_for_thread(Thread* thread) {
   110 // Get buffer off free list.
   111   return thread->metadata_on_stack_buffer() != NULL;
   111 MetadataOnStackBuffer* MetadataOnStackMark::allocate_buffer() {
   112 }
   112   MetadataOnStackBuffer* allocated = _free_buffers;
   113 
   113 
   114 MetadataOnStackBuffer* MetadataOnStackMark::allocate_buffer() {
   114   if (allocated != NULL) {
   115   MetadataOnStackBuffer* allocated;
   115     _free_buffers = allocated->next_free();
   116   MetadataOnStackBuffer* new_head;
   116   }
   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 
   117 
   126   if (allocated == NULL) {
   118   if (allocated == NULL) {
   127     allocated = new MetadataOnStackBuffer();
   119     allocated = new MetadataOnStackBuffer();
   128   }
   120   }
   129 
   121 
   131 
   123 
   132   return allocated;
   124   return allocated;
   133 }
   125 }
   134 
   126 
   135 // Record which objects are marked so we can unmark the same objects.
   127 // Record which objects are marked so we can unmark the same objects.
   136 void MetadataOnStackMark::record(Metadata* m, Thread* thread) {
   128 void MetadataOnStackMark::record(Metadata* m) {
   137   assert(_is_active, "metadata on stack marking is active");
   129   assert(_is_active, "metadata on stack marking is active");
   138 
   130 
   139   MetadataOnStackBuffer* buffer =  thread->metadata_on_stack_buffer();
   131   MetadataOnStackBuffer* buffer = _current_buffer;
   140 
   132 
   141   if (buffer != NULL && buffer->is_full()) {
   133   if (buffer != NULL && buffer->is_full()) {
   142     retire_buffer(buffer);
   134     retire_buffer(buffer);
   143     buffer = NULL;
   135     buffer = NULL;
   144   }
   136   }
   145 
   137 
   146   if (buffer == NULL) {
   138   if (buffer == NULL) {
   147     buffer = allocate_buffer();
   139     buffer = allocate_buffer();
   148     thread->set_metadata_on_stack_buffer(buffer);
   140     _current_buffer = buffer;
   149   }
   141   }
   150 
   142 
   151   buffer->push(m);
   143   buffer->push(m);
   152 }
   144 }