| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 11 matching lines...) Expand all Loading... |
| 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | 27 |
| 28 #ifndef V8_MARK_COMPACT_H_ | 28 #ifndef V8_MARK_COMPACT_H_ |
| 29 #define V8_MARK_COMPACT_H_ | 29 #define V8_MARK_COMPACT_H_ |
| 30 | 30 |
| 31 #include "compiler-intrinsics.h" | 31 #include "compiler-intrinsics.h" |
| 32 #include "spaces.h" |
| 32 | 33 |
| 33 namespace v8 { | 34 namespace v8 { |
| 34 namespace internal { | 35 namespace internal { |
| 35 | 36 |
| 36 // Callback function, returns whether an object is alive. The heap size | 37 // Callback function, returns whether an object is alive. The heap size |
| 37 // of the object is returned in size. It optionally updates the offset | 38 // of the object is returned in size. It optionally updates the offset |
| 38 // to the first live object in the page (only used for old and map objects). | 39 // to the first live object in the page (only used for old and map objects). |
| 39 typedef bool (*IsAliveFunction)(HeapObject* obj, int* size, int* offset); | 40 typedef bool (*IsAliveFunction)(HeapObject* obj, int* size, int* offset); |
| 40 | 41 |
| 41 // Forward declarations. | 42 // Forward declarations. |
| 43 class CodeFlusher; |
| 44 class GCTracer; |
| 45 class MarkingVisitor; |
| 42 class RootMarkingVisitor; | 46 class RootMarkingVisitor; |
| 43 class MarkingVisitor; | |
| 44 | 47 |
| 45 | 48 |
| 46 class Marking { | 49 class Marking { |
| 47 public: | 50 public: |
| 48 static inline MarkBit MarkBitFrom(HeapObject* obj) { | 51 explicit Marking(Heap* heap) |
| 52 : heap_(heap), |
| 53 new_space_bitmap_(NULL) { |
| 54 } |
| 55 |
| 56 inline MarkBit MarkBitFromNewSpace(HeapObject* obj); |
| 57 |
| 58 static inline MarkBit MarkBitFromOldSpace(HeapObject* obj); |
| 59 |
| 60 inline MarkBit MarkBitFrom(Address addr); |
| 61 |
| 62 inline MarkBit MarkBitFrom(HeapObject* obj) { |
| 49 return MarkBitFrom(reinterpret_cast<Address>(obj)); | 63 return MarkBitFrom(reinterpret_cast<Address>(obj)); |
| 50 } | 64 } |
| 51 | 65 |
| 52 static inline MarkBit MarkBitFromNewSpace(HeapObject* obj) { | 66 inline void ClearRange(Address addr, int size); |
| 53 ASSERT(Heap::InNewSpace(obj)); | |
| 54 uint32_t index = Heap::new_space()->AddressToMarkbitIndex( | |
| 55 reinterpret_cast<Address>(obj)); | |
| 56 return new_space_bitmap_->MarkBitFromIndex(index); | |
| 57 } | |
| 58 | 67 |
| 59 static inline MarkBit MarkBitFromOldSpace(HeapObject* obj) { | 68 void TransferMark(Address old_start, Address new_start); |
| 60 ASSERT(!Heap::InNewSpace(obj)); | |
| 61 ASSERT(obj->IsHeapObject()); | |
| 62 Address addr = reinterpret_cast<Address>(obj); | |
| 63 Page *p = Page::FromAddress(addr); | |
| 64 return p->markbits()->MarkBitFromIndex(p->AddressToMarkbitIndex(addr)); | |
| 65 } | |
| 66 | 69 |
| 67 static inline MarkBit MarkBitFrom(Address addr) { | 70 bool Setup(); |
| 68 if (Heap::InNewSpace(addr)) { | |
| 69 uint32_t index = Heap::new_space()->AddressToMarkbitIndex(addr); | |
| 70 return new_space_bitmap_->MarkBitFromIndex(index); | |
| 71 } else { | |
| 72 Page *p = Page::FromAddress(addr); | |
| 73 return p->markbits()->MarkBitFromIndex(p->AddressToMarkbitIndex(addr), | |
| 74 p->ContainsOnlyData()); | |
| 75 } | |
| 76 } | |
| 77 | 71 |
| 78 static void ClearRange(Address addr, int size) { | 72 void TearDown(); |
| 79 if (Heap::InNewSpace(addr)) { | |
| 80 uint32_t index = Heap::new_space()->AddressToMarkbitIndex(addr); | |
| 81 new_space_bitmap_->ClearRange(index, size >> kPointerSizeLog2); | |
| 82 } else { | |
| 83 Page *p = Page::FromAddress(addr); | |
| 84 p->markbits()->ClearRange(p->FastAddressToMarkbitIndex(addr), | |
| 85 size >> kPointerSizeLog2); | |
| 86 } | |
| 87 } | |
| 88 | |
| 89 // Find first marked object in the given cell with index cell_index on | |
| 90 // the given page. | |
| 91 INLINE(static Address FirstMarkedObject(Page* page, | |
| 92 uint32_t cell_index, | |
| 93 uint32_t cell)) { | |
| 94 ASSERT(cell != 0); | |
| 95 uint32_t bit = CompilerIntrinsics::CountTrailingZeros(cell); | |
| 96 return page->MarkbitIndexToAddress( | |
| 97 Page::MarkbitsBitmap::CellToIndex(cell_index) + bit); | |
| 98 } | |
| 99 | |
| 100 static void TransferMark(Address old_start, Address new_start); | |
| 101 | |
| 102 static bool Setup(); | |
| 103 | |
| 104 static void TearDown(); | |
| 105 | 73 |
| 106 private: | 74 private: |
| 107 class BitmapStorageDescriptor { | 75 class BitmapStorageDescriptor { |
| 108 public: | 76 public: |
| 109 INLINE(static int CellsCount(Address addr)) { | 77 INLINE(static int CellsCount(Address addr)) { |
| 110 return HeaderOf(addr)->cells_count_; | 78 return HeaderOf(addr)->cells_count_; |
| 111 } | 79 } |
| 112 | 80 |
| 113 static Bitmap<BitmapStorageDescriptor>* Allocate(int cells_count) { | 81 static Bitmap<BitmapStorageDescriptor>* Allocate(int cells_count) { |
| 114 VirtualMemory* memory = new VirtualMemory(SizeFor(cells_count)); | 82 VirtualMemory* memory = new VirtualMemory(SizeFor(cells_count)); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 140 Bitmap<BitmapStorageDescriptor>::SizeFor(cell_count); | 108 Bitmap<BitmapStorageDescriptor>::SizeFor(cell_count); |
| 141 } | 109 } |
| 142 | 110 |
| 143 static Header* HeaderOf(Address addr) { | 111 static Header* HeaderOf(Address addr) { |
| 144 return reinterpret_cast<Header*>(addr - sizeof(Header)); | 112 return reinterpret_cast<Header*>(addr - sizeof(Header)); |
| 145 } | 113 } |
| 146 }; | 114 }; |
| 147 | 115 |
| 148 typedef Bitmap<BitmapStorageDescriptor> NewSpaceMarkbitsBitmap; | 116 typedef Bitmap<BitmapStorageDescriptor> NewSpaceMarkbitsBitmap; |
| 149 | 117 |
| 150 static NewSpaceMarkbitsBitmap* new_space_bitmap_; | 118 Heap* heap_; |
| 119 NewSpaceMarkbitsBitmap* new_space_bitmap_; |
| 151 }; | 120 }; |
| 152 | 121 |
| 122 // ---------------------------------------------------------------------------- |
| 123 // Marking stack for tracing live objects. |
| 124 |
| 125 class MarkingStack { |
| 126 public: |
| 127 MarkingStack() : low_(NULL), top_(NULL), high_(NULL), overflowed_(false) { } |
| 128 |
| 129 void Initialize(Address low, Address high) { |
| 130 top_ = low_ = reinterpret_cast<HeapObject**>(low); |
| 131 high_ = reinterpret_cast<HeapObject**>(high); |
| 132 overflowed_ = false; |
| 133 } |
| 134 |
| 135 bool is_full() const { return top_ >= high_; } |
| 136 |
| 137 bool is_empty() const { return top_ <= low_; } |
| 138 |
| 139 bool overflowed() const { return overflowed_; } |
| 140 |
| 141 void clear_overflowed() { overflowed_ = false; } |
| 142 |
| 143 // Push the (marked) object on the marking stack if there is room, |
| 144 // otherwise mark the object as overflowed and wait for a rescan of the |
| 145 // heap. |
| 146 void Push(HeapObject* object) { |
| 147 CHECK(object->IsHeapObject()); |
| 148 if (is_full()) { |
| 149 object->SetOverflow(); |
| 150 overflowed_ = true; |
| 151 } else { |
| 152 *(top_++) = object; |
| 153 } |
| 154 } |
| 155 |
| 156 HeapObject* Pop() { |
| 157 ASSERT(!is_empty()); |
| 158 HeapObject* object = *(--top_); |
| 159 CHECK(object->IsHeapObject()); |
| 160 return object; |
| 161 } |
| 162 |
| 163 HeapObject** low() { return low_; } |
| 164 HeapObject** top() { return top_; } |
| 165 void set_top(HeapObject** top) { top_ = top; } |
| 166 |
| 167 private: |
| 168 HeapObject** low_; |
| 169 HeapObject** top_; |
| 170 HeapObject** high_; |
| 171 bool overflowed_; |
| 172 |
| 173 DISALLOW_COPY_AND_ASSIGN(MarkingStack); |
| 174 }; |
| 175 |
| 176 |
| 153 // ------------------------------------------------------------------------- | 177 // ------------------------------------------------------------------------- |
| 154 // Mark-Compact collector | 178 // Mark-Compact collector |
| 155 // | 179 // |
| 156 // All methods are static. | 180 // All methods are static. |
| 157 | 181 |
| 158 class MarkCompactCollector: public AllStatic { | 182 class OverflowedObjectsScanner; |
| 183 |
| 184 class MarkCompactCollector { |
| 159 public: | 185 public: |
| 160 // Type of functions to compute forwarding addresses of objects in | 186 // Type of functions to compute forwarding addresses of objects in |
| 161 // compacted spaces. Given an object and its size, return a (non-failure) | 187 // compacted spaces. Given an object and its size, return a (non-failure) |
| 162 // Object* that will be the object after forwarding. There is a separate | 188 // Object* that will be the object after forwarding. There is a separate |
| 163 // allocation function for each (compactable) space based on the location | 189 // allocation function for each (compactable) space based on the location |
| 164 // of the object before compaction. | 190 // of the object before compaction. |
| 165 typedef MaybeObject* (*AllocationFunction)(HeapObject* object, | 191 typedef MaybeObject* (*AllocationFunction)(Heap* heap, |
| 192 HeapObject* object, |
| 166 int object_size); | 193 int object_size); |
| 167 | 194 |
| 168 // Type of functions to encode the forwarding address for an object. | 195 // Type of functions to encode the forwarding address for an object. |
| 169 // Given the object, its size, and the new (non-failure) object it will be | 196 // Given the object, its size, and the new (non-failure) object it will be |
| 170 // forwarded to, encode the forwarding address. For paged spaces, the | 197 // forwarded to, encode the forwarding address. For paged spaces, the |
| 171 // 'offset' input/output parameter contains the offset of the forwarded | 198 // 'offset' input/output parameter contains the offset of the forwarded |
| 172 // object from the forwarding address of the previous live object in the | 199 // object from the forwarding address of the previous live object in the |
| 173 // page as input, and is updated to contain the offset to be used for the | 200 // page as input, and is updated to contain the offset to be used for the |
| 174 // next live object in the same page. For spaces using a different | 201 // next live object in the same page. For spaces using a different |
| 175 // encoding (ie, contiguous spaces), the offset parameter is ignored. | 202 // encoding (ie, contiguous spaces), the offset parameter is ignored. |
| 176 typedef void (*EncodingFunction)(HeapObject* old_object, | 203 typedef void (*EncodingFunction)(Heap* heap, |
| 204 HeapObject* old_object, |
| 177 int object_size, | 205 int object_size, |
| 178 Object* new_object, | 206 Object* new_object, |
| 179 int* offset); | 207 int* offset); |
| 180 | 208 |
| 181 // Type of functions to process non-live objects. | 209 // Type of functions to process non-live objects. |
| 182 typedef void (*ProcessNonLiveFunction)(HeapObject* object); | 210 typedef void (*ProcessNonLiveFunction)(HeapObject* object); |
| 183 | 211 |
| 212 // Pointer to member function, used in IterateLiveObjects. |
| 213 typedef int (MarkCompactCollector::*LiveObjectCallback)(HeapObject* obj); |
| 214 |
| 184 // Set the global force_compaction flag, it must be called before Prepare | 215 // Set the global force_compaction flag, it must be called before Prepare |
| 185 // to take effect. | 216 // to take effect. |
| 186 static void SetFlags(int flags) { | 217 inline void SetFlags(int flags); |
| 187 force_compaction_ = ((flags & Heap::kForceCompactionMask) != 0); | 218 |
| 188 sweep_precisely_ = ((flags & Heap::kMakeHeapIterableMask) != 0); | 219 inline bool PreciseSweepingRequired() { |
| 220 return sweep_precisely_; |
| 189 } | 221 } |
| 190 | 222 |
| 191 static bool PreciseSweepingRequired() { return sweep_precisely_; } | |
| 192 | |
| 193 static void Initialize(); | 223 static void Initialize(); |
| 194 | 224 |
| 195 // Prepares for GC by resetting relocation info in old and map spaces and | 225 // Prepares for GC by resetting relocation info in old and map spaces and |
| 196 // choosing spaces to compact. | 226 // choosing spaces to compact. |
| 197 static void Prepare(GCTracer* tracer); | 227 void Prepare(GCTracer* tracer); |
| 198 | 228 |
| 199 // Performs a global garbage collection. | 229 // Performs a global garbage collection. |
| 200 static void CollectGarbage(); | 230 void CollectGarbage(); |
| 201 | 231 |
| 202 // True if the last full GC performed heap compaction. | 232 // True if the last full GC performed heap compaction. |
| 203 static bool HasCompacted() { return compacting_collection_; } | 233 bool HasCompacted() { return compacting_collection_; } |
| 204 | 234 |
| 205 // True after the Prepare phase if the compaction is taking place. | 235 // True after the Prepare phase if the compaction is taking place. |
| 206 static bool IsCompacting() { | 236 bool IsCompacting() { |
| 207 #ifdef DEBUG | 237 #ifdef DEBUG |
| 208 // For the purposes of asserts we don't want this to keep returning true | 238 // For the purposes of asserts we don't want this to keep returning true |
| 209 // after the collection is completed. | 239 // after the collection is completed. |
| 210 return state_ != IDLE && compacting_collection_; | 240 return state_ != IDLE && compacting_collection_; |
| 211 #else | 241 #else |
| 212 return compacting_collection_; | 242 return compacting_collection_; |
| 213 #endif | 243 #endif |
| 214 } | 244 } |
| 215 | 245 |
| 216 // During a full GC, there is a stack-allocated GCTracer that is used for | 246 // During a full GC, there is a stack-allocated GCTracer that is used for |
| 217 // bookkeeping information. Return a pointer to that tracer. | 247 // bookkeeping information. Return a pointer to that tracer. |
| 218 static GCTracer* tracer() { return tracer_; } | 248 GCTracer* tracer() { return tracer_; } |
| 219 | 249 |
| 220 #ifdef DEBUG | 250 #ifdef DEBUG |
| 221 // Checks whether performing mark-compact collection. | 251 // Checks whether performing mark-compact collection. |
| 222 static bool in_use() { return state_ > PREPARE_GC; } | 252 bool in_use() { return state_ > PREPARE_GC; } |
| 223 static bool are_map_pointers_encoded() { return state_ == UPDATE_POINTERS; } | 253 bool are_map_pointers_encoded() { return state_ == UPDATE_POINTERS; } |
| 224 #endif | 254 #endif |
| 225 | 255 |
| 226 // Determine type of object and emit deletion log event. | 256 // Determine type of object and emit deletion log event. |
| 227 static void ReportDeleteIfNeeded(HeapObject* obj); | 257 static void ReportDeleteIfNeeded(HeapObject* obj); |
| 228 | 258 |
| 229 // Distinguishable invalid map encodings (for single word and multiple words) | 259 // Distinguishable invalid map encodings (for single word and multiple words) |
| 230 // that indicate free regions. | 260 // that indicate free regions. |
| 231 static const uint32_t kSingleFreeEncoding = 0; | 261 static const uint32_t kSingleFreeEncoding = 0; |
| 232 static const uint32_t kMultiFreeEncoding = 1; | 262 static const uint32_t kMultiFreeEncoding = 1; |
| 233 | 263 |
| 234 #ifdef DEBUG | 264 inline bool IsMarked(Object* obj); |
| 235 static bool IsMarked(Object* obj) { | 265 |
| 236 ASSERT(obj->IsHeapObject()); | 266 inline Heap* heap() const { return heap_; } |
| 237 HeapObject* heap_object = HeapObject::cast(obj); | 267 |
| 238 return Marking::MarkBitFrom(heap_object).Get(); | 268 CodeFlusher* code_flusher() { return code_flusher_; } |
| 239 } | 269 inline bool is_code_flushing_enabled() const { return code_flusher_ != NULL; } |
| 240 #endif | 270 void EnableCodeFlushing(bool enable); |
| 241 | 271 |
| 242 private: | 272 private: |
| 273 MarkCompactCollector(); |
| 274 ~MarkCompactCollector(); |
| 275 |
| 243 #ifdef DEBUG | 276 #ifdef DEBUG |
| 244 enum CollectorState { | 277 enum CollectorState { |
| 245 IDLE, | 278 IDLE, |
| 246 PREPARE_GC, | 279 PREPARE_GC, |
| 247 MARK_LIVE_OBJECTS, | 280 MARK_LIVE_OBJECTS, |
| 248 SWEEP_SPACES, | 281 SWEEP_SPACES, |
| 249 ENCODE_FORWARDING_ADDRESSES, | 282 ENCODE_FORWARDING_ADDRESSES, |
| 250 UPDATE_POINTERS, | 283 UPDATE_POINTERS, |
| 251 RELOCATE_OBJECTS | 284 RELOCATE_OBJECTS |
| 252 }; | 285 }; |
| 253 | 286 |
| 254 // The current stage of the collector. | 287 // The current stage of the collector. |
| 255 static CollectorState state_; | 288 CollectorState state_; |
| 256 #endif | 289 #endif |
| 257 | 290 |
| 258 // Global flag that forces a compaction. | 291 // Global flag that forces a compaction. |
| 259 static bool force_compaction_; | 292 bool force_compaction_; |
| 260 | 293 |
| 261 // Global flag that forces sweeping to be precise, so we can traverse the | 294 // Global flag that forces sweeping to be precise, so we can traverse the |
| 262 // heap. | 295 // heap. |
| 263 static bool sweep_precisely_; | 296 bool sweep_precisely_; |
| 264 | 297 |
| 265 // Global flag indicating whether spaces were compacted on the last GC. | 298 // Global flag indicating whether spaces were compacted on the last GC. |
| 266 static bool compacting_collection_; | 299 bool compacting_collection_; |
| 267 | 300 |
| 268 // Global flag indicating whether spaces will be compacted on the next GC. | 301 // Global flag indicating whether spaces will be compacted on the next GC. |
| 269 static bool compact_on_next_gc_; | 302 bool compact_on_next_gc_; |
| 303 |
| 304 // The number of objects left marked at the end of the last completed full |
| 305 // GC (expected to be zero). |
| 306 int previous_marked_count_; |
| 270 | 307 |
| 271 // A pointer to the current stack-allocated GC tracer object during a full | 308 // A pointer to the current stack-allocated GC tracer object during a full |
| 272 // collection (NULL before and after). | 309 // collection (NULL before and after). |
| 273 static GCTracer* tracer_; | 310 GCTracer* tracer_; |
| 274 | 311 |
| 275 // Finishes GC, performs heap verification if enabled. | 312 // Finishes GC, performs heap verification if enabled. |
| 276 static void Finish(); | 313 void Finish(); |
| 277 | 314 |
| 278 // ----------------------------------------------------------------------- | 315 // ----------------------------------------------------------------------- |
| 279 // Phase 1: Marking live objects. | 316 // Phase 1: Marking live objects. |
| 280 // | 317 // |
| 281 // Before: The heap has been prepared for garbage collection by | 318 // Before: The heap has been prepared for garbage collection by |
| 282 // MarkCompactCollector::Prepare() and is otherwise in its | 319 // MarkCompactCollector::Prepare() and is otherwise in its |
| 283 // normal state. | 320 // normal state. |
| 284 // | 321 // |
| 285 // After: Live objects are marked and non-live objects are unmarked. | 322 // After: Live objects are marked and non-live objects are unmarked. |
| 286 | 323 |
| 287 | 324 |
| 288 friend class RootMarkingVisitor; | 325 friend class RootMarkingVisitor; |
| 289 friend class MarkingVisitor; | 326 friend class MarkingVisitor; |
| 290 friend class StaticMarkingVisitor; | 327 friend class StaticMarkingVisitor; |
| 291 friend class CodeMarkingVisitor; | 328 friend class CodeMarkingVisitor; |
| 292 friend class SharedFunctionInfoMarkingVisitor; | 329 friend class SharedFunctionInfoMarkingVisitor; |
| 293 | 330 |
| 294 static void PrepareForCodeFlushing(); | 331 void PrepareForCodeFlushing(); |
| 295 | 332 |
| 296 // Marking operations for objects reachable from roots. | 333 // Marking operations for objects reachable from roots. |
| 297 static void MarkLiveObjects(); | 334 void MarkLiveObjects(); |
| 298 | 335 |
| 299 static void AfterMarking(); | 336 void AfterMarking(); |
| 300 | 337 |
| 338 INLINE(void MarkObject(HeapObject* obj, MarkBit mark_bit)); |
| 301 | 339 |
| 302 INLINE(static void MarkObject(HeapObject* obj, MarkBit mark_bit)) { | 340 INLINE(void SetMark(HeapObject* obj, MarkBit mark_bit)); |
| 303 ASSERT(Marking::MarkBitFrom(obj) == mark_bit); | |
| 304 if (!mark_bit.Get()) { | |
| 305 mark_bit.Set(); | |
| 306 tracer_->increment_marked_count(); | |
| 307 #ifdef DEBUG | |
| 308 UpdateLiveObjectCount(obj); | |
| 309 #endif | |
| 310 ProcessNewlyMarkedObject(obj); | |
| 311 } | |
| 312 } | |
| 313 | 341 |
| 314 INLINE(static void SetMark(HeapObject* obj, MarkBit mark_bit)) { | 342 void ProcessNewlyMarkedObject(HeapObject* obj); |
| 315 ASSERT(Marking::MarkBitFrom(obj) == mark_bit); | |
| 316 mark_bit.Set(); | |
| 317 tracer_->increment_marked_count(); | |
| 318 #ifdef DEBUG | |
| 319 UpdateLiveObjectCount(obj); | |
| 320 #endif | |
| 321 } | |
| 322 | |
| 323 static void ProcessNewlyMarkedObject(HeapObject* obj); | |
| 324 | 343 |
| 325 // Creates back pointers for all map transitions, stores them in | 344 // Creates back pointers for all map transitions, stores them in |
| 326 // the prototype field. The original prototype pointers are restored | 345 // the prototype field. The original prototype pointers are restored |
| 327 // in ClearNonLiveTransitions(). All JSObject maps | 346 // in ClearNonLiveTransitions(). All JSObject maps |
| 328 // connected by map transitions have the same prototype object, which | 347 // connected by map transitions have the same prototype object, which |
| 329 // is why we can use this field temporarily for back pointers. | 348 // is why we can use this field temporarily for back pointers. |
| 330 static void CreateBackPointers(); | 349 void CreateBackPointers(); |
| 331 | 350 |
| 332 // Mark a Map and its DescriptorArray together, skipping transitions. | 351 // Mark a Map and its DescriptorArray together, skipping transitions. |
| 333 static void MarkMapContents(Map* map); | 352 void MarkMapContents(Map* map); |
| 334 static void MarkDescriptorArray(DescriptorArray* descriptors); | 353 void MarkDescriptorArray(DescriptorArray* descriptors); |
| 335 | 354 |
| 336 // Mark the heap roots and all objects reachable from them. | 355 // Mark the heap roots and all objects reachable from them. |
| 337 static void MarkRoots(RootMarkingVisitor* visitor); | 356 void MarkRoots(RootMarkingVisitor* visitor); |
| 338 | 357 |
| 339 // Mark the symbol table specially. References to symbols from the | 358 // Mark the symbol table specially. References to symbols from the |
| 340 // symbol table are weak. | 359 // symbol table are weak. |
| 341 static void MarkSymbolTable(); | 360 void MarkSymbolTable(); |
| 342 | 361 |
| 343 // Mark objects in object groups that have at least one object in the | 362 // Mark objects in object groups that have at least one object in the |
| 344 // group marked. | 363 // group marked. |
| 345 static void MarkObjectGroups(); | 364 void MarkObjectGroups(); |
| 346 | 365 |
| 347 // Mark objects in implicit references groups if their parent object | 366 // Mark objects in implicit references groups if their parent object |
| 348 // is marked. | 367 // is marked. |
| 349 static void MarkImplicitRefGroups(); | 368 void MarkImplicitRefGroups(); |
| 350 | 369 |
| 351 // Mark all objects which are reachable due to host application | 370 // Mark all objects which are reachable due to host application |
| 352 // logic like object groups or implicit references' groups. | 371 // logic like object groups or implicit references' groups. |
| 353 static void ProcessExternalMarking(); | 372 void ProcessExternalMarking(); |
| 354 | 373 |
| 355 // Mark objects reachable (transitively) from objects in the marking stack | 374 // Mark objects reachable (transitively) from objects in the marking stack |
| 356 // or overflowed in the heap. | 375 // or overflowed in the heap. |
| 357 static void ProcessMarkingStack(); | 376 void ProcessMarkingStack(); |
| 358 | 377 |
| 359 // Mark objects reachable (transitively) from objects in the marking | 378 // Mark objects reachable (transitively) from objects in the marking |
| 360 // stack. This function empties the marking stack, but may leave | 379 // stack. This function empties the marking stack, but may leave |
| 361 // overflowed objects in the heap, in which case the marking stack's | 380 // overflowed objects in the heap, in which case the marking stack's |
| 362 // overflow flag will be set. | 381 // overflow flag will be set. |
| 363 static void EmptyMarkingStack(); | 382 void EmptyMarkingStack(); |
| 364 | 383 |
| 365 // Refill the marking stack with overflowed objects from the heap. This | 384 // Refill the marking stack with overflowed objects from the heap. This |
| 366 // function either leaves the marking stack full or clears the overflow | 385 // function either leaves the marking stack full or clears the overflow |
| 367 // flag on the marking stack. | 386 // flag on the marking stack. |
| 368 static void RefillMarkingStack(); | 387 void RefillMarkingStack(); |
| 369 | 388 |
| 370 // Callback function for telling whether the object *p is an unmarked | 389 // Callback function for telling whether the object *p is an unmarked |
| 371 // heap object. | 390 // heap object. |
| 372 static bool IsUnmarkedHeapObject(Object** p); | 391 static bool IsUnmarkedHeapObject(Object** p); |
| 373 | 392 |
| 374 #ifdef DEBUG | 393 #ifdef DEBUG |
| 375 static void UpdateLiveObjectCount(HeapObject* obj); | 394 void UpdateLiveObjectCount(HeapObject* obj); |
| 376 #endif | 395 #endif |
| 377 | 396 |
| 378 // Test whether a (possibly marked) object is a Map. | 397 // Test whether a (possibly marked) object is a Map. |
| 379 static inline bool SafeIsMap(HeapObject* object); | 398 static inline bool SafeIsMap(HeapObject* object); |
| 380 | 399 |
| 381 // Map transitions from a live map to a dead map must be killed. | 400 // Map transitions from a live map to a dead map must be killed. |
| 382 // We replace them with a null descriptor, with the same key. | 401 // We replace them with a null descriptor, with the same key. |
| 383 static void ClearNonLiveTransitions(); | 402 void ClearNonLiveTransitions(); |
| 384 | 403 |
| 385 // ----------------------------------------------------------------------- | 404 // ----------------------------------------------------------------------- |
| 386 // Phase 2: Sweeping to clear mark bits and free non-live objects for | 405 // Phase 2: Sweeping to clear mark bits and free non-live objects for |
| 387 // a non-compacting collection. | 406 // a non-compacting collection. |
| 388 // | 407 // |
| 389 // Before: Live objects are marked and non-live objects are unmarked. | 408 // Before: Live objects are marked and non-live objects are unmarked. |
| 390 // | 409 // |
| 391 // After: Live objects are unmarked, non-live regions have been added to | 410 // After: Live objects are unmarked, non-live regions have been added to |
| 392 // their space's free list. Active eden semispace is compacted by | 411 // their space's free list. Active eden semispace is compacted by |
| 393 // evacuation. | 412 // evacuation. |
| 394 // | 413 // |
| 395 | 414 |
| 415 |
| 396 // Iterates live objects in a space, passes live objects | 416 // Iterates live objects in a space, passes live objects |
| 397 // to a callback function which returns the heap size of the object. | 417 // to a callback function which returns the heap size of the object. |
| 398 // Returns the number of live objects iterated. | 418 // Returns the number of live objects iterated. |
| 399 static int IterateLiveObjects(NewSpace* space, HeapObjectCallback size_f); | 419 int IterateLiveObjects(NewSpace* space, LiveObjectCallback size_f); |
| 400 static int IterateLiveObjects(PagedSpace* space, HeapObjectCallback size_f); | 420 int IterateLiveObjects(PagedSpace* space, LiveObjectCallback size_f); |
| 401 | 421 |
| 402 // Iterates the live objects between a range of addresses, returning the | 422 // Iterates the live objects between a range of addresses, returning the |
| 403 // number of live objects. | 423 // number of live objects. |
| 404 static int IterateLiveObjectsInRange(Address start, Address end, | 424 int IterateLiveObjectsInRange(Address start, Address end, |
| 405 HeapObjectCallback size_func); | 425 LiveObjectCallback size_func); |
| 406 | 426 |
| 407 // If we are not compacting the heap, we simply sweep the spaces except | 427 // If we are not compacting the heap, we simply sweep the spaces except |
| 408 // for the large object space, clearing mark bits and adding unmarked | 428 // for the large object space, clearing mark bits and adding unmarked |
| 409 // regions to each space's free list. | 429 // regions to each space's free list. |
| 410 static void SweepSpaces(); | 430 void SweepSpaces(); |
| 411 | 431 |
| 412 static void SweepNewSpace(NewSpace* space); | 432 void SweepNewSpace(NewSpace* space); |
| 413 | 433 |
| 414 enum SweeperType { CONSERVATIVE, PRECISE }; | 434 enum SweeperType { CONSERVATIVE, PRECISE }; |
| 415 | 435 |
| 416 static void SweepSpace(PagedSpace* space, SweeperType sweeper); | 436 void SweepSpace(PagedSpace* space, SweeperType sweeper); |
| 417 | 437 |
| 418 #ifdef DEBUG | 438 #ifdef DEBUG |
| 419 // ----------------------------------------------------------------------- | 439 // ----------------------------------------------------------------------- |
| 420 // Debugging variables, functions and classes | 440 // Debugging variables, functions and classes |
| 421 // Counters used for debugging the marking phase of mark-compact or | 441 // Counters used for debugging the marking phase of mark-compact or |
| 422 // mark-sweep collection. | 442 // mark-sweep collection. |
| 423 | 443 |
| 424 // Size of live objects in Heap::to_space_. | 444 // Size of live objects in Heap::to_space_. |
| 425 static int live_young_objects_size_; | 445 int live_young_objects_size_; |
| 426 | 446 |
| 427 // Size of live objects in Heap::old_pointer_space_. | 447 // Size of live objects in Heap::old_pointer_space_. |
| 428 static int live_old_pointer_objects_size_; | 448 int live_old_pointer_objects_size_; |
| 429 | 449 |
| 430 // Size of live objects in Heap::old_data_space_. | 450 // Size of live objects in Heap::old_data_space_. |
| 431 static int live_old_data_objects_size_; | 451 int live_old_data_objects_size_; |
| 432 | 452 |
| 433 // Size of live objects in Heap::code_space_. | 453 // Size of live objects in Heap::code_space_. |
| 434 static int live_code_objects_size_; | 454 int live_code_objects_size_; |
| 435 | 455 |
| 436 // Size of live objects in Heap::map_space_. | 456 // Size of live objects in Heap::map_space_. |
| 437 static int live_map_objects_size_; | 457 int live_map_objects_size_; |
| 438 | 458 |
| 439 // Size of live objects in Heap::cell_space_. | 459 // Size of live objects in Heap::cell_space_. |
| 440 static int live_cell_objects_size_; | 460 int live_cell_objects_size_; |
| 441 | 461 |
| 442 // Size of live objects in Heap::lo_space_. | 462 // Size of live objects in Heap::lo_space_. |
| 443 static int live_lo_objects_size_; | 463 int live_lo_objects_size_; |
| 444 | 464 |
| 445 // Number of live bytes in this collection. | 465 // Number of live bytes in this collection. |
| 446 static int live_bytes_; | 466 int live_bytes_; |
| 447 | 467 |
| 448 friend class MarkObjectVisitor; | 468 friend class MarkObjectVisitor; |
| 449 static void VisitObject(HeapObject* obj); | 469 static void VisitObject(HeapObject* obj); |
| 450 | 470 |
| 451 friend class UnmarkObjectVisitor; | 471 friend class UnmarkObjectVisitor; |
| 452 static void UnmarkObject(HeapObject* obj); | 472 static void UnmarkObject(HeapObject* obj); |
| 453 #endif | 473 #endif |
| 474 |
| 475 Heap* heap_; |
| 476 MarkingStack marking_stack_; |
| 477 CodeFlusher* code_flusher_; |
| 478 |
| 479 friend class Heap; |
| 480 friend class OverflowedObjectsScanner; |
| 454 }; | 481 }; |
| 455 | 482 |
| 456 | 483 |
| 457 } } // namespace v8::internal | 484 } } // namespace v8::internal |
| 458 | 485 |
| 459 #endif // V8_MARK_COMPACT_H_ | 486 #endif // V8_MARK_COMPACT_H_ |
| OLD | NEW |