src/share/vm/gc_implementation/g1/g1CodeCacheRemSet.cpp
Print this page
*** 28,54 ****
#include "gc_implementation/g1/g1CodeCacheRemSet.hpp"
#include "memory/iterator.hpp"
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
! G1CodeRootChunk::G1CodeRootChunk() : _top(NULL), _next(NULL), _prev(NULL) {
_top = bottom();
}
void G1CodeRootChunk::reset() {
_next = _prev = NULL;
_top = bottom();
}
void G1CodeRootChunk::nmethods_do(CodeBlobClosure* cl) {
! nmethod** cur = bottom();
while (cur != _top) {
! cl->do_code_blob(*cur);
cur++;
}
}
G1CodeRootChunkManager::G1CodeRootChunkManager() : _free_list(), _num_chunks_handed_out(0) {
_free_list.initialize();
_free_list.set_size(G1CodeRootChunk::word_size());
}
--- 28,83 ----
#include "gc_implementation/g1/g1CodeCacheRemSet.hpp"
#include "memory/iterator.hpp"
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
! G1CodeRootChunk::G1CodeRootChunk() : _top(NULL), _next(NULL), _prev(NULL), _free(NULL) {
_top = bottom();
}
void G1CodeRootChunk::reset() {
_next = _prev = NULL;
+ _free = NULL;
_top = bottom();
}
void G1CodeRootChunk::nmethods_do(CodeBlobClosure* cl) {
! NmethodOrLink* cur = bottom();
while (cur != _top) {
! if (is_nmethod(cur)) {
! cl->do_code_blob(cur->_nmethod);
! }
cur++;
}
}
+ bool G1CodeRootChunk::remove_lock_free(nmethod* method) {
+ NmethodOrLink* cur = bottom();
+
+ for (NmethodOrLink* cur = bottom(); cur != _top; cur++) {
+ if (cur->_nmethod == method) {
+ bool result = Atomic::cmpxchg_ptr(NULL, &cur->_nmethod, method) == method;
+
+ if (!result) {
+ // Someone else cleared out this entry.
+ return false;
+ }
+
+ // The method was cleared. Time to link it into the free list.
+ NmethodOrLink* prev_free;
+ do {
+ prev_free = (NmethodOrLink*)_free;
+ cur->_link = prev_free;
+ } while (Atomic::cmpxchg_ptr(cur, &_free, prev_free) != prev_free);
+
+ return true;
+ }
+ }
+
+ return false;
+ }
+
G1CodeRootChunkManager::G1CodeRootChunkManager() : _free_list(), _num_chunks_handed_out(0) {
_free_list.initialize();
_free_list.set_size(G1CodeRootChunk::word_size());
}
*** 138,175 ****
clear();
}
void G1CodeRootSet::add(nmethod* method) {
if (!contains(method)) {
! // Try to add the nmethod. If there is not enough space, get a new chunk.
! if (_list.head() == NULL || _list.head()->is_full()) {
! G1CodeRootChunk* cur = new_chunk();
_list.return_chunk_at_head(cur);
}
! bool result = _list.head()->add(method);
guarantee(result, err_msg("Not able to add nmethod "PTR_FORMAT" to newly allocated chunk.", method));
_length++;
}
}
! void G1CodeRootSet::remove(nmethod* method) {
G1CodeRootChunk* found = find(method);
if (found != NULL) {
! bool result = found->remove(method);
! guarantee(result, err_msg("could not find nmethod "PTR_FORMAT" during removal although we previously found it", method));
! // eventually free completely emptied chunk
! if (found->is_empty()) {
! _list.remove_chunk(found);
! free(found);
}
- _length--;
}
assert(!contains(method), err_msg(PTR_FORMAT" still contains nmethod "PTR_FORMAT, this, method));
}
nmethod* G1CodeRootSet::pop() {
! do {
G1CodeRootChunk* cur = _list.head();
if (cur == NULL) {
assert(_length == 0, "when there are no chunks, there should be no elements");
return NULL;
}
--- 167,213 ----
clear();
}
void G1CodeRootSet::add(nmethod* method) {
if (!contains(method)) {
! // Find the first chunk thatisn't full.
! G1CodeRootChunk* cur = _list.head();
! while (cur != NULL) {
! if (!cur->is_full()) {
! break;
! }
! cur = cur->next();
! }
!
! // All chunks are full, get a new chunk.
! if (cur == NULL) {
! cur = new_chunk();
_list.return_chunk_at_head(cur);
}
!
! // Add the nmethod.
! bool result = cur->add(method);
!
guarantee(result, err_msg("Not able to add nmethod "PTR_FORMAT" to newly allocated chunk.", method));
+
_length++;
}
}
! void G1CodeRootSet::remove_lock_free(nmethod* method) {
G1CodeRootChunk* found = find(method);
if (found != NULL) {
! bool result = found->remove_lock_free(method);
! if (result) {
! Atomic::dec_ptr((volatile intptr_t*)&_length);
}
}
assert(!contains(method), err_msg(PTR_FORMAT" still contains nmethod "PTR_FORMAT, this, method));
}
nmethod* G1CodeRootSet::pop() {
! while (true) {
G1CodeRootChunk* cur = _list.head();
if (cur == NULL) {
assert(_length == 0, "when there are no chunks, there should be no elements");
return NULL;
}
*** 178,188 ****
_length--;
return result;
} else {
free(_list.get_chunk_at_head());
}
! } while (true);
}
G1CodeRootChunk* G1CodeRootSet::find(nmethod* method) {
G1CodeRootChunk* cur = _list.head();
while (cur != NULL) {
--- 216,226 ----
_length--;
return result;
} else {
free(_list.get_chunk_at_head());
}
! }
}
G1CodeRootChunk* G1CodeRootSet::find(nmethod* method) {
G1CodeRootChunk* cur = _list.head();
while (cur != NULL) {