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

Mon, 08 Sep 2014 17:47:43 +0200

author
mgerdin
date
Mon, 08 Sep 2014 17:47:43 +0200
changeset 7209
58925d1f325e
parent 7208
7baf47cb97cb
child 7210
318cc6fdae90

8057722: G1: Code root hashtable updated incorrectly when evacuation failed
Reviewed-by: brutisso, jwilhelm

src/share/vm/gc_implementation/g1/g1CodeCacheRemSet.cpp file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/vm/gc_implementation/g1/g1CodeCacheRemSet.cpp	Fri Aug 29 13:12:21 2014 +0200
     1.2 +++ b/src/share/vm/gc_implementation/g1/g1CodeCacheRemSet.cpp	Mon Sep 08 17:47:43 2014 +0200
     1.3 @@ -48,6 +48,7 @@
     1.4      return hash ^ (hash >> 7); // code heap blocks are 128byte aligned
     1.5    }
     1.6  
     1.7 +  void remove_entry(Entry* e, Entry* previous);
     1.8    Entry* new_entry(nmethod* nm);
     1.9  
    1.10   public:
    1.11 @@ -67,7 +68,7 @@
    1.12    void nmethods_do(CodeBlobClosure* blk);
    1.13  
    1.14    template<typename CB>
    1.15 -  void remove_if(CB& should_remove);
    1.16 +  int remove_if(CB& should_remove);
    1.17  
    1.18    static void purge_list_append(CodeRootSetTable* tbl);
    1.19    static void purge();
    1.20 @@ -91,6 +92,18 @@
    1.21    return entry;
    1.22  }
    1.23  
    1.24 +void CodeRootSetTable::remove_entry(Entry* e, Entry* previous) {
    1.25 +  int index = hash_to_index(e->hash());
    1.26 +  assert((e == bucket(index)) == (previous == NULL), "if e is the first entry then previous should be null");
    1.27 +
    1.28 +  if (previous == NULL) {
    1.29 +    set_entry(index, e->next());
    1.30 +  } else {
    1.31 +    previous->set_next(e->next());
    1.32 +  }
    1.33 +  free_entry(e);
    1.34 +}
    1.35 +
    1.36  CodeRootSetTable::~CodeRootSetTable() {
    1.37    for (int index = 0; index < table_size(); ++index) {
    1.38      for (Entry* e = bucket(index); e != NULL; ) {
    1.39 @@ -133,12 +146,7 @@
    1.40    Entry* previous = NULL;
    1.41    for (Entry* e = bucket(index); e != NULL; previous = e, e = e->next()) {
    1.42      if (e->literal() == nm) {
    1.43 -      if (previous != NULL) {
    1.44 -        previous->set_next(e->next());
    1.45 -      } else {
    1.46 -        set_entry(index, e->next());
    1.47 -      }
    1.48 -      free_entry(e);
    1.49 +      remove_entry(e, previous);
    1.50        return true;
    1.51      }
    1.52    }
    1.53 @@ -163,25 +171,23 @@
    1.54  }
    1.55  
    1.56  template<typename CB>
    1.57 -void CodeRootSetTable::remove_if(CB& should_remove) {
    1.58 +int CodeRootSetTable::remove_if(CB& should_remove) {
    1.59 +  int num_removed = 0;
    1.60    for (int index = 0; index < table_size(); ++index) {
    1.61      Entry* previous = NULL;
    1.62      Entry* e = bucket(index);
    1.63      while (e != NULL) {
    1.64        Entry* next = e->next();
    1.65        if (should_remove(e->literal())) {
    1.66 -        if (previous != NULL) {
    1.67 -          previous->set_next(next);
    1.68 -        } else {
    1.69 -          set_entry(index, next);
    1.70 -        }
    1.71 -        free_entry(e);
    1.72 +        remove_entry(e, previous);
    1.73 +        ++num_removed;
    1.74        } else {
    1.75          previous = e;
    1.76        }
    1.77        e = next;
    1.78      }
    1.79    }
    1.80 +  return num_removed;
    1.81  }
    1.82  
    1.83  G1CodeRootSet::~G1CodeRootSet() {
    1.84 @@ -320,14 +326,19 @@
    1.85    bool operator() (nmethod* nm) {
    1.86      _detector._points_into = false;
    1.87      _blobs.do_code_blob(nm);
    1.88 -    return _detector._points_into;
    1.89 +    return !_detector._points_into;
    1.90    }
    1.91  };
    1.92  
    1.93  void G1CodeRootSet::clean(HeapRegion* owner) {
    1.94    CleanCallback should_clean(owner);
    1.95    if (_table != NULL) {
    1.96 -    _table->remove_if(should_clean);
    1.97 +    int removed = _table->remove_if(should_clean);
    1.98 +    assert((size_t)removed <= _length, "impossible");
    1.99 +    _length -= removed;
   1.100 +  }
   1.101 +  if (_length == 0) {
   1.102 +    clear();
   1.103    }
   1.104  }
   1.105  

mercurial