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;
|