1.1 --- a/src/share/vm/runtime/sweeper.cpp Mon May 16 14:21:16 2011 -0700 1.2 +++ b/src/share/vm/runtime/sweeper.cpp Mon May 16 22:16:44 2011 -0700 1.3 @@ -37,6 +37,94 @@ 1.4 #include "utilities/events.hpp" 1.5 #include "utilities/xmlstream.hpp" 1.6 1.7 +#ifdef ASSERT 1.8 + 1.9 +#define SWEEP(nm) record_sweep(nm, __LINE__) 1.10 +// Sweeper logging code 1.11 +class SweeperRecord { 1.12 + public: 1.13 + int traversal; 1.14 + int invocation; 1.15 + int compile_id; 1.16 + long traversal_mark; 1.17 + int state; 1.18 + const char* kind; 1.19 + address vep; 1.20 + address uep; 1.21 + int line; 1.22 + 1.23 + void print() { 1.24 + tty->print_cr("traversal = %d invocation = %d compile_id = %d %s uep = " PTR_FORMAT " vep = " 1.25 + PTR_FORMAT " state = %d traversal_mark %d line = %d", 1.26 + traversal, 1.27 + invocation, 1.28 + compile_id, 1.29 + kind == NULL ? "" : kind, 1.30 + uep, 1.31 + vep, 1.32 + state, 1.33 + traversal_mark, 1.34 + line); 1.35 + } 1.36 +}; 1.37 + 1.38 +static int _sweep_index = 0; 1.39 +static SweeperRecord* _records = NULL; 1.40 + 1.41 +void NMethodSweeper::report_events(int id, address entry) { 1.42 + if (_records != NULL) { 1.43 + for (int i = _sweep_index; i < SweeperLogEntries; i++) { 1.44 + if (_records[i].uep == entry || 1.45 + _records[i].vep == entry || 1.46 + _records[i].compile_id == id) { 1.47 + _records[i].print(); 1.48 + } 1.49 + } 1.50 + for (int i = 0; i < _sweep_index; i++) { 1.51 + if (_records[i].uep == entry || 1.52 + _records[i].vep == entry || 1.53 + _records[i].compile_id == id) { 1.54 + _records[i].print(); 1.55 + } 1.56 + } 1.57 + } 1.58 +} 1.59 + 1.60 +void NMethodSweeper::report_events() { 1.61 + if (_records != NULL) { 1.62 + for (int i = _sweep_index; i < SweeperLogEntries; i++) { 1.63 + // skip empty records 1.64 + if (_records[i].vep == NULL) continue; 1.65 + _records[i].print(); 1.66 + } 1.67 + for (int i = 0; i < _sweep_index; i++) { 1.68 + // skip empty records 1.69 + if (_records[i].vep == NULL) continue; 1.70 + _records[i].print(); 1.71 + } 1.72 + } 1.73 +} 1.74 + 1.75 +void NMethodSweeper::record_sweep(nmethod* nm, int line) { 1.76 + if (_records != NULL) { 1.77 + _records[_sweep_index].traversal = _traversals; 1.78 + _records[_sweep_index].traversal_mark = nm->_stack_traversal_mark; 1.79 + _records[_sweep_index].invocation = _invocations; 1.80 + _records[_sweep_index].compile_id = nm->compile_id(); 1.81 + _records[_sweep_index].kind = nm->compile_kind(); 1.82 + _records[_sweep_index].state = nm->_state; 1.83 + _records[_sweep_index].vep = nm->verified_entry_point(); 1.84 + _records[_sweep_index].uep = nm->entry_point(); 1.85 + _records[_sweep_index].line = line; 1.86 + 1.87 + _sweep_index = (_sweep_index + 1) % SweeperLogEntries; 1.88 + } 1.89 +} 1.90 +#else 1.91 +#define SWEEP(nm) 1.92 +#endif 1.93 + 1.94 + 1.95 long NMethodSweeper::_traversals = 0; // No. of stack traversals performed 1.96 nmethod* NMethodSweeper::_current = NULL; // Current nmethod 1.97 int NMethodSweeper::_seen = 0 ; // No. of nmethods we have currently processed in current pass of CodeCache 1.98 @@ -137,6 +225,13 @@ 1.99 if (old != 0) { 1.100 return; 1.101 } 1.102 +#ifdef ASSERT 1.103 + if (LogSweeper && _records == NULL) { 1.104 + // Create the ring buffer for the logging code 1.105 + _records = NEW_C_HEAP_ARRAY(SweeperRecord, SweeperLogEntries); 1.106 + memset(_records, 0, sizeof(SweeperRecord) * SweeperLogEntries); 1.107 + } 1.108 +#endif 1.109 if (_invocations > 0) { 1.110 sweep_code_cache(); 1.111 _invocations--; 1.112 @@ -213,10 +308,29 @@ 1.113 } 1.114 } 1.115 1.116 +class NMethodMarker: public StackObj { 1.117 + private: 1.118 + CompilerThread* _thread; 1.119 + public: 1.120 + NMethodMarker(nmethod* nm) { 1.121 + _thread = CompilerThread::current(); 1.122 + _thread->set_scanned_nmethod(nm); 1.123 + } 1.124 + ~NMethodMarker() { 1.125 + _thread->set_scanned_nmethod(NULL); 1.126 + } 1.127 +}; 1.128 + 1.129 1.130 void NMethodSweeper::process_nmethod(nmethod *nm) { 1.131 assert(!CodeCache_lock->owned_by_self(), "just checking"); 1.132 1.133 + // Make sure this nmethod doesn't get unloaded during the scan, 1.134 + // since the locks acquired below might safepoint. 1.135 + NMethodMarker nmm(nm); 1.136 + 1.137 + SWEEP(nm); 1.138 + 1.139 // Skip methods that are currently referenced by the VM 1.140 if (nm->is_locked_by_vm()) { 1.141 // But still remember to clean-up inline caches for alive nmethods 1.142 @@ -224,8 +338,10 @@ 1.143 // Clean-up all inline caches that points to zombie/non-reentrant methods 1.144 MutexLocker cl(CompiledIC_lock); 1.145 nm->cleanup_inline_caches(); 1.146 + SWEEP(nm); 1.147 } else { 1.148 _locked_seen++; 1.149 + SWEEP(nm); 1.150 } 1.151 return; 1.152 } 1.153 @@ -247,6 +363,7 @@ 1.154 } 1.155 nm->mark_for_reclamation(); 1.156 _rescan = true; 1.157 + SWEEP(nm); 1.158 } 1.159 } else if (nm->is_not_entrant()) { 1.160 // If there is no current activations of this method on the 1.161 @@ -257,6 +374,7 @@ 1.162 } 1.163 nm->make_zombie(); 1.164 _rescan = true; 1.165 + SWEEP(nm); 1.166 } else { 1.167 // Still alive, clean up its inline caches 1.168 MutexLocker cl(CompiledIC_lock); 1.169 @@ -265,6 +383,7 @@ 1.170 // request a rescan. If this method stays on the stack for a 1.171 // long time we don't want to keep rescanning the code cache. 1.172 _not_entrant_seen_on_stack++; 1.173 + SWEEP(nm); 1.174 } 1.175 } else if (nm->is_unloaded()) { 1.176 // Unloaded code, just make it a zombie 1.177 @@ -273,10 +392,12 @@ 1.178 if (nm->is_osr_method()) { 1.179 // No inline caches will ever point to osr methods, so we can just remove it 1.180 MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); 1.181 + SWEEP(nm); 1.182 nm->flush(); 1.183 } else { 1.184 nm->make_zombie(); 1.185 _rescan = true; 1.186 + SWEEP(nm); 1.187 } 1.188 } else { 1.189 assert(nm->is_alive(), "should be alive"); 1.190 @@ -293,6 +414,7 @@ 1.191 // Clean-up all inline caches that points to zombie/non-reentrant methods 1.192 MutexLocker cl(CompiledIC_lock); 1.193 nm->cleanup_inline_caches(); 1.194 + SWEEP(nm); 1.195 } 1.196 } 1.197