src/share/vm/gc_implementation/g1/bufferingOopClosure.hpp

Wed, 25 Mar 2009 13:10:54 -0700

author
apetrusenko
date
Wed, 25 Mar 2009 13:10:54 -0700
changeset 1112
96b229c54d1e
parent 777
37f87013dfd8
child 1280
df6caf649ff7
permissions
-rw-r--r--

6543938: G1: remove the concept of popularity
Reviewed-by: iveresov, tonyp

     1 /*
     2  * Copyright 2001-2007 Sun Microsystems, Inc.  All Rights Reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     8  *
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    12  * version 2 for more details (a copy is included in the LICENSE file that
    13  * accompanied this code).
    14  *
    15  * You should have received a copy of the GNU General Public License version
    16  * 2 along with this work; if not, write to the Free Software Foundation,
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    18  *
    19  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    20  * CA 95054 USA or visit www.sun.com if you need additional information or
    21  * have any questions.
    22  *
    23  */
    25 // A BufferingOops closure tries to separate out the cost of finding roots
    26 // from the cost of applying closures to them.  It maintains an array of
    27 // ref-containing locations.  Until the array is full, applying the closure
    28 // to an oop* merely records that location in the array.  Since this
    29 // closure app cost is small, an elapsed timer can approximately attribute
    30 // all of this cost to the cost of finding the roots.  When the array fills
    31 // up, the wrapped closure is applied to all elements, keeping track of
    32 // this elapsed time of this process, and leaving the array empty.
    33 // The caller must be sure to call "done" to process any unprocessed
    34 // buffered entriess.
    36 class Generation;
    37 class HeapRegion;
    39 class BufferingOopClosure: public OopClosure {
    40 protected:
    41   enum PrivateConstants {
    42     BufferLength = 1024
    43   };
    45   oop          *_buffer[BufferLength];
    46   oop         **_buffer_top;
    47   oop         **_buffer_curr;
    49   OopClosure  *_oc;
    50   double       _closure_app_seconds;
    52   void process_buffer () {
    54     double start = os::elapsedTime();
    55     for (oop **curr = _buffer; curr < _buffer_curr; ++curr) {
    56       _oc->do_oop(*curr);
    57     }
    58     _buffer_curr = _buffer;
    59     _closure_app_seconds += (os::elapsedTime() - start);
    60   }
    62 public:
    63   virtual void do_oop(narrowOop* p) {
    64     guarantee(false, "NYI");
    65   }
    66   virtual void do_oop(oop *p) {
    67     if (_buffer_curr == _buffer_top) {
    68       process_buffer();
    69     }
    71     *_buffer_curr = p;
    72     ++_buffer_curr;
    73   }
    74   void done () {
    75     if (_buffer_curr > _buffer) {
    76       process_buffer();
    77     }
    78   }
    79   double closure_app_seconds () {
    80     return _closure_app_seconds;
    81   }
    82   BufferingOopClosure (OopClosure *oc) :
    83     _oc(oc),
    84     _buffer_curr(_buffer), _buffer_top(_buffer + BufferLength),
    85     _closure_app_seconds(0.0) { }
    86 };
    88 class BufferingOopsInGenClosure: public OopsInGenClosure {
    89   BufferingOopClosure _boc;
    90   OopsInGenClosure* _oc;
    91 public:
    92   BufferingOopsInGenClosure(OopsInGenClosure *oc) :
    93     _boc(oc), _oc(oc) {}
    95   virtual void do_oop(narrowOop* p) {
    96     guarantee(false, "NYI");
    97   }
    99   virtual void do_oop(oop* p) {
   100     assert(generation()->is_in_reserved(p), "Must be in!");
   101     _boc.do_oop(p);
   102   }
   104   void done() {
   105     _boc.done();
   106   }
   108   double closure_app_seconds () {
   109     return _boc.closure_app_seconds();
   110   }
   112   void set_generation(Generation* gen) {
   113     OopsInGenClosure::set_generation(gen);
   114     _oc->set_generation(gen);
   115   }
   117   void reset_generation() {
   118     // Make sure we finish the current work with the current generation.
   119     _boc.done();
   120     OopsInGenClosure::reset_generation();
   121     _oc->reset_generation();
   122   }
   124 };
   127 class BufferingOopsInHeapRegionClosure: public OopsInHeapRegionClosure {
   128 private:
   129   enum PrivateConstants {
   130     BufferLength = 1024
   131   };
   133   oop                      *_buffer[BufferLength];
   134   oop                     **_buffer_top;
   135   oop                     **_buffer_curr;
   137   HeapRegion               *_hr_buffer[BufferLength];
   138   HeapRegion              **_hr_curr;
   140   OopsInHeapRegionClosure  *_oc;
   141   double                    _closure_app_seconds;
   143   void process_buffer () {
   145     assert((_hr_curr - _hr_buffer) == (_buffer_curr - _buffer),
   146            "the two lengths should be the same");
   148     double start = os::elapsedTime();
   149     HeapRegion **hr_curr = _hr_buffer;
   150     HeapRegion *hr_prev = NULL;
   151     for (oop **curr = _buffer; curr < _buffer_curr; ++curr) {
   152       HeapRegion *region = *hr_curr;
   153       if (region != hr_prev) {
   154         _oc->set_region(region);
   155         hr_prev = region;
   156       }
   157       _oc->do_oop(*curr);
   158       ++hr_curr;
   159     }
   160     _buffer_curr = _buffer;
   161     _hr_curr = _hr_buffer;
   162     _closure_app_seconds += (os::elapsedTime() - start);
   163   }
   165 public:
   166   virtual void do_oop(narrowOop *p) {
   167     guarantee(false, "NYI");
   168   }
   170   virtual void do_oop(oop *p) {
   171     if (_buffer_curr == _buffer_top) {
   172       assert(_hr_curr > _hr_buffer, "_hr_curr should be consistent with _buffer_curr");
   173       process_buffer();
   174     }
   176     *_buffer_curr = p;
   177     ++_buffer_curr;
   178     *_hr_curr = _from;
   179     ++_hr_curr;
   180   }
   181   void done () {
   182     if (_buffer_curr > _buffer) {
   183       assert(_hr_curr > _hr_buffer, "_hr_curr should be consistent with _buffer_curr");
   184       process_buffer();
   185     }
   186   }
   187   double closure_app_seconds () {
   188     return _closure_app_seconds;
   189   }
   190   BufferingOopsInHeapRegionClosure (OopsInHeapRegionClosure *oc) :
   191     _oc(oc),
   192     _buffer_curr(_buffer), _buffer_top(_buffer + BufferLength),
   193     _hr_curr(_hr_buffer),
   194     _closure_app_seconds(0.0) { }
   195 };

mercurial