src/share/vm/gc_implementation/g1/g1CodeCacheRemSet.cpp

changeset 6992
2c6ef90f030a
parent 6932
828056cf311f
child 6993
870c03421152
     1.1 --- a/src/share/vm/gc_implementation/g1/g1CodeCacheRemSet.cpp	Tue Jul 01 09:03:55 2014 +0200
     1.2 +++ b/src/share/vm/gc_implementation/g1/g1CodeCacheRemSet.cpp	Mon Jul 07 10:12:40 2014 +0200
     1.3 @@ -30,23 +30,52 @@
     1.4  
     1.5  PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
     1.6  
     1.7 -G1CodeRootChunk::G1CodeRootChunk() : _top(NULL), _next(NULL), _prev(NULL) {
     1.8 +G1CodeRootChunk::G1CodeRootChunk() : _top(NULL), _next(NULL), _prev(NULL), _free(NULL) {
     1.9    _top = bottom();
    1.10  }
    1.11  
    1.12  void G1CodeRootChunk::reset() {
    1.13    _next = _prev = NULL;
    1.14 +  _free = NULL;
    1.15    _top = bottom();
    1.16  }
    1.17  
    1.18  void G1CodeRootChunk::nmethods_do(CodeBlobClosure* cl) {
    1.19 -  nmethod** cur = bottom();
    1.20 +  NmethodOrLink* cur = bottom();
    1.21    while (cur != _top) {
    1.22 -    cl->do_code_blob(*cur);
    1.23 +    if (is_nmethod(cur)) {
    1.24 +      cl->do_code_blob(cur->_nmethod);
    1.25 +    }
    1.26      cur++;
    1.27    }
    1.28  }
    1.29  
    1.30 +bool G1CodeRootChunk::remove_lock_free(nmethod* method) {
    1.31 +  NmethodOrLink* cur = bottom();
    1.32 +
    1.33 +  for (NmethodOrLink* cur = bottom(); cur != _top; cur++) {
    1.34 +    if (cur->_nmethod == method) {
    1.35 +      bool result = Atomic::cmpxchg_ptr(NULL, &cur->_nmethod, method) == method;
    1.36 +
    1.37 +      if (!result) {
    1.38 +        // Someone else cleared out this entry.
    1.39 +        return false;
    1.40 +      }
    1.41 +
    1.42 +      // The method was cleared. Time to link it into the free list.
    1.43 +      NmethodOrLink* prev_free;
    1.44 +      do {
    1.45 +        prev_free = (NmethodOrLink*)_free;
    1.46 +        cur->_link = prev_free;
    1.47 +      } while (Atomic::cmpxchg_ptr(cur, &_free, prev_free) != prev_free);
    1.48 +
    1.49 +      return true;
    1.50 +    }
    1.51 +  }
    1.52 +
    1.53 +  return false;
    1.54 +}
    1.55 +
    1.56  G1CodeRootChunkManager::G1CodeRootChunkManager() : _free_list(), _num_chunks_handed_out(0) {
    1.57    _free_list.initialize();
    1.58    _free_list.set_size(G1CodeRootChunk::word_size());
    1.59 @@ -140,34 +169,43 @@
    1.60  
    1.61  void G1CodeRootSet::add(nmethod* method) {
    1.62    if (!contains(method)) {
    1.63 -    // Try to add the nmethod. If there is not enough space, get a new chunk.
    1.64 -    if (_list.head() == NULL || _list.head()->is_full()) {
    1.65 -      G1CodeRootChunk* cur = new_chunk();
    1.66 +    // Find the first chunk thatisn't full.
    1.67 +    G1CodeRootChunk* cur = _list.head();
    1.68 +    while (cur != NULL) {
    1.69 +      if (!cur->is_full()) {
    1.70 +        break;
    1.71 +      }
    1.72 +      cur = cur->next();
    1.73 +    }
    1.74 +
    1.75 +    // All chunks are full, get a new chunk.
    1.76 +    if (cur == NULL) {
    1.77 +      cur = new_chunk();
    1.78        _list.return_chunk_at_head(cur);
    1.79      }
    1.80 -    bool result = _list.head()->add(method);
    1.81 +
    1.82 +    // Add the nmethod.
    1.83 +    bool result = cur->add(method);
    1.84 +
    1.85      guarantee(result, err_msg("Not able to add nmethod "PTR_FORMAT" to newly allocated chunk.", method));
    1.86 +
    1.87      _length++;
    1.88    }
    1.89  }
    1.90  
    1.91 -void G1CodeRootSet::remove(nmethod* method) {
    1.92 +void G1CodeRootSet::remove_lock_free(nmethod* method) {
    1.93    G1CodeRootChunk* found = find(method);
    1.94    if (found != NULL) {
    1.95 -    bool result = found->remove(method);
    1.96 -    guarantee(result, err_msg("could not find nmethod "PTR_FORMAT" during removal although we previously found it", method));
    1.97 -    // eventually free completely emptied chunk
    1.98 -    if (found->is_empty()) {
    1.99 -      _list.remove_chunk(found);
   1.100 -      free(found);
   1.101 +    bool result = found->remove_lock_free(method);
   1.102 +    if (result) {
   1.103 +      Atomic::dec_ptr((volatile intptr_t*)&_length);
   1.104      }
   1.105 -    _length--;
   1.106    }
   1.107    assert(!contains(method), err_msg(PTR_FORMAT" still contains nmethod "PTR_FORMAT, this, method));
   1.108  }
   1.109  
   1.110  nmethod* G1CodeRootSet::pop() {
   1.111 -  do {
   1.112 +  while (true) {
   1.113      G1CodeRootChunk* cur = _list.head();
   1.114      if (cur == NULL) {
   1.115        assert(_length == 0, "when there are no chunks, there should be no elements");
   1.116 @@ -180,7 +218,7 @@
   1.117      } else {
   1.118        free(_list.get_chunk_at_head());
   1.119      }
   1.120 -  } while (true);
   1.121 +  }
   1.122  }
   1.123  
   1.124  G1CodeRootChunk* G1CodeRootSet::find(nmethod* method) {

mercurial