space.cpp

Go to the documentation of this file.
00001 /* Copyright 1994, 1995 LongView Technologies L.L.C. $Revision: 1.43 $ */
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 # include "incls/_space.cpp.incl"
00027 
00028 oop* OldWaterMark::pseudo_allocate(int size) {
00029   oop* p = _point;
00030   if (p + size  < _space->end()) {
00031     _point = p + size;
00032   } else {
00033     lprintf("crossing space\n");
00034     fatal("not implemented yet");
00035   }
00036   return p;
00037 }
00038 
00039 void space::clear() {
00040   set_top(bottom());
00041 # ifdef ASSERT 
00042     // to detect scavenging bugs
00043     set_oops(bottom(), capacity()/oopSize, oop(1));
00044 # endif
00045 }
00046 
00047 void space::switch_pointers(oop from, oop to) {
00048   // FIX LATER
00049   fatal("not implemented yet");
00050 }
00051 
00052 void space::initialize(char* name, oop* bottom, oop* end) {
00053   assert(Universe::on_page_boundary(bottom) && Universe::on_page_boundary(end), "invalid space boundaries");
00054 
00055   set_name(name);
00056   set_bottom(bottom);
00057   set_top(bottom);
00058   set_end(end);
00059 }
00060 
00061 void space::prepare_for_compaction(OldWaterMark* mark) {
00062   // compute the new addresses for the live objects and update all
00063   // pointers to these objects.
00064   // Used by universe::mark_sweep_phase2()
00065   // %profiling note:
00066   //    the garbage collectior spends 55% of its time in this function
00067   oop* q          = bottom();
00068   oop* t          = top();
00069   oop* new_top    = mark->_point;
00070   memOop first_free = NULL;
00071   while (q < t) {
00072     memOop m = as_memOop(q);
00073     if (m->is_gc_marked()) {
00074       if (first_free) { 
00075         first_free->set_mark(q);
00076         // lprintf("[%#lx] = %#lx, %#lx\n", first_free, first_free->mark(), q);
00077         first_free = NULL;
00078       }
00079 
00080       // Reverse the list with the mark at the end
00081       oop* root_or_mark = (oop*) m->mark();
00082       while (is_oop_root(root_or_mark)) {
00083         oop* next = (oop*) *root_or_mark;
00084         *root_or_mark = (oop) as_memOop(new_top);
00085         root_or_mark = next;
00086       }
00087       m->set_mark(markOop(root_or_mark));
00088 
00089       int size = m->gc_retrieve_size(); // The mark has to be restored before 
00090                                         // the size is retrieved
00091       new_top += size;
00092       q       += size;
00093     } else {
00094       if (!first_free) {
00095         first_free = m;
00096         // lprintf("First free %#lx\n", q);
00097       }
00098       q += m->size();
00099     }
00100   }
00101   if (first_free) { 
00102     first_free->set_mark(q);
00103     // lprintf("[%#lx] = %#lx, %#lx\n", first_free, first_free->mark(), q);
00104   }
00105   mark->_point = new_top;
00106 }
00107 
00108 void space::compact(OldWaterMark* mark) {
00109   // compute the new addresses for the live objects
00110   // Used by universe::mark_sweep_phase3()
00111   // %profiling note:
00112   //    the garbage collectior spends 23% of its time in this function
00113   oop* q       = bottom();
00114   oop* t       = top();
00115   oop* new_top = mark->_point;
00116   while (q < t) {
00117     memOop m = as_memOop(q);
00118     if (m->mark()->is_smi()) {
00119       // lprintf("Expanding %#lx -> %#lx\n", q, *q);
00120       q = (oop*) *q;
00121     } else {
00122       int size = m->gc_retrieve_size();
00123       if (q != new_top) {
00124         copy_oops(q, new_top, size);
00125         // lprintf("copy %#lx -> %#lx (%d)\n", q, new_top, size);
00126         assert((*new_top)->is_mark(), "should be header");
00127       }
00128       mark->_space->update_offsets(new_top, new_top + size);
00129       q       += size;
00130       new_top += size;
00131     }
00132   }
00133   mark->_point = new_top;
00134   mark->_space->set_top(new_top);
00135   set_top(new_top);
00136 }
00137 
00138 oop* newSpace::object_start(oop* p) {
00139   assert (bottom() <= p && p < top(), "p must be in space");
00140   oop* q = bottom();
00141   oop* t = top();
00142   while (q < t) {
00143     oop* prev = q;
00144     q += as_memOop(q)->size();
00145     if (q > p) return prev;
00146   }
00147   fatal("should never reach this point");
00148   return NULL;
00149 }
00150 
00151 void newSpace::object_iterate_from(NewWaterMark* mark, ObjectClosure* blk) {
00152   blk->begin_space(this);
00153   oop* p = mark->_point;
00154   oop* t = top();
00155   while (p < t) {
00156     memOop m = as_memOop(p);
00157     blk->do_object(m);
00158     p += m->size();
00159   }
00160   mark->_point = p;
00161   blk->end_space(this);
00162 }
00163 
00164 edenSpace::edenSpace() {}
00165 survivorSpace::survivorSpace() {}
00166 
00167 void survivorSpace::scavenge_contents_from(NewWaterMark* mark) {
00168 # ifdef VERBOSE_SCAVENGING  
00169   lprintf("{scavenge_contents [ %#lx <= %#lx <= %#lx]}\n",
00170           bottom(), mark->_point, top());
00171 # endif
00172 
00173   if (top() == mark->_point) return;
00174   assert(mark->_point < top(), "scavenging past top");
00175 
00176   oop* p = mark->_point; // for performance
00177   oop* t = top();
00178   
00179   do {
00180     memOop m = as_memOop(p);
00181 
00182 # ifdef VERBOSE_SCAVENGING  
00183     lprintf("{scavenge %#lx (%#lx)} ", p, m->klass());
00184     lprintf("%s\n", m->klass()->name());
00185     oop *prev = p;
00186 # endif
00187 
00188     assert((*p)->is_mark(), "Header should be mark");
00189     p += m->scavenge_contents();
00190 
00191 # ifdef VERBOSE_SCAVENGING  
00192     if (p - prev != m->size())
00193       fatal("scavenge_contents is not returning the right size");
00194 # endif
00195 
00196   } while (p < t);
00197   mark->_point = p;
00198 }
00199 
00200 void oldSpace::initialize_threshold() {
00201   next_offset_index                 = 0;
00202   offset_array[next_offset_index++] = 0;
00203   next_offset_treshold = _bottom + card_size_in_oops;
00204 }
00205 
00206 oldSpace::oldSpace(char *name, int &size) {
00207   next_space= NULL;
00208 
00209   offset_array = NEW_C_HEAP_ARRAY(u_char, Universe::old_gen.virtual_space.reserved_size()/card_size);
00210   set_name(name);
00211   set_bottom((oop*) Universe::old_gen.virtual_space.low());
00212   set_top((oop*)    Universe::old_gen.virtual_space.low());
00213   set_end((oop*)    Universe::old_gen.virtual_space.high());
00214   initialize_threshold();
00215 }
00216 
00217 void oldSpace::update_offset_array(oop* p, oop* p_end) {
00218   assert( p_end >= next_offset_treshold, "should be past threshold");
00219   //  [    ][    ][   ]       "card pages"
00220   //    ^p  ^t     ^p_end
00221   assert((next_offset_treshold - p) <= card_size_in_oops,
00222          "Offset should be <= card_size_in_oops");
00223   offset_array[next_offset_index++] = next_offset_treshold - p;
00224   next_offset_treshold += card_size_in_oops;
00225   while (next_offset_treshold < p_end) {
00226     offset_array[next_offset_index++] = card_size_in_oops;
00227     next_offset_treshold += card_size_in_oops;
00228   }
00229 }
00230 
00231 oop* oldSpace::expand_and_allocate(int size) {
00232   int min_size = ReservedSpace::page_align_size(size);
00233   int expand_size = max(min_size, ObjectHeapExpandSize * K);
00234   Universe::old_gen.virtual_space.expand(expand_size);
00235   set_end((oop*) Universe::old_gen.virtual_space.high());
00236   return allocate(size);
00237 }
00238 
00239 void oldSpace::scavenge_recorded_stores() {
00240   Universe::remembered_set->scavenge_contents(this);
00241 }
00242 
00243 void oldSpace::scavenge_contents_from(OldWaterMark* mark) {
00244   assert(this == mark->_space, "Match does not match space");
00245   oop* p = mark->_point;
00246   while (p < _top) {
00247     assert(oop(*p)->is_mark(),"must be mark");
00248     memOop x = as_memOop(p);
00249     p += x->scavenge_tenured_contents();
00250   }
00251   assert(p == _top, "p should be top");
00252   mark->_point = _top;
00253 }
00254 
00255 void oldSpace::object_iterate_from(OldWaterMark* mark, ObjectClosure* blk) {
00256   blk->begin_space(this);
00257   oop* p = mark->_point;
00258   oop* t = top();
00259   while (p < t) {
00260     memOop m = as_memOop(p);
00261     blk->do_object(m);
00262     p += m->size();
00263   }
00264   mark->_point = p;
00265   blk->end_space(this);
00266 }
00267 
00268 
00269 void space::oops_do(oopsDoFn f) {
00270   oop* p = bottom();
00271   oop* t = top();
00272   while (p < t) {
00273     memOop m = as_memOop(p);
00274     f((oop*) &m);
00275     p += m->size();
00276   }
00277 }
00278 
00279 void space::print() {
00280   std->print(" %5s %6dK, %d%% used", name(), capacity() / K, used() * 100 / capacity());
00281   if (WizardMode) {
00282     std->print(" [%#-6lx,%#-6lx[", bottom(), top());
00283   }
00284   std->cr();
00285 }
00286 
00287 void space::object_iterate(ObjectClosure* blk) {
00288   if (is_empty()) return;
00289   blk->begin_space(this);
00290   oop* p = bottom();
00291   oop* t = top();
00292   while (p < t) {
00293     memOop m = as_memOop(p);
00294     blk->do_object(m);
00295     p += m->size();
00296   }
00297   blk->end_space(this);
00298 }
00299 
00300 void newSpace::verify() {
00301   lprintf("%s ", name());
00302   oop* p = bottom();
00303   oop* t = top();
00304 
00305   memOop m;
00306   while (p < t) {
00307     assert(oop(*p)->is_mark(), "First word must be mark");
00308     m = as_memOop(p);
00309     m->verify();
00310     p += m->size();
00311   }
00312   assert(p == top(), "end of last object must match end of space");
00313 }
00314 
00315 class VerifyOldOopClosure : public OopClosure {
00316  public:
00317   memOop the_obj;
00318   void do_oop(oop* o) {
00319     oop obj = *o;
00320     if (obj->is_new()) {
00321       // Make sure the the_obj is in the remembered set
00322       if (!Universe::remembered_set->is_object_dirty(the_obj)) {
00323         std->cr();
00324         std->print_cr("New obj reference found in non dirty page.");
00325         std->print_cr("- object containing the reference:");
00326         the_obj->print();
00327         std->print_cr("- the referred object:");
00328         std->print("[0x%lx]: 0x%lx = ", o, obj);
00329         obj->print_value();
00330         std->cr();
00331         Universe::remembered_set->print_set_for_object(the_obj);
00332         warning("gc problem");
00333       }
00334     }
00335   }
00336 };
00337 
00338 void oldSpace::verify() {
00339   lprintf("%s ", name());
00340   oop*   p = _bottom;
00341   memOop m;
00342   VerifyOldOopClosure blk;
00343   while (p < _top) {
00344     assert(oop(*p)->is_mark(), "First word must be mark");
00345     m = as_memOop(p);
00346 
00347     int size = m->size();
00348     assert(m == as_memOop(Universe::object_start(p + (size/2))), "check offset computation");
00349 
00350     m->verify();
00351     blk.the_obj = m;
00352     m->oop_iterate(&blk);
00353     p += m->size();
00354   }
00355   assert(p == _top, "end of last object must match end of space");
00356 }
00357 
00358 oop* oldSpace::object_start(oop* p) {
00359   // Find the page start
00360   oop* q = p;
00361   int b = (int) q;
00362   clearBits(b, nthMask(card_shift));
00363   q = (oop*) b;
00364   assert(contains(q), "q must be in this space");
00365   int index  = (q - bottom()) / card_size_in_oops;
00366 
00367   int offset = offset_array[index--];
00368   while(offset == card_size_in_oops) {
00369     q -= card_size_in_oops;
00370     offset = offset_array[index--];
00371   }
00372   q -= offset;
00373   oop* n = q;
00374   assert((*n)->is_mark(), "check for header");
00375   while (n <= p) {
00376     q = n;
00377     n += as_memOop(n)->size();
00378   }
00379   assert( as_memOop(q)->mark()->is_mark(), "Must be mark");
00380   return q;
00381 }
00382 
00383 extern "C" oop* eden_bottom = NULL;
00384 extern "C" oop* eden_top    = NULL;
00385 extern "C" oop* eden_end    = NULL;

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