sweeper.cpp

Go to the documentation of this file.
00001 /* Copyright 1994 - 1996, LongView Technologies L.L.C. $Revision: 1.17 $ */
00002 /* Copyright (c) 2006, Sun Microsystems, Inc.
00003 All rights reserved.
00004 
00005 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the 
00006 following conditions are met:
00007 
00008     * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
00009     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following 
00010           disclaimer in the documentation and/or other materials provided with the distribution.
00011     * Neither the name of Sun Microsystems nor the names of its contributors may be used to endorse or promote products derived 
00012           from this software without specific prior written permission.
00013 
00014 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 
00015 NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
00016 THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
00017 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
00018 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
00019 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
00020 
00021 
00022 */
00023 
00024 # include "incls/_precompiled.incl"
00025 # include "incls/_sweeper.cpp.incl"
00026 # include <math.h>
00027 
00028 // The sweeper run at real_time ticks. We only swep if the interrupted
00029 // Delta process is in a well-defined state (see SweeperTask).
00030 // We might change the sweeper to sweep at preempt time like in the Self system.
00031 
00032 Sweeper*  Sweeper::_head           = NULL;
00033 int       Sweeper::sweep_seconds   = 0;
00034 bool      Sweeper::_is_running     = false;
00035 methodOop Sweeper::_active_method  = NULL;
00036 nmethod*  Sweeper::_active_nmethod = NULL;
00037 
00038 void Sweeper::print_all() {
00039   for (Sweeper* n = head(); n; n = n->next()) 
00040     n->print();
00041 }
00042 
00043 bool Sweeper::register_active_frame(frame fr) {
00044   if (fr.is_interpreted_frame()) {
00045     _active_method = fr.method();
00046     if (_active_method == NULL) return NULL;
00047     return true;
00048   } else if (fr.is_compiled_frame()) {
00049     _active_nmethod = findNMethod(fr.pc());
00050     return true;
00051   }
00052   return false;
00053 }
00054 
00055 void Sweeper::clear_active_frame() {
00056   _active_method  = NULL;
00057   _active_nmethod = NULL;
00058 }
00059 
00060 void Sweeper::step_all() {
00061   _is_running = true;
00062   ResourceMark rm;
00063   for (Sweeper* n = head(); n; n = n->next()) 
00064     n->step();
00065   sweep_seconds++;
00066   _is_running = false;
00067 }
00068 
00069 Sweeper::Sweeper() {
00070   _is_active   = false;
00071   _sweep_start = sweep_seconds;
00072 }
00073 
00074 void Sweeper::add(Sweeper* sweeper) {
00075   sweeper->_next = head();
00076   _head          = sweeper;
00077 }
00078 
00079 void Sweeper::step() {
00080   if (interval() == 0) return;
00081  
00082   if (!is_active() && (sweep_seconds - _sweep_start) >= interval()) {
00083     _sweep_start = sweep_seconds;
00084      activate();
00085   }
00086   if (is_active()) task();
00087 }
00088 
00089 void Sweeper::print() const {
00090   std->print_cr("%s", name());
00091 }
00092 
00093 void Sweeper::activate() {
00094   _is_active = true;
00095   LOG_EVENT1("Activating %s", name());
00096 }
00097 
00098 void Sweeper::deactivate() {
00099   _is_active = false;
00100   LOG_EVENT1("Deactivating %s", name());
00101 }
00102 
00103 // ---------------- HeapSweeper -----------------
00104 
00105 void HeapSweeper::activate() {
00106   mark = Universe::old_gen.bottom_mark();
00107   Sweeper::activate();
00108 }
00109 
00110 void HeapSweeper::task() {}
00111 
00112 // ---------------- CodeSweeper -----------------
00113 
00114 inline void CodeSweeper::updateInterval() {
00115   if (oldHalfLifeTime != CounterHalfLifeTime) {
00116     oldHalfLifeTime = CounterHalfLifeTime;
00117     CodeSweeperInterval = 4;                // for now, use fixed value; could adjust if necessary
00118     fractionPerTask = 8;
00119     const double log2 = 0.69314718055995;   // log(2)
00120     decayFactor = exp(log2 * CodeSweeperInterval * fractionPerTask / CounterHalfLifeTime);
00121     if (PrintCodeSweep) std->print("*method sweep: decay factor %f\n", decayFactor);
00122   }
00123 }
00124 
00125 
00126 int CodeSweeper::interval() const {
00127   ((CodeSweeper*)this)->updateInterval();
00128   return CodeSweeperInterval;
00129 }
00130 
00131 // ---------------- MethodSweeper -----------------
00132 
00133 
00134 void MethodSweeper::method_task(methodOop method) {
00135   if (method != Sweeper::active_method()) {
00136     if (method->invocation_count() > 0) {
00137       method->decay_invocation_count(decayFactor);
00138     }
00139     method->cleanup_inline_caches();
00140   } else {
00141     // Save the nmethod for next round
00142     set_excluded_method(Sweeper::active_method());
00143   }
00144 }
00145 
00146 int MethodSweeper::method_dict_task(objArrayOop methods) {
00147   int length = methods->length();
00148   for (int index = 1; index <= length; index++) {
00149     methodOop method = methodOop(methods->obj_at(index));
00150     assert(method->is_method(), "just checking");
00151     method_task(method);
00152   }
00153   return length;
00154 }
00155 
00156 int MethodSweeper::klass_task(klassOop klass) {
00157   int result = 0;
00158   Klass* k = klass->klass_part();
00159   // Fix the customized methods 
00160   result += method_dict_task(k->methods());
00161   result += method_dict_task(klass->klass()->klass_part()->methods());
00162   if (k->is_named_class()) {
00163     // Fix the mixin parts
00164     result += method_dict_task(k->mixin()->methods());
00165     result += method_dict_task(klass->klass()->klass_part()->mixin()->methods());
00166   }
00167 
00168   if (!k->has_superKlass()) return result;
00169   if (k->superKlass()->klass_part()->is_named_class()) return result;
00170   
00171   // super class is an unnamed class so we have to handle it
00172   result += klass_task(k->superKlass());
00173   return result;
00174 }
00175 
00176 void MethodSweeper::task() {
00177   // Prologue: check is there is leftover from last sweep
00178   if (excluded_method()) {
00179     methodOop m = excluded_method();
00180     set_excluded_method(NULL);
00181     method_task(m);
00182   }
00183 
00184   objArrayOop array     = Universe::systemDictionaryObj();
00185   int          length   = array->length();
00186   int number_of_entries = length / fractionPerTask;
00187   if (PrintCodeSweep) std->print("*method sweep: %d entries...", number_of_entries);
00188   TraceTime t("MethodSweep ", PrintCodeSweep);
00189 
00190   int end = (index + number_of_entries);
00191   if (end > length)
00192     end = length;
00193 
00194   int begin = index;
00195   int result = 0;
00196 
00197   for (; index <= end; index++) {
00198      associationOop assoc =  associationOop(array->obj_at(index));
00199      assert(assoc->is_association(), "just checking");
00200      if (assoc->is_constant() && assoc->value()->is_klass()) {
00201        int result = klass_task(klassOop(assoc->value()));
00202      }
00203   }
00204   LOG_EVENT3("MethodSweeper task [%d, %d] #%d", begin, end, result);
00205 
00206   if (index > length) deactivate();
00207 }
00208 
00209 void MethodSweeper::activate() {
00210   index = 1;
00211   Sweeper::activate();
00212 }
00213 
00214 // ---------------- ZoneSweeper -----------------
00215 
00216 void ZoneSweeper::nmethod_task(nmethod* nm) {
00217   if (nm != Sweeper::active_nmethod()) {
00218     nm->sweeper_step(decayFactor);
00219   } else {
00220     // Save the nmethod for next round
00221     set_excluded_nmethod(Sweeper::active_nmethod());
00222   }
00223 }
00224 
00225 void ZoneSweeper::task() {
00226   // Prologue: check is there is leftover from last sweep
00227   if (excluded_nmethod()) {
00228     nmethod* nm = excluded_nmethod();
00229     set_excluded_nmethod(NULL);
00230     nmethod_task(nm);
00231   }
00232 
00233   // %fix this:
00234   //    we need to validate next
00235   int total = Universe::code->numberOfNMethods();
00236   int todo = total / fractionPerTask;
00237   if (PrintCodeSweep) std->print("*zone sweep: %d of %d entries...", todo, total);
00238   TraceTime t("ZoneSweep ", PrintCodeSweep);
00239   
00240   for (int index = 0; index < todo; index++) {
00241     if (next == NULL) {
00242       deactivate(); 
00243       break;
00244     }
00245     nmethod_task(next);
00246     next = Universe::code->next_nm(next);
00247   }
00248 
00249   if (UseNMethodAging) {
00250     for (nmethod* nm = Universe::code->first_nm(); nm; nm = Universe::code->next_nm(nm)) {
00251       nm->incrementAge();
00252     }
00253   }
00254 }
00255 
00256 void ZoneSweeper::activate() {
00257   if (Universe::code->numberOfNMethods() > 0) {
00258     next = Universe::code->first_nm();
00259     _excluded_nmethod = NULL;
00260     Sweeper::activate();
00261   } else {
00262     deactivate();
00263   }
00264 }
00265 
00266 // The sweeper task is activated every second (1000 milliseconds).
00267 class SweeperTask : public PeriodicTask {
00268  private:
00269    int counter;
00270  public:
00271   SweeperTask() : PeriodicTask(100) {
00272     counter = 0;
00273   }
00274 
00275   void task() {
00276     // If we're idle forget about the tick.
00277     if (DeltaProcess::is_idle()) return;
00278     if (++counter > 10) {
00279       if (processSemaphore) return;
00280       if (last_Delta_fp)    return;
00281 
00282       if (Sweeper::register_active_frame(DeltaProcess::active()->profile_top_frame())) {
00283         Sweeper::step_all();
00284         Sweeper::clear_active_frame();
00285         counter -= 10;
00286       }
00287     }
00288   }
00289 };
00290 
00291 MethodSweeper* methodSweeper;
00292 
00293 void sweeper_init() {
00294   // Sweeper::add(new HeapSweeper());
00295   Sweeper::add(new ZoneSweeper());
00296   Sweeper::add(methodSweeper = new MethodSweeper());
00297 
00298   if (SweeperUseTimer) {
00299     SweeperTask* t = new SweeperTask;
00300     t->enroll();
00301   }
00302 }

Generated on Mon Oct 9 13:37:28 2006 for Strongtalk VM by  doxygen 1.4.7