提交 d317f266 编写于 作者: M mgerdin

8057722: G1: Code root hashtable updated incorrectly when evacuation failed

Reviewed-by: brutisso, jwilhelm
上级 6c3f70ca
...@@ -48,6 +48,7 @@ class CodeRootSetTable : public Hashtable<nmethod*, mtGC> { ...@@ -48,6 +48,7 @@ class CodeRootSetTable : public Hashtable<nmethod*, mtGC> {
return hash ^ (hash >> 7); // code heap blocks are 128byte aligned return hash ^ (hash >> 7); // code heap blocks are 128byte aligned
} }
void remove_entry(Entry* e, Entry* previous);
Entry* new_entry(nmethod* nm); Entry* new_entry(nmethod* nm);
public: public:
...@@ -67,7 +68,7 @@ class CodeRootSetTable : public Hashtable<nmethod*, mtGC> { ...@@ -67,7 +68,7 @@ class CodeRootSetTable : public Hashtable<nmethod*, mtGC> {
void nmethods_do(CodeBlobClosure* blk); void nmethods_do(CodeBlobClosure* blk);
template<typename CB> template<typename CB>
void remove_if(CB& should_remove); int remove_if(CB& should_remove);
static void purge_list_append(CodeRootSetTable* tbl); static void purge_list_append(CodeRootSetTable* tbl);
static void purge(); static void purge();
...@@ -91,6 +92,18 @@ CodeRootSetTable::Entry* CodeRootSetTable::new_entry(nmethod* nm) { ...@@ -91,6 +92,18 @@ CodeRootSetTable::Entry* CodeRootSetTable::new_entry(nmethod* nm) {
return entry; return entry;
} }
void CodeRootSetTable::remove_entry(Entry* e, Entry* previous) {
int index = hash_to_index(e->hash());
assert((e == bucket(index)) == (previous == NULL), "if e is the first entry then previous should be null");
if (previous == NULL) {
set_entry(index, e->next());
} else {
previous->set_next(e->next());
}
free_entry(e);
}
CodeRootSetTable::~CodeRootSetTable() { CodeRootSetTable::~CodeRootSetTable() {
for (int index = 0; index < table_size(); ++index) { for (int index = 0; index < table_size(); ++index) {
for (Entry* e = bucket(index); e != NULL; ) { for (Entry* e = bucket(index); e != NULL; ) {
...@@ -133,12 +146,7 @@ bool CodeRootSetTable::remove(nmethod* nm) { ...@@ -133,12 +146,7 @@ bool CodeRootSetTable::remove(nmethod* nm) {
Entry* previous = NULL; Entry* previous = NULL;
for (Entry* e = bucket(index); e != NULL; previous = e, e = e->next()) { for (Entry* e = bucket(index); e != NULL; previous = e, e = e->next()) {
if (e->literal() == nm) { if (e->literal() == nm) {
if (previous != NULL) { remove_entry(e, previous);
previous->set_next(e->next());
} else {
set_entry(index, e->next());
}
free_entry(e);
return true; return true;
} }
} }
...@@ -163,25 +171,23 @@ void CodeRootSetTable::nmethods_do(CodeBlobClosure* blk) { ...@@ -163,25 +171,23 @@ void CodeRootSetTable::nmethods_do(CodeBlobClosure* blk) {
} }
template<typename CB> template<typename CB>
void CodeRootSetTable::remove_if(CB& should_remove) { int CodeRootSetTable::remove_if(CB& should_remove) {
int num_removed = 0;
for (int index = 0; index < table_size(); ++index) { for (int index = 0; index < table_size(); ++index) {
Entry* previous = NULL; Entry* previous = NULL;
Entry* e = bucket(index); Entry* e = bucket(index);
while (e != NULL) { while (e != NULL) {
Entry* next = e->next(); Entry* next = e->next();
if (should_remove(e->literal())) { if (should_remove(e->literal())) {
if (previous != NULL) { remove_entry(e, previous);
previous->set_next(next); ++num_removed;
} else {
set_entry(index, next);
}
free_entry(e);
} else { } else {
previous = e; previous = e;
} }
e = next; e = next;
} }
} }
return num_removed;
} }
G1CodeRootSet::~G1CodeRootSet() { G1CodeRootSet::~G1CodeRootSet() {
...@@ -320,14 +326,19 @@ class CleanCallback : public StackObj { ...@@ -320,14 +326,19 @@ class CleanCallback : public StackObj {
bool operator() (nmethod* nm) { bool operator() (nmethod* nm) {
_detector._points_into = false; _detector._points_into = false;
_blobs.do_code_blob(nm); _blobs.do_code_blob(nm);
return _detector._points_into; return !_detector._points_into;
} }
}; };
void G1CodeRootSet::clean(HeapRegion* owner) { void G1CodeRootSet::clean(HeapRegion* owner) {
CleanCallback should_clean(owner); CleanCallback should_clean(owner);
if (_table != NULL) { if (_table != NULL) {
_table->remove_if(should_clean); int removed = _table->remove_if(should_clean);
assert((size_t)removed <= _length, "impossible");
_length -= removed;
}
if (_length == 0) {
clear();
} }
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册