1.1 --- a/src/share/vm/code/codeCache.cpp Tue Sep 15 11:09:34 2009 -0700 1.2 +++ b/src/share/vm/code/codeCache.cpp Tue Sep 15 21:53:47 2009 -0700 1.3 @@ -95,6 +95,7 @@ 1.4 int CodeCache::_number_of_blobs = 0; 1.5 int CodeCache::_number_of_nmethods_with_dependencies = 0; 1.6 bool CodeCache::_needs_cache_clean = false; 1.7 +nmethod* CodeCache::_scavenge_root_nmethods = NULL; 1.8 1.9 1.10 CodeBlob* CodeCache::first() { 1.11 @@ -148,10 +149,7 @@ 1.12 } 1.13 } 1.14 verify_if_often(); 1.15 - if (PrintCodeCache2) { // Need to add a new flag 1.16 - ResourceMark rm; 1.17 - tty->print_cr("CodeCache allocation: addr: " INTPTR_FORMAT ", size: 0x%x\n", cb, size); 1.18 - } 1.19 + print_trace("allocation", cb, size); 1.20 return cb; 1.21 } 1.22 1.23 @@ -159,10 +157,7 @@ 1.24 assert_locked_or_safepoint(CodeCache_lock); 1.25 verify_if_often(); 1.26 1.27 - if (PrintCodeCache2) { // Need to add a new flag 1.28 - ResourceMark rm; 1.29 - tty->print_cr("CodeCache free: addr: " INTPTR_FORMAT ", size: 0x%x\n", cb, cb->size()); 1.30 - } 1.31 + print_trace("free", cb); 1.32 if (cb->is_nmethod() && ((nmethod *)cb)->has_dependencies()) { 1.33 _number_of_nmethods_with_dependencies--; 1.34 } 1.35 @@ -260,14 +255,148 @@ 1.36 } 1.37 } 1.38 1.39 -void CodeCache::oops_do(OopClosure* f) { 1.40 +void CodeCache::blobs_do(CodeBlobClosure* f) { 1.41 assert_locked_or_safepoint(CodeCache_lock); 1.42 FOR_ALL_ALIVE_BLOBS(cb) { 1.43 - cb->oops_do(f); 1.44 + f->do_code_blob(cb); 1.45 + 1.46 +#ifdef ASSERT 1.47 + if (cb->is_nmethod()) 1.48 + ((nmethod*)cb)->verify_scavenge_root_oops(); 1.49 +#endif //ASSERT 1.50 } 1.51 } 1.52 1.53 +// Walk the list of methods which might contain non-perm oops. 1.54 +void CodeCache::scavenge_root_nmethods_do(CodeBlobClosure* f) { 1.55 + assert_locked_or_safepoint(CodeCache_lock); 1.56 + debug_only(mark_scavenge_root_nmethods()); 1.57 + 1.58 + for (nmethod* cur = scavenge_root_nmethods(); cur != NULL; cur = cur->scavenge_root_link()) { 1.59 + debug_only(cur->clear_scavenge_root_marked()); 1.60 + assert(cur->scavenge_root_not_marked(), ""); 1.61 + assert(cur->on_scavenge_root_list(), "else shouldn't be on this list"); 1.62 + 1.63 + bool is_live = (!cur->is_zombie() && !cur->is_unloaded()); 1.64 +#ifndef PRODUCT 1.65 + if (TraceScavenge) { 1.66 + cur->print_on(tty, is_live ? "scavenge root" : "dead scavenge root"); tty->cr(); 1.67 + } 1.68 +#endif //PRODUCT 1.69 + if (is_live) 1.70 + // Perform cur->oops_do(f), maybe just once per nmethod. 1.71 + f->do_code_blob(cur); 1.72 + } 1.73 + 1.74 + // Check for stray marks. 1.75 + debug_only(verify_perm_nmethods(NULL)); 1.76 +} 1.77 + 1.78 +void CodeCache::add_scavenge_root_nmethod(nmethod* nm) { 1.79 + assert_locked_or_safepoint(CodeCache_lock); 1.80 + nm->set_on_scavenge_root_list(); 1.81 + nm->set_scavenge_root_link(_scavenge_root_nmethods); 1.82 + set_scavenge_root_nmethods(nm); 1.83 + print_trace("add_scavenge_root", nm); 1.84 +} 1.85 + 1.86 +void CodeCache::drop_scavenge_root_nmethod(nmethod* nm) { 1.87 + assert_locked_or_safepoint(CodeCache_lock); 1.88 + print_trace("drop_scavenge_root", nm); 1.89 + nmethod* last = NULL; 1.90 + nmethod* cur = scavenge_root_nmethods(); 1.91 + while (cur != NULL) { 1.92 + nmethod* next = cur->scavenge_root_link(); 1.93 + if (cur == nm) { 1.94 + if (last != NULL) 1.95 + last->set_scavenge_root_link(next); 1.96 + else set_scavenge_root_nmethods(next); 1.97 + nm->set_scavenge_root_link(NULL); 1.98 + nm->clear_on_scavenge_root_list(); 1.99 + return; 1.100 + } 1.101 + last = cur; 1.102 + cur = next; 1.103 + } 1.104 + assert(false, "should have been on list"); 1.105 +} 1.106 + 1.107 +void CodeCache::prune_scavenge_root_nmethods() { 1.108 + assert_locked_or_safepoint(CodeCache_lock); 1.109 + debug_only(mark_scavenge_root_nmethods()); 1.110 + 1.111 + nmethod* last = NULL; 1.112 + nmethod* cur = scavenge_root_nmethods(); 1.113 + while (cur != NULL) { 1.114 + nmethod* next = cur->scavenge_root_link(); 1.115 + debug_only(cur->clear_scavenge_root_marked()); 1.116 + assert(cur->scavenge_root_not_marked(), ""); 1.117 + assert(cur->on_scavenge_root_list(), "else shouldn't be on this list"); 1.118 + 1.119 + if (!cur->is_zombie() && !cur->is_unloaded() 1.120 + && cur->detect_scavenge_root_oops()) { 1.121 + // Keep it. Advance 'last' to prevent deletion. 1.122 + last = cur; 1.123 + } else { 1.124 + // Prune it from the list, so we don't have to look at it any more. 1.125 + print_trace("prune_scavenge_root", cur); 1.126 + cur->set_scavenge_root_link(NULL); 1.127 + cur->clear_on_scavenge_root_list(); 1.128 + if (last != NULL) 1.129 + last->set_scavenge_root_link(next); 1.130 + else set_scavenge_root_nmethods(next); 1.131 + } 1.132 + cur = next; 1.133 + } 1.134 + 1.135 + // Check for stray marks. 1.136 + debug_only(verify_perm_nmethods(NULL)); 1.137 +} 1.138 + 1.139 +#ifndef PRODUCT 1.140 +void CodeCache::asserted_non_scavengable_nmethods_do(CodeBlobClosure* f) { 1.141 + // While we are here, verify the integrity of the list. 1.142 + mark_scavenge_root_nmethods(); 1.143 + for (nmethod* cur = scavenge_root_nmethods(); cur != NULL; cur = cur->scavenge_root_link()) { 1.144 + assert(cur->on_scavenge_root_list(), "else shouldn't be on this list"); 1.145 + cur->clear_scavenge_root_marked(); 1.146 + } 1.147 + verify_perm_nmethods(f); 1.148 +} 1.149 + 1.150 +// Temporarily mark nmethods that are claimed to be on the non-perm list. 1.151 +void CodeCache::mark_scavenge_root_nmethods() { 1.152 + FOR_ALL_ALIVE_BLOBS(cb) { 1.153 + if (cb->is_nmethod()) { 1.154 + nmethod *nm = (nmethod*)cb; 1.155 + assert(nm->scavenge_root_not_marked(), "clean state"); 1.156 + if (nm->on_scavenge_root_list()) 1.157 + nm->set_scavenge_root_marked(); 1.158 + } 1.159 + } 1.160 +} 1.161 + 1.162 +// If the closure is given, run it on the unlisted nmethods. 1.163 +// Also make sure that the effects of mark_scavenge_root_nmethods is gone. 1.164 +void CodeCache::verify_perm_nmethods(CodeBlobClosure* f_or_null) { 1.165 + FOR_ALL_ALIVE_BLOBS(cb) { 1.166 + bool call_f = (f_or_null != NULL); 1.167 + if (cb->is_nmethod()) { 1.168 + nmethod *nm = (nmethod*)cb; 1.169 + assert(nm->scavenge_root_not_marked(), "must be already processed"); 1.170 + if (nm->on_scavenge_root_list()) 1.171 + call_f = false; // don't show this one to the client 1.172 + nm->verify_scavenge_root_oops(); 1.173 + } else { 1.174 + call_f = false; // not an nmethod 1.175 + } 1.176 + if (call_f) f_or_null->do_code_blob(cb); 1.177 + } 1.178 +} 1.179 +#endif //PRODUCT 1.180 + 1.181 void CodeCache::gc_prologue() { 1.182 + assert(!nmethod::oops_do_marking_is_active(), "oops_do_marking_epilogue must be called"); 1.183 } 1.184 1.185 1.186 @@ -285,6 +414,8 @@ 1.187 cb->fix_oop_relocations(); 1.188 } 1.189 set_needs_cache_clean(false); 1.190 + prune_scavenge_root_nmethods(); 1.191 + assert(!nmethod::oops_do_marking_is_active(), "oops_do_marking_prologue must be called"); 1.192 } 1.193 1.194 1.195 @@ -508,6 +639,14 @@ 1.196 } 1.197 } 1.198 1.199 +void CodeCache::print_trace(const char* event, CodeBlob* cb, int size) { 1.200 + if (PrintCodeCache2) { // Need to add a new flag 1.201 + ResourceMark rm; 1.202 + if (size == 0) size = cb->size(); 1.203 + tty->print_cr("CodeCache %s: addr: " INTPTR_FORMAT ", size: 0x%x", event, cb, size); 1.204 + } 1.205 +} 1.206 + 1.207 void CodeCache::print_internals() { 1.208 int nmethodCount = 0; 1.209 int runtimeStubCount = 0;