00001 // Copyright 2006-2008 the V8 project authors. All rights reserved. 00002 // Redistribution and use in source and binary forms, with or without 00003 // modification, are permitted provided that the following conditions are 00004 // met: 00005 // 00006 // * Redistributions of source code must retain the above copyright 00007 // notice, this list of conditions and the following disclaimer. 00008 // * Redistributions in binary form must reproduce the above 00009 // copyright notice, this list of conditions and the following 00010 // disclaimer in the documentation and/or other materials provided 00011 // with the distribution. 00012 // * Neither the name of Google Inc. nor the names of its 00013 // contributors may be used to endorse or promote products derived 00014 // from this software without specific prior written permission. 00015 // 00016 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00017 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00018 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 00019 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 00020 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00021 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 00022 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00023 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00024 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00025 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00026 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00027 00028 #ifndef V8_MARK_COMPACT_H_ 00029 #define V8_MARK_COMPACT_H_ 00030 00031 namespace v8 { namespace internal { 00032 00033 // Callback function, returns whether an object is alive. The heap size 00034 // of the object is returned in size. It optionally updates the offset 00035 // to the first live object in the page (only used for old and map objects). 00036 typedef bool (*IsAliveFunction)(HeapObject* obj, int* size, int* offset); 00037 00038 // Callback function for non-live blocks in the old generation. 00039 typedef void (*DeallocateFunction)(Address start, int size_in_bytes); 00040 00041 00042 // Forward declarations. 00043 class RootMarkingVisitor; 00044 class MarkingVisitor; 00045 00046 00047 // ---------------------------------------------------------------------------- 00048 // Mark-Compact collector 00049 // 00050 // All methods are static. 00051 00052 class MarkCompactCollector : public AllStatic { 00053 public: 00054 // Type of functions to compute forwarding addresses of objects in 00055 // compacted spaces. Given an object and its size, return a (non-failure) 00056 // Object* that will be the object after forwarding. There is a separate 00057 // allocation function for each (compactable) space based on the location 00058 // of the object before compaction. 00059 typedef Object* (*AllocationFunction)(HeapObject* object, int object_size); 00060 00061 // Type of functions to encode the forwarding address for an object. 00062 // Given the object, its size, and the new (non-failure) object it will be 00063 // forwarded to, encode the forwarding address. For paged spaces, the 00064 // 'offset' input/output parameter contains the offset of the forwarded 00065 // object from the forwarding address of the previous live object in the 00066 // page as input, and is updated to contain the offset to be used for the 00067 // next live object in the same page. For spaces using a different 00068 // encoding (ie, contiguous spaces), the offset parameter is ignored. 00069 typedef void (*EncodingFunction)(HeapObject* old_object, 00070 int object_size, 00071 Object* new_object, 00072 int* offset); 00073 00074 // Type of functions to process non-live objects. 00075 typedef void (*ProcessNonLiveFunction)(HeapObject* object); 00076 00077 // Performs a global garbage collection. 00078 static void CollectGarbage(GCTracer* tracer); 00079 00080 // True if the last full GC performed heap compaction. 00081 static bool HasCompacted() { return compacting_collection_; } 00082 00083 // True after the Prepare phase if the compaction is taking place. 00084 static bool IsCompacting() { return compacting_collection_; } 00085 00086 // The count of the number of objects left marked at the end of the last 00087 // completed full GC (expected to be zero). 00088 static int previous_marked_count() { return previous_marked_count_; } 00089 00090 // During a full GC, there is a stack-allocated GCTracer that is used for 00091 // bookkeeping information. Return a pointer to that tracer. 00092 static GCTracer* tracer() { return tracer_; } 00093 00094 #ifdef DEBUG 00095 // Checks whether performing mark-compact collection. 00096 static bool in_use() { return state_ > PREPARE_GC; } 00097 #endif 00098 00099 private: 00100 #ifdef DEBUG 00101 enum CollectorState { 00102 IDLE, 00103 PREPARE_GC, 00104 MARK_LIVE_OBJECTS, 00105 SWEEP_SPACES, 00106 ENCODE_FORWARDING_ADDRESSES, 00107 UPDATE_POINTERS, 00108 RELOCATE_OBJECTS, 00109 REBUILD_RSETS 00110 }; 00111 00112 // The current stage of the collector. 00113 static CollectorState state_; 00114 #endif 00115 // Global flag indicating whether spaces were compacted on the last GC. 00116 static bool compacting_collection_; 00117 00118 // The number of objects left marked at the end of the last completed full 00119 // GC (expected to be zero). 00120 static int previous_marked_count_; 00121 00122 // A pointer to the current stack-allocated GC tracer object during a full 00123 // collection (NULL before and after). 00124 static GCTracer* tracer_; 00125 00126 // Prepares for GC by resetting relocation info in old and map spaces and 00127 // choosing spaces to compact. 00128 static void Prepare(); 00129 00130 // Finishes GC, performs heap verification. 00131 static void Finish(); 00132 00133 // -------------------------------------------------------------------------- 00134 // Phase 1: functions related to marking phase. 00135 // before: Heap is in normal state, collector is 'IDLE'. 00136 // 00137 // The first word of a page in old spaces has the end of 00138 // allocation address of the page. 00139 // 00140 // The word at Chunk::high_ address has the address of the 00141 // first page in the next chunk. (The address is tagged to 00142 // distinguish it from end-of-allocation address). 00143 // 00144 // after: live objects are marked. 00145 00146 friend class RootMarkingVisitor; 00147 friend class MarkingVisitor; 00148 00149 // Marking operations for objects reachable from roots. 00150 static void MarkLiveObjects(); 00151 00152 static void MarkUnmarkedObject(HeapObject* obj); 00153 00154 static inline void MarkObject(HeapObject* obj) { 00155 if (!obj->IsMarked()) MarkUnmarkedObject(obj); 00156 } 00157 00158 // Creates back pointers for all map transitions, stores them in 00159 // the prototype field. The original prototype pointers are restored 00160 // in ClearNonLiveTransitions(). All JSObject maps 00161 // connected by map transitions have the same prototype object, which 00162 // is why we can use this field temporarily for back pointers. 00163 static void CreateBackPointers(); 00164 00165 // Mark a Map and its DescriptorArray together, skipping transitions. 00166 static void MarkMapContents(Map* map); 00167 static void MarkDescriptorArray(DescriptorArray* descriptors); 00168 00169 // Mark the heap roots and all objects reachable from them. 00170 static void ProcessRoots(RootMarkingVisitor* visitor); 00171 00172 // Mark objects in object groups that have at least one object in the 00173 // group marked. 00174 static void MarkObjectGroups(); 00175 00176 // Mark all objects in an object group with at least one marked 00177 // object, then all objects reachable from marked objects in object 00178 // groups, and repeat. 00179 static void ProcessObjectGroups(MarkingVisitor* visitor); 00180 00181 // Mark objects reachable (transitively) from objects in the marking stack 00182 // or overflowed in the heap. 00183 static void ProcessMarkingStack(MarkingVisitor* visitor); 00184 00185 // Mark objects reachable (transitively) from objects in the marking 00186 // stack. This function empties the marking stack, but may leave 00187 // overflowed objects in the heap, in which case the marking stack's 00188 // overflow flag will be set. 00189 static void EmptyMarkingStack(MarkingVisitor* visitor); 00190 00191 // Refill the marking stack with overflowed objects from the heap. This 00192 // function either leaves the marking stack full or clears the overflow 00193 // flag on the marking stack. 00194 static void RefillMarkingStack(); 00195 00196 // Callback function for telling whether the object *p must be marked. 00197 static bool MustBeMarked(Object** p); 00198 00199 #ifdef DEBUG 00200 static void UpdateLiveObjectCount(HeapObject* obj); 00201 static void VerifyHeapAfterMarkingPhase(); 00202 #endif 00203 00204 // We sweep the large object space in the same way whether we are 00205 // compacting or not, because the large object space is never compacted. 00206 static void SweepLargeObjectSpace(); 00207 00208 // Test whether a (possibly marked) object is a Map. 00209 static inline bool SafeIsMap(HeapObject* object); 00210 00211 // Map transitions from a live map to a dead map must be killed. 00212 // We replace them with a null descriptor, with the same key. 00213 static void ClearNonLiveTransitions(); 00214 00215 // -------------------------------------------------------------------------- 00216 // Phase 2: functions related to computing and encoding forwarding pointers 00217 // before: live objects' map pointers are marked as '00' 00218 // after: Map pointers of live old and map objects have encoded 00219 // forwarding pointers and map pointers 00220 // 00221 // The 3rd word of a page has the page top offset after compaction. 00222 // 00223 // The 4th word of a page in the map space has the map index 00224 // of this page in the map table. This word is not used in 00225 // the old space. 00226 // 00227 // The 5th and 6th words of a page have the start and end 00228 // addresses of the first free region in the page. 00229 // 00230 // The 7th word of a page in old spaces has the forwarding address 00231 // of the first live object in the page. 00232 // 00233 // Live young objects have their forwarding pointers in 00234 // the from space at the same offset to the beginning of the space. 00235 00236 // Encodes forwarding addresses of objects in compactable parts of the 00237 // heap. 00238 static void EncodeForwardingAddresses(); 00239 00240 // Encodes the forwarding addresses of objects in new space. 00241 static void EncodeForwardingAddressesInNewSpace(); 00242 00243 // Function template to encode the forwarding addresses of objects in 00244 // paged spaces, parameterized by allocation and non-live processing 00245 // functions. 00246 template<AllocationFunction Alloc, ProcessNonLiveFunction ProcessNonLive> 00247 static void EncodeForwardingAddressesInPagedSpace(PagedSpace* space); 00248 00249 // Iterates live objects in a space, passes live objects 00250 // to a callback function which returns the heap size of the object. 00251 // Returns the number of live objects iterated. 00252 static int IterateLiveObjects(NewSpace* space, HeapObjectCallback size_f); 00253 static int IterateLiveObjects(PagedSpace* space, HeapObjectCallback size_f); 00254 00255 // Iterates the live objects between a range of addresses, returning the 00256 // number of live objects. 00257 static int IterateLiveObjectsInRange(Address start, Address end, 00258 HeapObjectCallback size_func); 00259 00260 // Callback functions for deallocating non-live blocks in the old 00261 // generation. 00262 static void DeallocateOldPointerBlock(Address start, int size_in_bytes); 00263 static void DeallocateOldDataBlock(Address start, int size_in_bytes); 00264 static void DeallocateCodeBlock(Address start, int size_in_bytes); 00265 static void DeallocateMapBlock(Address start, int size_in_bytes); 00266 00267 // Phase 2: If we are not compacting the heap, we simply sweep the spaces 00268 // except for the large object space, clearing mark bits and adding 00269 // unmarked regions to each space's free list. 00270 static void SweepSpaces(); 00271 00272 #ifdef DEBUG 00273 static void VerifyHeapAfterEncodingForwardingAddresses(); 00274 #endif 00275 00276 // -------------------------------------------------------------------------- 00277 // Phase 3: function related to updating pointers and decode map pointers 00278 // before: see after phase 2 00279 // after: all pointers are updated to forwarding addresses. 00280 00281 friend class UpdatingVisitor; // helper for updating visited objects 00282 00283 // Updates pointers in all spaces. 00284 static void UpdatePointers(); 00285 00286 // Updates pointers in an object in new space. 00287 // Returns the heap size of the object. 00288 static int UpdatePointersInNewObject(HeapObject* obj); 00289 00290 // Updates pointers in an object in old spaces. 00291 // Returns the heap size of the object. 00292 static int UpdatePointersInOldObject(HeapObject* obj); 00293 00294 // Calculates the forwarding address of an object in an old space. 00295 static Address GetForwardingAddressInOldSpace(HeapObject* obj); 00296 00297 #ifdef DEBUG 00298 static void VerifyHeapAfterUpdatingPointers(); 00299 #endif 00300 00301 // -------------------------------------------------------------------------- 00302 // Phase 4: functions related to relocating objects 00303 // before: see after phase 3 00304 // after: heap is in a normal state, except remembered set is not built 00305 00306 // Relocates objects in all spaces. 00307 static void RelocateObjects(); 00308 00309 // Converts a code object's inline target to addresses, convention from 00310 // address to target happens in the marking phase. 00311 static int ConvertCodeICTargetToAddress(HeapObject* obj); 00312 00313 // Relocate a map object. 00314 static int RelocateMapObject(HeapObject* obj); 00315 00316 // Relocates an old object. 00317 static int RelocateOldPointerObject(HeapObject* obj); 00318 static int RelocateOldDataObject(HeapObject* obj); 00319 00320 // Helper function. 00321 static inline int RelocateOldNonCodeObject(HeapObject* obj, OldSpace* space); 00322 00323 // Relocates an object in the code space. 00324 static int RelocateCodeObject(HeapObject* obj); 00325 00326 // Copy a new object. 00327 static int RelocateNewObject(HeapObject* obj); 00328 00329 #ifdef DEBUG 00330 static void VerifyHeapAfterRelocatingObjects(); 00331 #endif 00332 00333 // --------------------------------------------------------------------------- 00334 // Phase 5: functions related to rebuilding remembered sets 00335 00336 // Rebuild remembered set in old and map spaces. 00337 static void RebuildRSets(); 00338 00339 #ifdef DEBUG 00340 // --------------------------------------------------------------------------- 00341 // Debugging variables, functions and classes 00342 // Counters used for debugging the marking phase of mark-compact or 00343 // mark-sweep collection. 00344 00345 // Number of live objects in Heap::to_space_. 00346 static int live_young_objects_; 00347 00348 // Number of live objects in Heap::old_pointer_space_. 00349 static int live_old_pointer_objects_; 00350 00351 // Number of live objects in Heap::old_data_space_. 00352 static int live_old_data_objects_; 00353 00354 // Number of live objects in Heap::code_space_. 00355 static int live_code_objects_; 00356 00357 // Number of live objects in Heap::map_space_. 00358 static int live_map_objects_; 00359 00360 // Number of live objects in Heap::lo_space_. 00361 static int live_lo_objects_; 00362 00363 // Number of live bytes in this collection. 00364 static int live_bytes_; 00365 00366 static void VerifyPageHeaders(PagedSpace* space); 00367 00368 // Verification functions when relocating objects. 00369 friend class VerifyCopyingVisitor; 00370 static void VerifyCopyingObjects(Object** p); 00371 00372 friend class MarkObjectVisitor; 00373 static void VisitObject(HeapObject* obj); 00374 00375 friend class UnmarkObjectVisitor; 00376 static void UnmarkObject(HeapObject* obj); 00377 #endif 00378 }; 00379 00380 00381 } } // namespace v8::internal 00382 00383 #endif // V8_MARK_COMPACT_H_