rSet.cpp

Go to the documentation of this file.
00001 /* Copyright 1994 - 1996 LongView Technologies L.L.C. $Revision: 1.32 $ */
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 
00025 # include "incls/_precompiled.incl"
00026 
00027 # include <string.h>
00028 
00029 # include "incls/_rSet.cpp.incl"
00030 
00031 // values of bytes in byte map: during normal operation (incl. scavenge),
00032 // bytes are either -1 (clean) or 0 (dirty); i.e., the interpreter / compiled code
00033 // clear a byte when storing into that card.
00034 // More precisely, the card being marked corrsponds to the object start, not
00035 // necessarily to the word being updated (e.g., if the object starts towards the
00036 // end of a card, the updated instance variable may be on the next card).  But for
00037 // objArrays, the precise card is marked so that we don't need to scavenge the
00038 // entire array.
00039 // During GC, the bytes are used to remember object sizes, see comment further below
00040 
00041 // To do list for the remembered set
00042 //
00043 // 1. Optimization suggested by Urs 9/30/95
00044 //    Speed up card scanning by comparing words for frequent case
00045 //    (A profile of Mark Sweep is necessary to make the call).
00046 // 2. Handle objArrays in a more effficient way. Scavenge only
00047 //    parts of the objArray with dirty cards.
00048 //    The current implementation is REALLY slow for huge tenured objArrays
00049 //    with few new pointers.
00050 
00051 rSet::rSet() {
00052    low_boundary = Universe::new_gen.low_boundary;
00053   high_boundary = Universe::old_gen.high_boundary;
00054   clear(); 
00055   Set_Byte_Map_Base(byte_for(NULL));
00056   assert(byte_for(low_boundary) == byte_map, "Checking start of map");
00057 }
00058 
00059 void* rSet::operator new(size_t size) {
00060   assert((int(Universe::new_gen.low_boundary) & (card_size - 1)) == 0,
00061          "new must start at card boundary");
00062   assert((int(Universe::old_gen.low_boundary) & (card_size - 1)) == 0,
00063          "old must start at card boundary");
00064   assert((int(Universe::old_gen.high_boundary) & (card_size - 1)) == 0,
00065          "old must end at card boundary");
00066   assert(card_size >= 512, "card_size must be at least 512");
00067   int bmsize =
00068     (Universe::old_gen.high_boundary - Universe::new_gen.low_boundary)
00069       / card_size;
00070   return AllocateHeap(size + bmsize, "rSet");
00071 }
00072 
00073 // copy the bits from an older, smaller bitmap, add area [start,end)
00074 rSet::rSet(rSet *old, char *start, char *end) {
00075   ShouldNotReachHere();
00076   /*
00077    low_boundary= Universe::new_gen.low_boundary;
00078   high_boundary= Universe::old_gen.high_boundary;
00079   char *old_low=  old->low_boundary;
00080   char *old_high= old->high_boundary;
00081   Set_Byte_Map_Base(byte_for(NULL));
00082   memcpy(byte_for(old_low),
00083          old->byte_for(old_low),
00084          old->byte_for(old_high) - old->byte_for(old_low));
00085   clear(byte_for(start), byte_for(end));
00086   delete old;
00087   */
00088 }  
00089 
00090 char* rSet::scavenge_contents(oldSpace* sp, char* begin, char* limit) {
00091   // make sure we are staring with a dirty page
00092   assert(!*begin, "check for dirty page");
00093 
00094   // Find object at page start
00095 
00096   oop* s = oop_for(begin);
00097 
00098   // Return if we're at the end.
00099   if (s >= sp->top()) return begin + 1;
00100 
00101   s = sp->object_start(s);
00102 
00103   char* end = begin+1;
00104 
00105   oop* object_end = NULL;
00106 
00107   while (!*end && end < limit) {
00108     while (!*end && end < limit) end++;
00109 
00110     // We now have a string of dirty pages [begin..end[
00111     oop* e = min(oop_for(end), (oop*)sp->top());
00112 
00113     if (e < (oop*)sp->top()) {
00114       // Find the object crossing the last dirty page
00115       object_end = sp->object_start(e);
00116       if (object_end != e) {
00117         // object starts on page boundary
00118         int size = as_memOop(object_end)->size();
00119         object_end += size;
00120       }
00121       end = byte_for(object_end);
00122     }
00123   }
00124 
00125   // Clear the cards
00126   for (char* i = begin; i < end; i++) *i = -1;
00127 
00128   // Find the end
00129   oop* e = min(oop_for(end), (oop*)sp->top());
00130 
00131   while (s < e) {
00132     memOop m = as_memOop(s);
00133     int size = m->scavenge_tenured_contents();
00134     assert(size = m->size(), "just checking");
00135     s += size;
00136   }
00137   return end;
00138 }
00139 
00140 void rSet::scavenge_contents(oldSpace* sp) {
00141   char* current_byte = byte_for(sp->bottom());
00142   char* end_byte     = byte_for(sp->top());
00143   // set sentinel for scan (dirty page)
00144   *(end_byte + 1) = 0;
00145 
00146   // scan over clean pages
00147   while (*current_byte) current_byte++;
00148 
00149   while (current_byte <= end_byte) {
00150     // Pass the dirty page on to scavenge_contents
00151     current_byte = scavenge_contents(sp, current_byte, end_byte);
00152 
00153     // scan over clean pages
00154     while (*current_byte) current_byte++;
00155   }
00156 }
00157 
00158 void rSet::print_set_for_space(oldSpace* sp) {
00159   char* current_byte = byte_for(sp->bottom());
00160   char* end_byte     = byte_for(sp->top());
00161   lprintf("%s: [%#lx, %#lx]\n", sp->name(), current_byte, end_byte);
00162   while (current_byte <= end_byte) {
00163     if (*current_byte) {
00164       lprintf("_");
00165     } else {
00166       lprintf("*");
00167     }
00168     current_byte++;
00169   }
00170   lprintf("\n");
00171 }
00172 
00173 int rSet::number_of_dirty_pages_in(oldSpace* sp) {
00174   int count = 0;
00175   char* current_byte = byte_for(sp->bottom());
00176   char* end_byte     = byte_for(sp->top());
00177   while (current_byte <= end_byte) {
00178     if (!*current_byte) count++;
00179     current_byte++;
00180   }
00181   return count;
00182 }
00183 
00184 class CheckDirtyClosure : public OopClosure {
00185  public:
00186   bool is_dirty;
00187 
00188   void clear() {
00189     is_dirty = false; 
00190   }
00191 
00192   void do_oop(oop* o) {
00193     if ((*o)->is_new()) {
00194       is_dirty = true;
00195       /*
00196       { FlagSetting fs(PrintObjectID, false);
00197         std->print("0x%lx ", o);
00198         (*o)->print_value();
00199         std->cr();
00200       }
00201       */
00202     }
00203   }
00204 };
00205 
00206 bool rSet::has_page_dirty_objects(oldSpace* sp, char* page) {
00207   // Find object at page start
00208   oop* s = sp->object_start(oop_for(page));
00209   // Find the end
00210   oop* e = min(oop_for(page+1), (oop*)sp->top());
00211 
00212   CheckDirtyClosure blk;
00213 
00214   while (s < e) {
00215     memOop m = as_memOop(s);
00216     blk.clear();
00217     m->oop_iterate(&blk);
00218     if (blk.is_dirty) return true;
00219     s += m->size();
00220   }
00221   return false;
00222 }
00223 
00224 int rSet::number_of_pages_with_dirty_objects_in(oldSpace* sp) {
00225   int count = 0;
00226   char* current_byte = byte_for(sp->bottom());
00227   char* end_byte     = byte_for(sp->top());
00228   while (current_byte <= end_byte) {
00229     if (has_page_dirty_objects(sp, current_byte))
00230       count++;
00231     current_byte++;
00232   }
00233   return count;
00234 }
00235 
00236 void rSet::print_set_for_object(memOop obj) {
00237   std->print("Remember set for 0x%lx ", obj);
00238   obj->print_value();
00239   std->cr();
00240   if (obj->is_new()) {
00241     std->print_cr(" object is in new space!");
00242   } else {
00243     std->sp();
00244     char* current_byte = byte_for(obj->addr());
00245     char* end_byte     = byte_for(obj->addr() + obj->size());
00246     while (current_byte <= end_byte) {
00247       if (*current_byte) {
00248         std->print("_");
00249       } else {
00250         std->print("*");
00251       }
00252       current_byte++;
00253     }
00254     std->cr();
00255   }
00256 }
00257 
00258 bool rSet::is_object_dirty(memOop obj) {
00259   assert(!obj->is_new(), "just checking");
00260   char* current_byte = byte_for(obj->addr());
00261   char* end_byte     = byte_for(obj->addr() + obj->size());
00262   while (current_byte <= end_byte) {
00263     if (*current_byte == 0) return true;
00264     current_byte++;
00265   }
00266   return false;
00267 }
00268 
00269 void rSet::clear(char *start, char *end) {
00270   int* from  = (int*) start;
00271   int  count = (int*) end - from;
00272   set_words(from, count, AllBits);
00273 }
00274 
00275 bool rSet::verify(bool postScavenge) {
00276   return true;
00277 }
00278 
00279 // Scheme for storing the size of objects during pointer-reversal phase of GC.
00280 // (Can't get object size via klass because pointers are reversed! :-)
00281 // size must be >= 128.
00282 // 1. byte     Size            Size
00283 // [0..128[ -> [128..256[
00284 // 128      -> 1 extra byte   [256      .. 256   + 2^8 [
00285 // 129      -> 2 extra bytes  [512      .. 512   + 2^16[
00286 // 130      -> 4 extra bytes  [66048    ..         2^32[
00287 
00288 const int lim_0 =         markOopDesc::max_age;
00289 const int lim_1 =         (1 <<  8);
00290 const int lim_2 = lim_1 + (1 <<  8);
00291 const int lim_3 = lim_2 + (1 << 16);
00292 
00293 void rSet::set_size(memOop obj, int size) {
00294   unsigned char* p = (unsigned char*) byte_for(obj->addr());
00295   assert(size >= lim_0, "size must be >= max_age");
00296   if (size < lim_1) {           // use 1 byte
00297     *p = (unsigned char) (size - lim_0);
00298   } else if (size < lim_2) {    // use 1 + 1 bytes
00299     *p++ = lim_0 + 2;
00300     *p   = (unsigned char) (size - lim_1);
00301   } else if (size < lim_3) {    // use 1 + 2 bytes
00302     *p++ = lim_0 + 3;
00303     *(unsigned short*)p = (unsigned short) (size - lim_2);
00304   } else {                      // use 1 + 4 bytes
00305     *p++ = lim_0 + 4;
00306     *(unsigned int*)p = (unsigned int) (size - lim_3);
00307   }
00308 }
00309 
00310 int rSet::get_size(memOop obj) {
00311   unsigned char* p = (unsigned char*) byte_for(obj->addr());
00312   unsigned char h = *p++;
00313   if (h <= lim_0 + 1) return h + lim_0;
00314   if (h == lim_0 + 2) return (*(unsigned char*)  p) + lim_1;
00315   if (h == lim_0 + 3) return (*(unsigned short*) p) + lim_2;
00316   if (h == lim_0 + 4) return (*(unsigned int*)   p) + lim_3;
00317   ShouldNotReachHere();
00318   return 0;
00319 }
00320 
00321 // new old space added; fix the cards
00322 void rSet::fixup(char *start, char *end) {
00323   if (end > high_boundary) {
00324     Universe::remembered_set = new rSet(this, start, end);
00325   } else {
00326     clear(byte_for(start), byte_for(end));
00327   }
00328 }

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