comparison src/share/vm/runtime/sweeper.cpp @ 3384:f52ed367b66d

6996747: SIGSEGV in nmethod::cleanup_inline_caches / CompiledIC::verify Reviewed-by: kvn, iveresov
author never
date Mon, 16 May 2011 22:16:44 -0700
parents dbccacb79c63
children dc7902820c9b cfdfbeac0a5b
comparison
equal deleted inserted replaced
3383:38569792a45a 3384:f52ed367b66d
35 #include "runtime/sweeper.hpp" 35 #include "runtime/sweeper.hpp"
36 #include "runtime/vm_operations.hpp" 36 #include "runtime/vm_operations.hpp"
37 #include "utilities/events.hpp" 37 #include "utilities/events.hpp"
38 #include "utilities/xmlstream.hpp" 38 #include "utilities/xmlstream.hpp"
39 39
40 #ifdef ASSERT
41
42 #define SWEEP(nm) record_sweep(nm, __LINE__)
43 // Sweeper logging code
44 class SweeperRecord {
45 public:
46 int traversal;
47 int invocation;
48 int compile_id;
49 long traversal_mark;
50 int state;
51 const char* kind;
52 address vep;
53 address uep;
54 int line;
55
56 void print() {
57 tty->print_cr("traversal = %d invocation = %d compile_id = %d %s uep = " PTR_FORMAT " vep = "
58 PTR_FORMAT " state = %d traversal_mark %d line = %d",
59 traversal,
60 invocation,
61 compile_id,
62 kind == NULL ? "" : kind,
63 uep,
64 vep,
65 state,
66 traversal_mark,
67 line);
68 }
69 };
70
71 static int _sweep_index = 0;
72 static SweeperRecord* _records = NULL;
73
74 void NMethodSweeper::report_events(int id, address entry) {
75 if (_records != NULL) {
76 for (int i = _sweep_index; i < SweeperLogEntries; i++) {
77 if (_records[i].uep == entry ||
78 _records[i].vep == entry ||
79 _records[i].compile_id == id) {
80 _records[i].print();
81 }
82 }
83 for (int i = 0; i < _sweep_index; i++) {
84 if (_records[i].uep == entry ||
85 _records[i].vep == entry ||
86 _records[i].compile_id == id) {
87 _records[i].print();
88 }
89 }
90 }
91 }
92
93 void NMethodSweeper::report_events() {
94 if (_records != NULL) {
95 for (int i = _sweep_index; i < SweeperLogEntries; i++) {
96 // skip empty records
97 if (_records[i].vep == NULL) continue;
98 _records[i].print();
99 }
100 for (int i = 0; i < _sweep_index; i++) {
101 // skip empty records
102 if (_records[i].vep == NULL) continue;
103 _records[i].print();
104 }
105 }
106 }
107
108 void NMethodSweeper::record_sweep(nmethod* nm, int line) {
109 if (_records != NULL) {
110 _records[_sweep_index].traversal = _traversals;
111 _records[_sweep_index].traversal_mark = nm->_stack_traversal_mark;
112 _records[_sweep_index].invocation = _invocations;
113 _records[_sweep_index].compile_id = nm->compile_id();
114 _records[_sweep_index].kind = nm->compile_kind();
115 _records[_sweep_index].state = nm->_state;
116 _records[_sweep_index].vep = nm->verified_entry_point();
117 _records[_sweep_index].uep = nm->entry_point();
118 _records[_sweep_index].line = line;
119
120 _sweep_index = (_sweep_index + 1) % SweeperLogEntries;
121 }
122 }
123 #else
124 #define SWEEP(nm)
125 #endif
126
127
40 long NMethodSweeper::_traversals = 0; // No. of stack traversals performed 128 long NMethodSweeper::_traversals = 0; // No. of stack traversals performed
41 nmethod* NMethodSweeper::_current = NULL; // Current nmethod 129 nmethod* NMethodSweeper::_current = NULL; // Current nmethod
42 int NMethodSweeper::_seen = 0 ; // No. of nmethods we have currently processed in current pass of CodeCache 130 int NMethodSweeper::_seen = 0 ; // No. of nmethods we have currently processed in current pass of CodeCache
43 131
44 volatile int NMethodSweeper::_invocations = 0; // No. of invocations left until we are completed with this pass 132 volatile int NMethodSweeper::_invocations = 0; // No. of invocations left until we are completed with this pass
135 // Only one thread at a time will sweep 223 // Only one thread at a time will sweep
136 jint old = Atomic::cmpxchg( 1, &_sweep_started, 0 ); 224 jint old = Atomic::cmpxchg( 1, &_sweep_started, 0 );
137 if (old != 0) { 225 if (old != 0) {
138 return; 226 return;
139 } 227 }
228 #ifdef ASSERT
229 if (LogSweeper && _records == NULL) {
230 // Create the ring buffer for the logging code
231 _records = NEW_C_HEAP_ARRAY(SweeperRecord, SweeperLogEntries);
232 memset(_records, 0, sizeof(SweeperRecord) * SweeperLogEntries);
233 }
234 #endif
140 if (_invocations > 0) { 235 if (_invocations > 0) {
141 sweep_code_cache(); 236 sweep_code_cache();
142 _invocations--; 237 _invocations--;
143 } 238 }
144 _sweep_started = 0; 239 _sweep_started = 0;
211 if (_invocations == 1) { 306 if (_invocations == 1) {
212 log_sweep("finished"); 307 log_sweep("finished");
213 } 308 }
214 } 309 }
215 310
311 class NMethodMarker: public StackObj {
312 private:
313 CompilerThread* _thread;
314 public:
315 NMethodMarker(nmethod* nm) {
316 _thread = CompilerThread::current();
317 _thread->set_scanned_nmethod(nm);
318 }
319 ~NMethodMarker() {
320 _thread->set_scanned_nmethod(NULL);
321 }
322 };
323
216 324
217 void NMethodSweeper::process_nmethod(nmethod *nm) { 325 void NMethodSweeper::process_nmethod(nmethod *nm) {
218 assert(!CodeCache_lock->owned_by_self(), "just checking"); 326 assert(!CodeCache_lock->owned_by_self(), "just checking");
327
328 // Make sure this nmethod doesn't get unloaded during the scan,
329 // since the locks acquired below might safepoint.
330 NMethodMarker nmm(nm);
331
332 SWEEP(nm);
219 333
220 // Skip methods that are currently referenced by the VM 334 // Skip methods that are currently referenced by the VM
221 if (nm->is_locked_by_vm()) { 335 if (nm->is_locked_by_vm()) {
222 // But still remember to clean-up inline caches for alive nmethods 336 // But still remember to clean-up inline caches for alive nmethods
223 if (nm->is_alive()) { 337 if (nm->is_alive()) {
224 // Clean-up all inline caches that points to zombie/non-reentrant methods 338 // Clean-up all inline caches that points to zombie/non-reentrant methods
225 MutexLocker cl(CompiledIC_lock); 339 MutexLocker cl(CompiledIC_lock);
226 nm->cleanup_inline_caches(); 340 nm->cleanup_inline_caches();
341 SWEEP(nm);
227 } else { 342 } else {
228 _locked_seen++; 343 _locked_seen++;
344 SWEEP(nm);
229 } 345 }
230 return; 346 return;
231 } 347 }
232 348
233 if (nm->is_zombie()) { 349 if (nm->is_zombie()) {
245 if (PrintMethodFlushing && Verbose) { 361 if (PrintMethodFlushing && Verbose) {
246 tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (zombie) being marked for reclamation", nm->compile_id(), nm); 362 tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (zombie) being marked for reclamation", nm->compile_id(), nm);
247 } 363 }
248 nm->mark_for_reclamation(); 364 nm->mark_for_reclamation();
249 _rescan = true; 365 _rescan = true;
366 SWEEP(nm);
250 } 367 }
251 } else if (nm->is_not_entrant()) { 368 } else if (nm->is_not_entrant()) {
252 // If there is no current activations of this method on the 369 // If there is no current activations of this method on the
253 // stack we can safely convert it to a zombie method 370 // stack we can safely convert it to a zombie method
254 if (nm->can_not_entrant_be_converted()) { 371 if (nm->can_not_entrant_be_converted()) {
255 if (PrintMethodFlushing && Verbose) { 372 if (PrintMethodFlushing && Verbose) {
256 tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (not entrant) being made zombie", nm->compile_id(), nm); 373 tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (not entrant) being made zombie", nm->compile_id(), nm);
257 } 374 }
258 nm->make_zombie(); 375 nm->make_zombie();
259 _rescan = true; 376 _rescan = true;
377 SWEEP(nm);
260 } else { 378 } else {
261 // Still alive, clean up its inline caches 379 // Still alive, clean up its inline caches
262 MutexLocker cl(CompiledIC_lock); 380 MutexLocker cl(CompiledIC_lock);
263 nm->cleanup_inline_caches(); 381 nm->cleanup_inline_caches();
264 // we coudn't transition this nmethod so don't immediately 382 // we coudn't transition this nmethod so don't immediately
265 // request a rescan. If this method stays on the stack for a 383 // request a rescan. If this method stays on the stack for a
266 // long time we don't want to keep rescanning the code cache. 384 // long time we don't want to keep rescanning the code cache.
267 _not_entrant_seen_on_stack++; 385 _not_entrant_seen_on_stack++;
386 SWEEP(nm);
268 } 387 }
269 } else if (nm->is_unloaded()) { 388 } else if (nm->is_unloaded()) {
270 // Unloaded code, just make it a zombie 389 // Unloaded code, just make it a zombie
271 if (PrintMethodFlushing && Verbose) 390 if (PrintMethodFlushing && Verbose)
272 tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (unloaded) being made zombie", nm->compile_id(), nm); 391 tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (unloaded) being made zombie", nm->compile_id(), nm);
273 if (nm->is_osr_method()) { 392 if (nm->is_osr_method()) {
274 // No inline caches will ever point to osr methods, so we can just remove it 393 // No inline caches will ever point to osr methods, so we can just remove it
275 MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); 394 MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
395 SWEEP(nm);
276 nm->flush(); 396 nm->flush();
277 } else { 397 } else {
278 nm->make_zombie(); 398 nm->make_zombie();
279 _rescan = true; 399 _rescan = true;
400 SWEEP(nm);
280 } 401 }
281 } else { 402 } else {
282 assert(nm->is_alive(), "should be alive"); 403 assert(nm->is_alive(), "should be alive");
283 404
284 if (UseCodeCacheFlushing) { 405 if (UseCodeCacheFlushing) {
291 } 412 }
292 413
293 // Clean-up all inline caches that points to zombie/non-reentrant methods 414 // Clean-up all inline caches that points to zombie/non-reentrant methods
294 MutexLocker cl(CompiledIC_lock); 415 MutexLocker cl(CompiledIC_lock);
295 nm->cleanup_inline_caches(); 416 nm->cleanup_inline_caches();
417 SWEEP(nm);
296 } 418 }
297 } 419 }
298 420
299 // Code cache unloading: when compilers notice the code cache is getting full, 421 // Code cache unloading: when compilers notice the code cache is getting full,
300 // they will call a vm op that comes here. This code attempts to speculatively 422 // they will call a vm op that comes here. This code attempts to speculatively