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

Print this page
rev 6322 : 8038930: G1CodeRootSet::test fails with assert(_num_chunks_handed_out == 0) failed: No elements must have been handed out yet
Summary: The test incorrectly assumed that it had been started with no other previous compilation activity. Fix this by allowing multiple code root free chunk lists, and use one separate from the global one to perform the test.
Reviewed-by: brutisso
rev 6329 : 8040792: G1: Memory usage calculation uses sizeof(this) instead of sizeof(classname)
Summary: A few locations in the code use sizeof(this) which returns the size of the pointer instead of sizeof(classname) which returns the size of the sum of its members. This change fixes these errors and adds a few tests.
Reviewed-by: mgerdin, brutisso


  69 void G1CodeRootChunkManager::purge_chunks(size_t keep_ratio) {
  70   size_t keep = _num_chunks_handed_out * keep_ratio / 100;
  71   if (keep >= (size_t)_free_list.count()) {
  72     return;
  73   }
  74 
  75   FreeList<G1CodeRootChunk> temp;
  76   temp.initialize();
  77   temp.set_size(G1CodeRootChunk::word_size());
  78 
  79   _free_list.getFirstNChunksFromList((size_t)_free_list.count() - keep, &temp);
  80 
  81   G1CodeRootChunk* cur = temp.get_chunk_at_head();
  82   while (cur != NULL) {
  83     delete cur;
  84     cur = temp.get_chunk_at_head();
  85   }
  86 }
  87 
  88 size_t G1CodeRootChunkManager::static_mem_size() {
  89   return sizeof(this);
  90 }
  91 
  92 
  93 G1CodeRootChunk* G1CodeRootChunkManager::new_chunk() {
  94   G1CodeRootChunk* result = _free_list.get_chunk_at_head();
  95   if (result == NULL) {
  96     result = new G1CodeRootChunk();
  97   }
  98   _num_chunks_handed_out++;
  99   result->reset();
 100   return result;
 101 }
 102 
 103 #ifndef PRODUCT
 104 
 105 size_t G1CodeRootChunkManager::num_chunks_handed_out() const {
 106   return _num_chunks_handed_out;
 107 }
 108 
 109 size_t G1CodeRootChunkManager::num_free_chunks() const {
 110   return (size_t)_free_list.count();
 111 }
 112 
 113 #endif
 114 
 115 G1CodeRootChunkManager G1CodeRootSet::_default_chunk_manager;
 116 
 117 void G1CodeRootSet::purge_chunks(size_t keep_ratio) {
 118   _default_chunk_manager.purge_chunks(keep_ratio);
 119 }
 120 
 121 size_t G1CodeRootSet::static_mem_size() {
 122   return _default_chunk_manager.static_mem_size();
 123 }
 124 
 125 size_t G1CodeRootSet::free_chunks_mem_size() {
 126   return _default_chunk_manager.fl_mem_size();
 127 }
 128 
 129 G1CodeRootSet::G1CodeRootSet(G1CodeRootChunkManager* manager) : _manager(manager), _list(), _length(0) {
 130   if (_manager == NULL) {
 131     _manager = &_default_chunk_manager;
 132   }
 133   _list.initialize();
 134   _list.set_size(G1CodeRootChunk::word_size());
 135 }
 136 
 137 G1CodeRootSet::~G1CodeRootSet() {
 138   clear();
 139 }
 140 
 141 void G1CodeRootSet::add(nmethod* method) {


 198   free_chunk(chunk);
 199 }
 200 
 201 bool G1CodeRootSet::contains(nmethod* method) {
 202   return find(method) != NULL;
 203 }
 204 
 205 void G1CodeRootSet::clear() {
 206   free_all_chunks(&_list);
 207   _length = 0;
 208 }
 209 
 210 void G1CodeRootSet::nmethods_do(CodeBlobClosure* blk) const {
 211   G1CodeRootChunk* cur = _list.head();
 212   while (cur != NULL) {
 213     cur->nmethods_do(blk);
 214     cur = (G1CodeRootChunk*)cur->next();
 215   }
 216 }
 217 




 218 size_t G1CodeRootSet::mem_size() {
 219   return sizeof(this) + _list.count() * _list.size();
 220 }
 221 
 222 #ifndef PRODUCT
 223 
 224 void G1CodeRootSet::test() {
 225   G1CodeRootChunkManager mgr;
 226 
 227   assert(mgr.num_chunks_handed_out() == 0, "Must not have handed out chunks yet");
 228 



 229   // The number of chunks that we allocate for purge testing.
 230   size_t const num_chunks = 10;
 231 
 232   {
 233     G1CodeRootSet set1(&mgr);
 234     assert(set1.is_empty(), "Code root set must be initially empty but is not.");
 235 



 236     set1.add((nmethod*)1);
 237     assert(mgr.num_chunks_handed_out() == 1,
 238            err_msg("Must have allocated and handed out one chunk, but handed out "
 239                    SIZE_FORMAT" chunks", mgr.num_chunks_handed_out()));
 240     assert(set1.length() == 1, err_msg("Added exactly one element, but set contains "
 241                                        SIZE_FORMAT" elements", set1.length()));
 242 
 243     // G1CodeRootChunk::word_size() is larger than G1CodeRootChunk::num_entries which
 244     // we cannot access.
 245     for (uint i = 0; i < G1CodeRootChunk::word_size() + 1; i++) {
 246       set1.add((nmethod*)1);
 247     }
 248     assert(mgr.num_chunks_handed_out() == 1,
 249            err_msg("Duplicate detection must have prevented allocation of further "
 250                    "chunks but allocated "SIZE_FORMAT, mgr.num_chunks_handed_out()));
 251     assert(set1.length() == 1,
 252            err_msg("Duplicate detection should not have increased the set size but "
 253                    "is "SIZE_FORMAT, set1.length()));
 254 
 255     size_t num_total_after_add = G1CodeRootChunk::word_size() + 1;




  69 void G1CodeRootChunkManager::purge_chunks(size_t keep_ratio) {
  70   size_t keep = _num_chunks_handed_out * keep_ratio / 100;
  71   if (keep >= (size_t)_free_list.count()) {
  72     return;
  73   }
  74 
  75   FreeList<G1CodeRootChunk> temp;
  76   temp.initialize();
  77   temp.set_size(G1CodeRootChunk::word_size());
  78 
  79   _free_list.getFirstNChunksFromList((size_t)_free_list.count() - keep, &temp);
  80 
  81   G1CodeRootChunk* cur = temp.get_chunk_at_head();
  82   while (cur != NULL) {
  83     delete cur;
  84     cur = temp.get_chunk_at_head();
  85   }
  86 }
  87 
  88 size_t G1CodeRootChunkManager::static_mem_size() {
  89   return sizeof(G1CodeRootChunkManager);
  90 }
  91 
  92 
  93 G1CodeRootChunk* G1CodeRootChunkManager::new_chunk() {
  94   G1CodeRootChunk* result = _free_list.get_chunk_at_head();
  95   if (result == NULL) {
  96     result = new G1CodeRootChunk();
  97   }
  98   _num_chunks_handed_out++;
  99   result->reset();
 100   return result;
 101 }
 102 
 103 #ifndef PRODUCT
 104 
 105 size_t G1CodeRootChunkManager::num_chunks_handed_out() const {
 106   return _num_chunks_handed_out;
 107 }
 108 
 109 size_t G1CodeRootChunkManager::num_free_chunks() const {
 110   return (size_t)_free_list.count();
 111 }
 112 
 113 #endif
 114 
 115 G1CodeRootChunkManager G1CodeRootSet::_default_chunk_manager;
 116 
 117 void G1CodeRootSet::purge_chunks(size_t keep_ratio) {
 118   _default_chunk_manager.purge_chunks(keep_ratio);
 119 }
 120 
 121 size_t G1CodeRootSet::free_chunks_static_mem_size() {
 122   return _default_chunk_manager.static_mem_size();
 123 }
 124 
 125 size_t G1CodeRootSet::free_chunks_mem_size() {
 126   return _default_chunk_manager.fl_mem_size();
 127 }
 128 
 129 G1CodeRootSet::G1CodeRootSet(G1CodeRootChunkManager* manager) : _manager(manager), _list(), _length(0) {
 130   if (_manager == NULL) {
 131     _manager = &_default_chunk_manager;
 132   }
 133   _list.initialize();
 134   _list.set_size(G1CodeRootChunk::word_size());
 135 }
 136 
 137 G1CodeRootSet::~G1CodeRootSet() {
 138   clear();
 139 }
 140 
 141 void G1CodeRootSet::add(nmethod* method) {


 198   free_chunk(chunk);
 199 }
 200 
 201 bool G1CodeRootSet::contains(nmethod* method) {
 202   return find(method) != NULL;
 203 }
 204 
 205 void G1CodeRootSet::clear() {
 206   free_all_chunks(&_list);
 207   _length = 0;
 208 }
 209 
 210 void G1CodeRootSet::nmethods_do(CodeBlobClosure* blk) const {
 211   G1CodeRootChunk* cur = _list.head();
 212   while (cur != NULL) {
 213     cur->nmethods_do(blk);
 214     cur = (G1CodeRootChunk*)cur->next();
 215   }
 216 }
 217 
 218 size_t G1CodeRootSet::static_mem_size() {
 219   return sizeof(G1CodeRootSet);
 220 }
 221 
 222 size_t G1CodeRootSet::mem_size() {
 223   return G1CodeRootSet::static_mem_size() + _list.count() * _list.size();
 224 }
 225 
 226 #ifndef PRODUCT
 227 
 228 void G1CodeRootSet::test() {
 229   G1CodeRootChunkManager mgr;
 230 
 231   assert(mgr.num_chunks_handed_out() == 0, "Must not have handed out chunks yet");
 232 
 233   assert(G1CodeRootChunkManager::static_mem_size() > sizeof(void*),
 234          err_msg("The chunk manager's static memory usage seems too small, is only "SIZE_FORMAT" bytes.", G1CodeRootChunkManager::static_mem_size()));
 235 
 236   // The number of chunks that we allocate for purge testing.
 237   size_t const num_chunks = 10;
 238 
 239   {
 240     G1CodeRootSet set1(&mgr);
 241     assert(set1.is_empty(), "Code root set must be initially empty but is not.");
 242 
 243     assert(G1CodeRootSet::static_mem_size() > sizeof(void*),
 244            err_msg("The code root set's static memory usage seems too small, is only "SIZE_FORMAT" bytes", G1CodeRootSet::static_mem_size()));
 245 
 246     set1.add((nmethod*)1);
 247     assert(mgr.num_chunks_handed_out() == 1,
 248            err_msg("Must have allocated and handed out one chunk, but handed out "
 249                    SIZE_FORMAT" chunks", mgr.num_chunks_handed_out()));
 250     assert(set1.length() == 1, err_msg("Added exactly one element, but set contains "
 251                                        SIZE_FORMAT" elements", set1.length()));
 252 
 253     // G1CodeRootChunk::word_size() is larger than G1CodeRootChunk::num_entries which
 254     // we cannot access.
 255     for (uint i = 0; i < G1CodeRootChunk::word_size() + 1; i++) {
 256       set1.add((nmethod*)1);
 257     }
 258     assert(mgr.num_chunks_handed_out() == 1,
 259            err_msg("Duplicate detection must have prevented allocation of further "
 260                    "chunks but allocated "SIZE_FORMAT, mgr.num_chunks_handed_out()));
 261     assert(set1.length() == 1,
 262            err_msg("Duplicate detection should not have increased the set size but "
 263                    "is "SIZE_FORMAT, set1.length()));
 264 
 265     size_t num_total_after_add = G1CodeRootChunk::word_size() + 1;