00001 /* Copyright 1994, 1995 LongView Technologies L.L.C. $Revision: 1.12 $ */ 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/_markSweep.cpp.incl" 00026 00027 GrowableArray<memOop>* MarkSweep::stack; 00028 GrowableArray<int>* MarkSweep::hcode_offsets; 00029 int MarkSweep::hcode_pos; 00030 00031 oop MarkSweep::collect(oop p) { 00032 FlagSetting fl(GCInProgress, true); 00033 EventMarker em("Garbage Collect"); 00034 ResourceMark rm; 00035 TraceTime t("Garbage collection", PrintGC); 00036 00037 int old_used = Universe::old_gen.used(); 00038 00039 if (VerifyBeforeScavenge || VerifyBeforeGC) Universe::verify(); 00040 00041 // Clear all vm inline caches 00042 DeltaCallCache::clearAll(); 00043 00044 // clear remembered set; it is used for object sizes 00045 Universe::remembered_set->clear(); 00046 00047 allocate(); // allocate stack for traversal 00048 00049 mark_sweep_phase1(&p); 00050 mark_sweep_phase2(); 00051 mark_sweep_phase3(); 00052 00053 deallocate(); // clear allocated structures 00054 00055 // clear the remember set; we have no pointers from old to new 00056 Universe::remembered_set->clear(); 00057 00058 lookupCache::flush(); 00059 00060 if (VerifyAfterScavenge || VerifyAfterGC) Universe::verify(); 00061 00062 if (PrintGC) { 00063 std->print(" %.1fM -> %.1fM", 00064 (double) old_used / (double) (1024 * 1024), 00065 (double) Universe::old_gen.used() / (double) (1024 * 1024)); 00066 } 00067 00068 return p; 00069 } 00070 00071 void MarkSweep::allocate() { 00072 stack = new GrowableArray<memOop>(200); 00073 hcode_offsets = new GrowableArray<int>(100); 00074 hcode_pos = 0; 00075 } 00076 00077 void MarkSweep::deallocate() { 00078 stack = NULL; 00079 hcode_offsets = NULL; 00080 } 00081 00082 void MarkSweep::trace(char* msg) { 00083 if (TraceGC) 00084 std->print("%s", msg); 00085 } 00086 00087 memOop MarkSweep::reverse(oop* p) { 00088 oop obj = *p; 00089 00090 // Return NULL if non memOop 00091 if (!obj->is_mem()) return NULL; 00092 00093 if (memOop(obj)->is_gc_marked()) { 00094 // Reverse pointer 00095 *p = oop(memOop(obj)->mark()); 00096 memOop(obj)->set_mark(p); 00097 00098 return NULL; 00099 } else { 00100 // Before the pointer reversal takes place the object size must be made accessible 00101 // without using the klass pointer. We store the object size partially in the 00102 // age field and partially in the remembered set. 00103 memOop(obj)->gc_store_size(); 00104 00105 assert(memOop(obj)->size() == memOop(obj)->gc_retrieve_size(), "checking real against stored size"); 00106 00107 // Reverse pointer 00108 *p = oop(memOop(obj)->mark()); 00109 memOop(obj)->set_mark(p); 00110 00111 assert(memOop(obj)->klass()->is_mem(), "just checking"); 00112 00113 return memOop(obj); 00114 } 00115 } 00116 00117 void MarkSweep::reverse_and_push(oop* p) { 00118 memOop m = reverse(p); 00119 if (m) stack->push(m); 00120 } 00121 00122 void MarkSweep::reverse_and_follow(oop* p) { 00123 memOop m = reverse(p); 00124 if (m) m->follow_contents(); // Follow contents of the marked object 00125 } 00126 00127 void MarkSweep::follow_root(oop* p) { 00128 reverse_and_follow(p); 00129 while (!stack->isEmpty()) 00130 stack->pop()->follow_contents(); 00131 } 00132 00133 void MarkSweep::add_hcode_offset(int offset) { 00134 hcode_offsets->push(offset); 00135 } 00136 00137 int MarkSweep::next_hcode_offset() { 00138 return hcode_offsets->at(hcode_pos++); 00139 } 00140 00141 void MarkSweep::mark_sweep_phase1(oop* p) { 00142 // Recursively traverse all live objects and mark them by reversing pointers. 00143 EventMarker em("1 reverse pointers"); 00144 00145 trace(" 1"); 00146 00147 WeakArrayRegister::begin_mark_sweep(); 00148 Processes::convert_hcode_pointers(); 00149 00150 Universe::oops_do(&follow_root); 00151 00152 // Hcode pointers point to the inside of methodOops and 00153 // have to be converted before we can follow the processes. 00154 Processes::follow_roots(); 00155 00156 WeakArrayRegister::check_and_follow_contents(); 00157 NotificationQueue::oops_do(&follow_root); 00158 00159 vmSymbols::follow_contents(); 00160 00161 // finalize unused objects - must be after all other gc_mark routines! 00162 Universe::symbol_table->follow_used_symbols(); 00163 00164 assert(stack->isEmpty(), "stack should be empty by now"); 00165 } 00166 00167 void MarkSweep::mark_sweep_phase2() { 00168 // Now all live objects are marked, compute the new object addresses. 00169 EventMarker em("2 compute new addresses"); 00170 trace("2"); 00171 00172 OldWaterMark mark = Universe::old_gen.bottom_mark(); 00173 // %note memory must be traversed in the same order as phase3 00174 Universe::old_gen.prepare_for_compaction(&mark); 00175 Universe::new_gen.prepare_for_compaction(&mark); 00176 } 00177 00178 void MarkSweep::mark_sweep_phase3() { 00179 EventMarker em("3 compact heap"); 00180 trace("3"); 00181 OldWaterMark mark = Universe::old_gen.bottom_mark(); 00182 mark._space->initialize_threshold(); 00183 // %note memory must be traversed in the same order as phase2 00184 Universe::old_gen.compact(&mark); 00185 Universe::new_gen.compact(&mark); 00186 00187 // All hcode pointers can now be restored. Remember 00188 // we converted these pointers in phase1. 00189 Processes::restore_hcode_pointers(); 00190 }