201 int marked = 0; 202 int removed = 0; 203 while (b != NULL) { 204 nmethod* nm = b->get_nmethod(); 205 if (b->count() > 0 && nm->is_alive() && !nm->is_marked_for_deoptimization()) { 206 nm->mark_for_deoptimization(); 207 marked++; 208 } 209 nmethodBucket* next = b->next(); 210 removed++; 211 delete b; 212 b = next; 213 } 214 set_has_stale_entries(false); 215 if (UsePerfData && removed > 0) { 216 _perf_total_buckets_deallocated_count->inc(removed); 217 } 218 return marked; 219 } 220 221 #ifndef PRODUCT 222 void DependencyContext::print_dependent_nmethods(bool verbose) { 223 int idx = 0; 224 for (nmethodBucket* b = dependencies(); b != NULL; b = b->next()) { 225 nmethod* nm = b->get_nmethod(); 226 tty->print("[%d] count=%d { ", idx++, b->count()); 227 if (!verbose) { 228 nm->print_on(tty, "nmethod"); 229 tty->print_cr(" } "); 230 } else { 231 nm->print(); 232 nm->print_dependencies(); 233 tty->print_cr("--- } "); 234 } 235 } 236 } 237 238 bool DependencyContext::is_dependent_nmethod(nmethod* nm) { 239 for (nmethodBucket* b = dependencies(); b != NULL; b = b->next()) { 240 if (nm == b->get_nmethod()) { 254 } 255 return false; 256 } 257 258 #endif //PRODUCT 259 260 int nmethodBucket::decrement() { 261 return Atomic::add(-1, (volatile int *)&_count); 262 } 263 264 /////////////// Unit tests /////////////// 265 266 #ifndef PRODUCT 267 268 class TestDependencyContext { 269 public: 270 nmethod* _nmethods[3]; 271 272 intptr_t _dependency_context; 273 274 TestDependencyContext() : _dependency_context(DependencyContext::EMPTY) { 275 CodeCache_lock->lock_without_safepoint_check(); 276 277 DependencyContext depContext(&_dependency_context); 278 279 _nmethods[0] = reinterpret_cast<nmethod*>(0x8 * 0); 280 _nmethods[1] = reinterpret_cast<nmethod*>(0x8 * 1); 281 _nmethods[2] = reinterpret_cast<nmethod*>(0x8 * 2); 282 283 depContext.add_dependent_nmethod(_nmethods[2]); 284 depContext.add_dependent_nmethod(_nmethods[1]); 285 depContext.add_dependent_nmethod(_nmethods[0]); 286 } 287 288 ~TestDependencyContext() { 289 wipe(); 290 CodeCache_lock->unlock(); 291 } 292 293 static void testRemoveDependentNmethod(int id, bool delete_immediately) { 294 TestDependencyContext c; 295 DependencyContext depContext(&c._dependency_context); 296 assert(!has_stale_entries(depContext), "check"); 297 298 nmethod* nm = c._nmethods[id]; 299 depContext.remove_dependent_nmethod(nm, delete_immediately); 300 301 if (!delete_immediately) { 302 assert(has_stale_entries(depContext), "check"); 303 assert(depContext.is_dependent_nmethod(nm), "check"); 304 depContext.expunge_stale_entries(); 305 } 306 307 assert(!has_stale_entries(depContext), "check"); 308 assert(!depContext.is_dependent_nmethod(nm), "check"); 309 } 310 311 static void testRemoveDependentNmethod() { 312 testRemoveDependentNmethod(0, false); 313 testRemoveDependentNmethod(1, false); 314 testRemoveDependentNmethod(2, false); 315 316 testRemoveDependentNmethod(0, true); 317 testRemoveDependentNmethod(1, true); 318 testRemoveDependentNmethod(2, true); 319 } 320 321 static void test() { 322 testRemoveDependentNmethod(); 323 } 324 325 static bool has_stale_entries(DependencyContext ctx) { 326 assert(ctx.has_stale_entries() == ctx.find_stale_entries(), "check"); 327 return ctx.has_stale_entries(); 328 } 329 330 void wipe() { 331 DependencyContext ctx(&_dependency_context); 332 nmethodBucket* b = ctx.dependencies(); 333 ctx.set_dependencies(NULL); 334 ctx.set_has_stale_entries(false); 335 while (b != NULL) { 336 nmethodBucket* next = b->next(); 337 delete b; 338 b = next; 339 } 340 } 341 }; 342 343 void TestDependencyContext_test() { 344 TestDependencyContext::test(); 345 } 346 347 #endif // PRODUCT | 201 int marked = 0; 202 int removed = 0; 203 while (b != NULL) { 204 nmethod* nm = b->get_nmethod(); 205 if (b->count() > 0 && nm->is_alive() && !nm->is_marked_for_deoptimization()) { 206 nm->mark_for_deoptimization(); 207 marked++; 208 } 209 nmethodBucket* next = b->next(); 210 removed++; 211 delete b; 212 b = next; 213 } 214 set_has_stale_entries(false); 215 if (UsePerfData && removed > 0) { 216 _perf_total_buckets_deallocated_count->inc(removed); 217 } 218 return marked; 219 } 220 221 void DependencyContext::wipe() { 222 assert_locked_or_safepoint(CodeCache_lock); 223 nmethodBucket* b = dependencies(); 224 set_dependencies(NULL); 225 set_has_stale_entries(false); 226 while (b != NULL) { 227 nmethodBucket* next = b->next(); 228 delete b; 229 b = next; 230 } 231 } 232 233 #ifndef PRODUCT 234 void DependencyContext::print_dependent_nmethods(bool verbose) { 235 int idx = 0; 236 for (nmethodBucket* b = dependencies(); b != NULL; b = b->next()) { 237 nmethod* nm = b->get_nmethod(); 238 tty->print("[%d] count=%d { ", idx++, b->count()); 239 if (!verbose) { 240 nm->print_on(tty, "nmethod"); 241 tty->print_cr(" } "); 242 } else { 243 nm->print(); 244 nm->print_dependencies(); 245 tty->print_cr("--- } "); 246 } 247 } 248 } 249 250 bool DependencyContext::is_dependent_nmethod(nmethod* nm) { 251 for (nmethodBucket* b = dependencies(); b != NULL; b = b->next()) { 252 if (nm == b->get_nmethod()) { 266 } 267 return false; 268 } 269 270 #endif //PRODUCT 271 272 int nmethodBucket::decrement() { 273 return Atomic::add(-1, (volatile int *)&_count); 274 } 275 276 /////////////// Unit tests /////////////// 277 278 #ifndef PRODUCT 279 280 class TestDependencyContext { 281 public: 282 nmethod* _nmethods[3]; 283 284 intptr_t _dependency_context; 285 286 DependencyContext dependencies() { 287 DependencyContext depContext(&_dependency_context); 288 return depContext; 289 } 290 291 TestDependencyContext() : _dependency_context(DependencyContext::EMPTY) { 292 CodeCache_lock->lock_without_safepoint_check(); 293 294 _nmethods[0] = reinterpret_cast<nmethod*>(0x8 * 0); 295 _nmethods[1] = reinterpret_cast<nmethod*>(0x8 * 1); 296 _nmethods[2] = reinterpret_cast<nmethod*>(0x8 * 2); 297 298 dependencies().add_dependent_nmethod(_nmethods[2]); 299 dependencies().add_dependent_nmethod(_nmethods[1]); 300 dependencies().add_dependent_nmethod(_nmethods[0]); 301 } 302 303 ~TestDependencyContext() { 304 dependencies().wipe(); 305 CodeCache_lock->unlock(); 306 } 307 308 static void testRemoveDependentNmethod(int id, bool delete_immediately) { 309 TestDependencyContext c; 310 DependencyContext depContext = c.dependencies(); 311 assert(!has_stale_entries(depContext), "check"); 312 313 nmethod* nm = c._nmethods[id]; 314 depContext.remove_dependent_nmethod(nm, delete_immediately); 315 316 if (!delete_immediately) { 317 assert(has_stale_entries(depContext), "check"); 318 assert(depContext.is_dependent_nmethod(nm), "check"); 319 depContext.expunge_stale_entries(); 320 } 321 322 assert(!has_stale_entries(depContext), "check"); 323 assert(!depContext.is_dependent_nmethod(nm), "check"); 324 } 325 326 static void testRemoveDependentNmethod() { 327 testRemoveDependentNmethod(0, false); 328 testRemoveDependentNmethod(1, false); 329 testRemoveDependentNmethod(2, false); 330 331 testRemoveDependentNmethod(0, true); 332 testRemoveDependentNmethod(1, true); 333 testRemoveDependentNmethod(2, true); 334 } 335 336 static void test() { 337 testRemoveDependentNmethod(); 338 } 339 340 static bool has_stale_entries(DependencyContext ctx) { 341 assert(ctx.has_stale_entries() == ctx.find_stale_entries(), "check"); 342 return ctx.has_stale_entries(); 343 } 344 }; 345 346 void TestDependencyContext_test() { 347 TestDependencyContext::test(); 348 } 349 350 #endif // PRODUCT |