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) {