src/share/vm/runtime/sweeper.cpp

changeset 2916
f52ed367b66d
parent 2764
dbccacb79c63
child 3572
cfdfbeac0a5b
     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  

mercurial