hotspot/src/share/vm/gc_implementation/g1/g1CodeCacheRemSet.cpp
changeset 25492 d27050bdfb04
parent 25491 70fb742e40aa
child 25500 4d2e06147d1e
equal deleted inserted replaced
25491:70fb742e40aa 25492:d27050bdfb04
    28 #include "gc_implementation/g1/g1CodeCacheRemSet.hpp"
    28 #include "gc_implementation/g1/g1CodeCacheRemSet.hpp"
    29 #include "memory/iterator.hpp"
    29 #include "memory/iterator.hpp"
    30 
    30 
    31 PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
    31 PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
    32 
    32 
    33 G1CodeRootChunk::G1CodeRootChunk() : _top(NULL), _next(NULL), _prev(NULL) {
    33 G1CodeRootChunk::G1CodeRootChunk() : _top(NULL), _next(NULL), _prev(NULL), _free(NULL) {
    34   _top = bottom();
    34   _top = bottom();
    35 }
    35 }
    36 
    36 
    37 void G1CodeRootChunk::reset() {
    37 void G1CodeRootChunk::reset() {
    38   _next = _prev = NULL;
    38   _next = _prev = NULL;
       
    39   _free = NULL;
    39   _top = bottom();
    40   _top = bottom();
    40 }
    41 }
    41 
    42 
    42 void G1CodeRootChunk::nmethods_do(CodeBlobClosure* cl) {
    43 void G1CodeRootChunk::nmethods_do(CodeBlobClosure* cl) {
    43   nmethod** cur = bottom();
    44   NmethodOrLink* cur = bottom();
    44   while (cur != _top) {
    45   while (cur != _top) {
    45     cl->do_code_blob(*cur);
    46     if (is_nmethod(cur)) {
       
    47       cl->do_code_blob(cur->_nmethod);
       
    48     }
    46     cur++;
    49     cur++;
    47   }
    50   }
       
    51 }
       
    52 
       
    53 bool G1CodeRootChunk::remove_lock_free(nmethod* method) {
       
    54   NmethodOrLink* cur = bottom();
       
    55 
       
    56   for (NmethodOrLink* cur = bottom(); cur != _top; cur++) {
       
    57     if (cur->_nmethod == method) {
       
    58       bool result = Atomic::cmpxchg_ptr(NULL, &cur->_nmethod, method) == method;
       
    59 
       
    60       if (!result) {
       
    61         // Someone else cleared out this entry.
       
    62         return false;
       
    63       }
       
    64 
       
    65       // The method was cleared. Time to link it into the free list.
       
    66       NmethodOrLink* prev_free;
       
    67       do {
       
    68         prev_free = (NmethodOrLink*)_free;
       
    69         cur->_link = prev_free;
       
    70       } while (Atomic::cmpxchg_ptr(cur, &_free, prev_free) != prev_free);
       
    71 
       
    72       return true;
       
    73     }
       
    74   }
       
    75 
       
    76   return false;
    48 }
    77 }
    49 
    78 
    50 G1CodeRootChunkManager::G1CodeRootChunkManager() : _free_list(), _num_chunks_handed_out(0) {
    79 G1CodeRootChunkManager::G1CodeRootChunkManager() : _free_list(), _num_chunks_handed_out(0) {
    51   _free_list.initialize();
    80   _free_list.initialize();
    52   _free_list.set_size(G1CodeRootChunk::word_size());
    81   _free_list.set_size(G1CodeRootChunk::word_size());
   138   clear();
   167   clear();
   139 }
   168 }
   140 
   169 
   141 void G1CodeRootSet::add(nmethod* method) {
   170 void G1CodeRootSet::add(nmethod* method) {
   142   if (!contains(method)) {
   171   if (!contains(method)) {
   143     // Try to add the nmethod. If there is not enough space, get a new chunk.
   172     // Find the first chunk thatisn't full.
   144     if (_list.head() == NULL || _list.head()->is_full()) {
   173     G1CodeRootChunk* cur = _list.head();
   145       G1CodeRootChunk* cur = new_chunk();
   174     while (cur != NULL) {
       
   175       if (!cur->is_full()) {
       
   176         break;
       
   177       }
       
   178       cur = cur->next();
       
   179     }
       
   180 
       
   181     // All chunks are full, get a new chunk.
       
   182     if (cur == NULL) {
       
   183       cur = new_chunk();
   146       _list.return_chunk_at_head(cur);
   184       _list.return_chunk_at_head(cur);
   147     }
   185     }
   148     bool result = _list.head()->add(method);
   186 
       
   187     // Add the nmethod.
       
   188     bool result = cur->add(method);
       
   189 
   149     guarantee(result, err_msg("Not able to add nmethod "PTR_FORMAT" to newly allocated chunk.", method));
   190     guarantee(result, err_msg("Not able to add nmethod "PTR_FORMAT" to newly allocated chunk.", method));
       
   191 
   150     _length++;
   192     _length++;
   151   }
   193   }
   152 }
   194 }
   153 
   195 
   154 void G1CodeRootSet::remove(nmethod* method) {
   196 void G1CodeRootSet::remove_lock_free(nmethod* method) {
   155   G1CodeRootChunk* found = find(method);
   197   G1CodeRootChunk* found = find(method);
   156   if (found != NULL) {
   198   if (found != NULL) {
   157     bool result = found->remove(method);
   199     bool result = found->remove_lock_free(method);
   158     guarantee(result, err_msg("could not find nmethod "PTR_FORMAT" during removal although we previously found it", method));
   200     if (result) {
   159     // eventually free completely emptied chunk
   201       Atomic::dec_ptr((volatile intptr_t*)&_length);
   160     if (found->is_empty()) {
   202     }
   161       _list.remove_chunk(found);
       
   162       free(found);
       
   163     }
       
   164     _length--;
       
   165   }
   203   }
   166   assert(!contains(method), err_msg(PTR_FORMAT" still contains nmethod "PTR_FORMAT, this, method));
   204   assert(!contains(method), err_msg(PTR_FORMAT" still contains nmethod "PTR_FORMAT, this, method));
   167 }
   205 }
   168 
   206 
   169 nmethod* G1CodeRootSet::pop() {
   207 nmethod* G1CodeRootSet::pop() {
   170   do {
   208   while (true) {
   171     G1CodeRootChunk* cur = _list.head();
   209     G1CodeRootChunk* cur = _list.head();
   172     if (cur == NULL) {
   210     if (cur == NULL) {
   173       assert(_length == 0, "when there are no chunks, there should be no elements");
   211       assert(_length == 0, "when there are no chunks, there should be no elements");
   174       return NULL;
   212       return NULL;
   175     }
   213     }
   178       _length--;
   216       _length--;
   179       return result;
   217       return result;
   180     } else {
   218     } else {
   181       free(_list.get_chunk_at_head());
   219       free(_list.get_chunk_at_head());
   182     }
   220     }
   183   } while (true);
   221   }
   184 }
   222 }
   185 
   223 
   186 G1CodeRootChunk* G1CodeRootSet::find(nmethod* method) {
   224 G1CodeRootChunk* G1CodeRootSet::find(nmethod* method) {
   187   G1CodeRootChunk* cur = _list.head();
   225   G1CodeRootChunk* cur = _list.head();
   188   while (cur != NULL) {
   226   while (cur != NULL) {