Mercurial > hg > graal-jvmci-8
comparison src/share/vm/code/codeCache.cpp @ 989:148e5441d916
6863023: need non-perm oops in code cache for JSR 292
Summary: Make a special root-list for those few nmethods which might contain non-perm oops.
Reviewed-by: twisti, kvn, never, jmasa, ysr
author | jrose |
---|---|
date | Tue, 15 Sep 2009 21:53:47 -0700 |
parents | a61af66fc99e |
children | 5f24d0319e54 |
comparison
equal
deleted
inserted
replaced
987:00977607da34 | 989:148e5441d916 |
---|---|
93 | 93 |
94 CodeHeap * CodeCache::_heap = new CodeHeap(); | 94 CodeHeap * CodeCache::_heap = new CodeHeap(); |
95 int CodeCache::_number_of_blobs = 0; | 95 int CodeCache::_number_of_blobs = 0; |
96 int CodeCache::_number_of_nmethods_with_dependencies = 0; | 96 int CodeCache::_number_of_nmethods_with_dependencies = 0; |
97 bool CodeCache::_needs_cache_clean = false; | 97 bool CodeCache::_needs_cache_clean = false; |
98 nmethod* CodeCache::_scavenge_root_nmethods = NULL; | |
98 | 99 |
99 | 100 |
100 CodeBlob* CodeCache::first() { | 101 CodeBlob* CodeCache::first() { |
101 assert_locked_or_safepoint(CodeCache_lock); | 102 assert_locked_or_safepoint(CodeCache_lock); |
102 return (CodeBlob*)_heap->first(); | 103 return (CodeBlob*)_heap->first(); |
146 (intptr_t)_heap->begin(), (intptr_t)_heap->end(), | 147 (intptr_t)_heap->begin(), (intptr_t)_heap->end(), |
147 (address)_heap->end() - (address)_heap->begin()); | 148 (address)_heap->end() - (address)_heap->begin()); |
148 } | 149 } |
149 } | 150 } |
150 verify_if_often(); | 151 verify_if_often(); |
151 if (PrintCodeCache2) { // Need to add a new flag | 152 print_trace("allocation", cb, size); |
152 ResourceMark rm; | |
153 tty->print_cr("CodeCache allocation: addr: " INTPTR_FORMAT ", size: 0x%x\n", cb, size); | |
154 } | |
155 return cb; | 153 return cb; |
156 } | 154 } |
157 | 155 |
158 void CodeCache::free(CodeBlob* cb) { | 156 void CodeCache::free(CodeBlob* cb) { |
159 assert_locked_or_safepoint(CodeCache_lock); | 157 assert_locked_or_safepoint(CodeCache_lock); |
160 verify_if_often(); | 158 verify_if_often(); |
161 | 159 |
162 if (PrintCodeCache2) { // Need to add a new flag | 160 print_trace("free", cb); |
163 ResourceMark rm; | |
164 tty->print_cr("CodeCache free: addr: " INTPTR_FORMAT ", size: 0x%x\n", cb, cb->size()); | |
165 } | |
166 if (cb->is_nmethod() && ((nmethod *)cb)->has_dependencies()) { | 161 if (cb->is_nmethod() && ((nmethod *)cb)->has_dependencies()) { |
167 _number_of_nmethods_with_dependencies--; | 162 _number_of_nmethods_with_dependencies--; |
168 } | 163 } |
169 _number_of_blobs--; | 164 _number_of_blobs--; |
170 | 165 |
258 FOR_ALL_ALIVE_BLOBS(cb) { | 253 FOR_ALL_ALIVE_BLOBS(cb) { |
259 cb->do_unloading(is_alive, keep_alive, unloading_occurred); | 254 cb->do_unloading(is_alive, keep_alive, unloading_occurred); |
260 } | 255 } |
261 } | 256 } |
262 | 257 |
263 void CodeCache::oops_do(OopClosure* f) { | 258 void CodeCache::blobs_do(CodeBlobClosure* f) { |
264 assert_locked_or_safepoint(CodeCache_lock); | 259 assert_locked_or_safepoint(CodeCache_lock); |
265 FOR_ALL_ALIVE_BLOBS(cb) { | 260 FOR_ALL_ALIVE_BLOBS(cb) { |
266 cb->oops_do(f); | 261 f->do_code_blob(cb); |
267 } | 262 |
268 } | 263 #ifdef ASSERT |
264 if (cb->is_nmethod()) | |
265 ((nmethod*)cb)->verify_scavenge_root_oops(); | |
266 #endif //ASSERT | |
267 } | |
268 } | |
269 | |
270 // Walk the list of methods which might contain non-perm oops. | |
271 void CodeCache::scavenge_root_nmethods_do(CodeBlobClosure* f) { | |
272 assert_locked_or_safepoint(CodeCache_lock); | |
273 debug_only(mark_scavenge_root_nmethods()); | |
274 | |
275 for (nmethod* cur = scavenge_root_nmethods(); cur != NULL; cur = cur->scavenge_root_link()) { | |
276 debug_only(cur->clear_scavenge_root_marked()); | |
277 assert(cur->scavenge_root_not_marked(), ""); | |
278 assert(cur->on_scavenge_root_list(), "else shouldn't be on this list"); | |
279 | |
280 bool is_live = (!cur->is_zombie() && !cur->is_unloaded()); | |
281 #ifndef PRODUCT | |
282 if (TraceScavenge) { | |
283 cur->print_on(tty, is_live ? "scavenge root" : "dead scavenge root"); tty->cr(); | |
284 } | |
285 #endif //PRODUCT | |
286 if (is_live) | |
287 // Perform cur->oops_do(f), maybe just once per nmethod. | |
288 f->do_code_blob(cur); | |
289 } | |
290 | |
291 // Check for stray marks. | |
292 debug_only(verify_perm_nmethods(NULL)); | |
293 } | |
294 | |
295 void CodeCache::add_scavenge_root_nmethod(nmethod* nm) { | |
296 assert_locked_or_safepoint(CodeCache_lock); | |
297 nm->set_on_scavenge_root_list(); | |
298 nm->set_scavenge_root_link(_scavenge_root_nmethods); | |
299 set_scavenge_root_nmethods(nm); | |
300 print_trace("add_scavenge_root", nm); | |
301 } | |
302 | |
303 void CodeCache::drop_scavenge_root_nmethod(nmethod* nm) { | |
304 assert_locked_or_safepoint(CodeCache_lock); | |
305 print_trace("drop_scavenge_root", nm); | |
306 nmethod* last = NULL; | |
307 nmethod* cur = scavenge_root_nmethods(); | |
308 while (cur != NULL) { | |
309 nmethod* next = cur->scavenge_root_link(); | |
310 if (cur == nm) { | |
311 if (last != NULL) | |
312 last->set_scavenge_root_link(next); | |
313 else set_scavenge_root_nmethods(next); | |
314 nm->set_scavenge_root_link(NULL); | |
315 nm->clear_on_scavenge_root_list(); | |
316 return; | |
317 } | |
318 last = cur; | |
319 cur = next; | |
320 } | |
321 assert(false, "should have been on list"); | |
322 } | |
323 | |
324 void CodeCache::prune_scavenge_root_nmethods() { | |
325 assert_locked_or_safepoint(CodeCache_lock); | |
326 debug_only(mark_scavenge_root_nmethods()); | |
327 | |
328 nmethod* last = NULL; | |
329 nmethod* cur = scavenge_root_nmethods(); | |
330 while (cur != NULL) { | |
331 nmethod* next = cur->scavenge_root_link(); | |
332 debug_only(cur->clear_scavenge_root_marked()); | |
333 assert(cur->scavenge_root_not_marked(), ""); | |
334 assert(cur->on_scavenge_root_list(), "else shouldn't be on this list"); | |
335 | |
336 if (!cur->is_zombie() && !cur->is_unloaded() | |
337 && cur->detect_scavenge_root_oops()) { | |
338 // Keep it. Advance 'last' to prevent deletion. | |
339 last = cur; | |
340 } else { | |
341 // Prune it from the list, so we don't have to look at it any more. | |
342 print_trace("prune_scavenge_root", cur); | |
343 cur->set_scavenge_root_link(NULL); | |
344 cur->clear_on_scavenge_root_list(); | |
345 if (last != NULL) | |
346 last->set_scavenge_root_link(next); | |
347 else set_scavenge_root_nmethods(next); | |
348 } | |
349 cur = next; | |
350 } | |
351 | |
352 // Check for stray marks. | |
353 debug_only(verify_perm_nmethods(NULL)); | |
354 } | |
355 | |
356 #ifndef PRODUCT | |
357 void CodeCache::asserted_non_scavengable_nmethods_do(CodeBlobClosure* f) { | |
358 // While we are here, verify the integrity of the list. | |
359 mark_scavenge_root_nmethods(); | |
360 for (nmethod* cur = scavenge_root_nmethods(); cur != NULL; cur = cur->scavenge_root_link()) { | |
361 assert(cur->on_scavenge_root_list(), "else shouldn't be on this list"); | |
362 cur->clear_scavenge_root_marked(); | |
363 } | |
364 verify_perm_nmethods(f); | |
365 } | |
366 | |
367 // Temporarily mark nmethods that are claimed to be on the non-perm list. | |
368 void CodeCache::mark_scavenge_root_nmethods() { | |
369 FOR_ALL_ALIVE_BLOBS(cb) { | |
370 if (cb->is_nmethod()) { | |
371 nmethod *nm = (nmethod*)cb; | |
372 assert(nm->scavenge_root_not_marked(), "clean state"); | |
373 if (nm->on_scavenge_root_list()) | |
374 nm->set_scavenge_root_marked(); | |
375 } | |
376 } | |
377 } | |
378 | |
379 // If the closure is given, run it on the unlisted nmethods. | |
380 // Also make sure that the effects of mark_scavenge_root_nmethods is gone. | |
381 void CodeCache::verify_perm_nmethods(CodeBlobClosure* f_or_null) { | |
382 FOR_ALL_ALIVE_BLOBS(cb) { | |
383 bool call_f = (f_or_null != NULL); | |
384 if (cb->is_nmethod()) { | |
385 nmethod *nm = (nmethod*)cb; | |
386 assert(nm->scavenge_root_not_marked(), "must be already processed"); | |
387 if (nm->on_scavenge_root_list()) | |
388 call_f = false; // don't show this one to the client | |
389 nm->verify_scavenge_root_oops(); | |
390 } else { | |
391 call_f = false; // not an nmethod | |
392 } | |
393 if (call_f) f_or_null->do_code_blob(cb); | |
394 } | |
395 } | |
396 #endif //PRODUCT | |
269 | 397 |
270 void CodeCache::gc_prologue() { | 398 void CodeCache::gc_prologue() { |
399 assert(!nmethod::oops_do_marking_is_active(), "oops_do_marking_epilogue must be called"); | |
271 } | 400 } |
272 | 401 |
273 | 402 |
274 void CodeCache::gc_epilogue() { | 403 void CodeCache::gc_epilogue() { |
275 assert_locked_or_safepoint(CodeCache_lock); | 404 assert_locked_or_safepoint(CodeCache_lock); |
283 debug_only(nm->verify();) | 412 debug_only(nm->verify();) |
284 } | 413 } |
285 cb->fix_oop_relocations(); | 414 cb->fix_oop_relocations(); |
286 } | 415 } |
287 set_needs_cache_clean(false); | 416 set_needs_cache_clean(false); |
417 prune_scavenge_root_nmethods(); | |
418 assert(!nmethod::oops_do_marking_is_active(), "oops_do_marking_prologue must be called"); | |
288 } | 419 } |
289 | 420 |
290 | 421 |
291 address CodeCache::first_address() { | 422 address CodeCache::first_address() { |
292 assert_locked_or_safepoint(CodeCache_lock); | 423 assert_locked_or_safepoint(CodeCache_lock); |
503 #ifndef PRODUCT | 634 #ifndef PRODUCT |
504 | 635 |
505 void CodeCache::verify_if_often() { | 636 void CodeCache::verify_if_often() { |
506 if (VerifyCodeCacheOften) { | 637 if (VerifyCodeCacheOften) { |
507 _heap->verify(); | 638 _heap->verify(); |
639 } | |
640 } | |
641 | |
642 void CodeCache::print_trace(const char* event, CodeBlob* cb, int size) { | |
643 if (PrintCodeCache2) { // Need to add a new flag | |
644 ResourceMark rm; | |
645 if (size == 0) size = cb->size(); | |
646 tty->print_cr("CodeCache %s: addr: " INTPTR_FORMAT ", size: 0x%x", event, cb, size); | |
508 } | 647 } |
509 } | 648 } |
510 | 649 |
511 void CodeCache::print_internals() { | 650 void CodeCache::print_internals() { |
512 int nmethodCount = 0; | 651 int nmethodCount = 0; |