OLD | NEW |
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 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 23 matching lines...) Expand all Loading... |
34 // Callback function, returns whether an object is alive. The heap size | 34 // Callback function, returns whether an object is alive. The heap size |
35 // of the object is returned in size. It optionally updates the offset | 35 // of the object is returned in size. It optionally updates the offset |
36 // to the first live object in the page (only used for old and map objects). | 36 // to the first live object in the page (only used for old and map objects). |
37 typedef bool (*IsAliveFunction)(HeapObject* obj, int* size, int* offset); | 37 typedef bool (*IsAliveFunction)(HeapObject* obj, int* size, int* offset); |
38 | 38 |
39 // Forward declarations. | 39 // Forward declarations. |
40 class RootMarkingVisitor; | 40 class RootMarkingVisitor; |
41 class MarkingVisitor; | 41 class MarkingVisitor; |
42 | 42 |
43 | 43 |
| 44 class Marking { |
| 45 public: |
| 46 INLINE(static bool IsMarked(HeapObject* obj)) { |
| 47 return IsMarked(obj->address()); |
| 48 } |
| 49 |
| 50 INLINE(static void SetMark(HeapObject* obj)) { |
| 51 SetMark(obj->address()); |
| 52 } |
| 53 |
| 54 INLINE(static void ClearMark(HeapObject* obj)) { |
| 55 ClearMark(obj->address()); |
| 56 } |
| 57 |
| 58 INLINE(static bool TestAndMark(Address addr)) { |
| 59 if (Heap::InNewSpace(addr)) { |
| 60 uint32_t index = Heap::new_space()->Address2MarkbitIndex(addr); |
| 61 return new_space_bitmap_->TestAndSet(index); |
| 62 } else { |
| 63 Page *p = Page::FromAddress(addr); |
| 64 return p->markbits()->TestAndSet(p->Address2Markbit(addr)); |
| 65 } |
| 66 } |
| 67 |
| 68 INLINE(static bool IsMarked(Address addr)) { |
| 69 if (Heap::InNewSpace(addr)) { |
| 70 uint32_t index = Heap::new_space()->Address2MarkbitIndex(addr); |
| 71 return new_space_bitmap_->Get(index); |
| 72 } else { |
| 73 Page *p = Page::FromAddress(addr); |
| 74 return p->markbits()->Get(p->Address2Markbit(addr)); |
| 75 } |
| 76 } |
| 77 |
| 78 INLINE(static void SetMark(Address addr)) { |
| 79 if (Heap::InNewSpace(addr)) { |
| 80 uint32_t index = Heap::new_space()->Address2MarkbitIndex(addr); |
| 81 new_space_bitmap_->Set(index, true); |
| 82 } else { |
| 83 Page *p = Page::FromAddress(addr); |
| 84 p->markbits()->Set(p->FastAddress2Markbit(addr), true); |
| 85 } |
| 86 } |
| 87 |
| 88 INLINE(static void ClearMark(Address addr)) { |
| 89 if (Heap::InNewSpace(addr)) { |
| 90 uint32_t index = Heap::new_space()->Address2MarkbitIndex(addr); |
| 91 new_space_bitmap_->Set(index, false); |
| 92 } else { |
| 93 Page *p = Page::FromAddress(addr); |
| 94 p->markbits()->Set(p->FastAddress2Markbit(addr), false); |
| 95 } |
| 96 } |
| 97 |
| 98 INLINE(static void ClearRange(Address addr, int size)) { |
| 99 if (Heap::InNewSpace(addr)) { |
| 100 uint32_t index = Heap::new_space()->Address2MarkbitIndex(addr); |
| 101 new_space_bitmap_->ClearRange(index, size >> kPointerSizeLog2); |
| 102 } else { |
| 103 Page *p = Page::FromAddress(addr); |
| 104 p->markbits()->ClearRange(p->FastAddress2Markbit(addr), |
| 105 size >> kPointerSizeLog2); |
| 106 } |
| 107 } |
| 108 |
| 109 static bool Setup(); |
| 110 |
| 111 static void TearDown(); |
| 112 |
| 113 private: |
| 114 class BitmapStorageDescriptor { |
| 115 public: |
| 116 INLINE(static int CellsCount(Address addr)) { |
| 117 return HeaderOf(addr)->cells_count_; |
| 118 } |
| 119 |
| 120 static Bitmap<BitmapStorageDescriptor>* Allocate(int cells_count) { |
| 121 VirtualMemory* memory = new VirtualMemory(SizeFor(cells_count)); |
| 122 |
| 123 if (!memory->Commit(memory->address(), memory->size(), false)) { |
| 124 delete memory; |
| 125 return NULL; |
| 126 } |
| 127 |
| 128 Address bitmap_address = |
| 129 reinterpret_cast<Address>(memory->address()) + sizeof(Header); |
| 130 HeaderOf(bitmap_address)->cells_count_ = cells_count; |
| 131 HeaderOf(bitmap_address)->storage_ = memory; |
| 132 return Bitmap<BitmapStorageDescriptor>::FromAddress(bitmap_address); |
| 133 } |
| 134 |
| 135 static void Free(Bitmap<BitmapStorageDescriptor>* bitmap) { |
| 136 delete HeaderOf(bitmap->address())->storage_; |
| 137 } |
| 138 |
| 139 private: |
| 140 struct Header { |
| 141 VirtualMemory* storage_; |
| 142 int cells_count_; |
| 143 }; |
| 144 |
| 145 static int SizeFor(int cell_count) { |
| 146 return sizeof(Header) + |
| 147 Bitmap<BitmapStorageDescriptor>::SizeFor(cell_count); |
| 148 } |
| 149 |
| 150 static Header* HeaderOf(Address addr) { |
| 151 return reinterpret_cast<Header*>(addr - sizeof(Header)); |
| 152 } |
| 153 }; |
| 154 |
| 155 typedef Bitmap<BitmapStorageDescriptor> NewSpaceMarkbitsBitmap; |
| 156 |
| 157 static NewSpaceMarkbitsBitmap* new_space_bitmap_; |
| 158 }; |
| 159 |
44 // ------------------------------------------------------------------------- | 160 // ------------------------------------------------------------------------- |
45 // Mark-Compact collector | 161 // Mark-Compact collector |
46 // | 162 // |
47 // All methods are static. | 163 // All methods are static. |
48 | 164 |
49 class MarkCompactCollector: public AllStatic { | 165 class MarkCompactCollector: public AllStatic { |
50 public: | 166 public: |
51 // Type of functions to compute forwarding addresses of objects in | 167 // Type of functions to compute forwarding addresses of objects in |
52 // compacted spaces. Given an object and its size, return a (non-failure) | 168 // compacted spaces. Given an object and its size, return a (non-failure) |
53 // Object* that will be the object after forwarding. There is a separate | 169 // Object* that will be the object after forwarding. There is a separate |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
95 static bool IsCompacting() { | 211 static bool IsCompacting() { |
96 #ifdef DEBUG | 212 #ifdef DEBUG |
97 // For the purposes of asserts we don't want this to keep returning true | 213 // For the purposes of asserts we don't want this to keep returning true |
98 // after the collection is completed. | 214 // after the collection is completed. |
99 return state_ != IDLE && compacting_collection_; | 215 return state_ != IDLE && compacting_collection_; |
100 #else | 216 #else |
101 return compacting_collection_; | 217 return compacting_collection_; |
102 #endif | 218 #endif |
103 } | 219 } |
104 | 220 |
105 // The count of the number of objects left marked at the end of the last | |
106 // completed full GC (expected to be zero). | |
107 static int previous_marked_count() { return previous_marked_count_; } | |
108 | |
109 // During a full GC, there is a stack-allocated GCTracer that is used for | 221 // During a full GC, there is a stack-allocated GCTracer that is used for |
110 // bookkeeping information. Return a pointer to that tracer. | 222 // bookkeeping information. Return a pointer to that tracer. |
111 static GCTracer* tracer() { return tracer_; } | 223 static GCTracer* tracer() { return tracer_; } |
112 | 224 |
113 #ifdef DEBUG | 225 #ifdef DEBUG |
114 // Checks whether performing mark-compact collection. | 226 // Checks whether performing mark-compact collection. |
115 static bool in_use() { return state_ > PREPARE_GC; } | 227 static bool in_use() { return state_ > PREPARE_GC; } |
116 static bool are_map_pointers_encoded() { return state_ == UPDATE_POINTERS; } | 228 static bool are_map_pointers_encoded() { return state_ == UPDATE_POINTERS; } |
117 #endif | 229 #endif |
118 | 230 |
(...skipping 26 matching lines...) Expand all Loading... |
145 | 257 |
146 // Global flag that forces a compaction. | 258 // Global flag that forces a compaction. |
147 static bool force_compaction_; | 259 static bool force_compaction_; |
148 | 260 |
149 // Global flag indicating whether spaces were compacted on the last GC. | 261 // Global flag indicating whether spaces were compacted on the last GC. |
150 static bool compacting_collection_; | 262 static bool compacting_collection_; |
151 | 263 |
152 // Global flag indicating whether spaces will be compacted on the next GC. | 264 // Global flag indicating whether spaces will be compacted on the next GC. |
153 static bool compact_on_next_gc_; | 265 static bool compact_on_next_gc_; |
154 | 266 |
155 // The number of objects left marked at the end of the last completed full | |
156 // GC (expected to be zero). | |
157 static int previous_marked_count_; | |
158 | |
159 // A pointer to the current stack-allocated GC tracer object during a full | 267 // A pointer to the current stack-allocated GC tracer object during a full |
160 // collection (NULL before and after). | 268 // collection (NULL before and after). |
161 static GCTracer* tracer_; | 269 static GCTracer* tracer_; |
162 | 270 |
163 // Finishes GC, performs heap verification if enabled. | 271 // Finishes GC, performs heap verification if enabled. |
164 static void Finish(); | 272 static void Finish(); |
165 | 273 |
166 // ----------------------------------------------------------------------- | 274 // ----------------------------------------------------------------------- |
167 // Phase 1: Marking live objects. | 275 // Phase 1: Marking live objects. |
168 // | 276 // |
169 // Before: The heap has been prepared for garbage collection by | 277 // Before: The heap has been prepared for garbage collection by |
170 // MarkCompactCollector::Prepare() and is otherwise in its | 278 // MarkCompactCollector::Prepare() and is otherwise in its |
171 // normal state. | 279 // normal state. |
172 // | 280 // |
173 // After: Live objects are marked and non-live objects are unmarked. | 281 // After: Live objects are marked and non-live objects are unmarked. |
174 | 282 |
175 | 283 |
176 friend class RootMarkingVisitor; | 284 friend class RootMarkingVisitor; |
177 friend class MarkingVisitor; | 285 friend class MarkingVisitor; |
178 friend class StaticMarkingVisitor; | 286 friend class StaticMarkingVisitor; |
179 friend class CodeMarkingVisitor; | 287 friend class CodeMarkingVisitor; |
180 friend class SharedFunctionInfoMarkingVisitor; | 288 friend class SharedFunctionInfoMarkingVisitor; |
181 | 289 |
182 static void PrepareForCodeFlushing(); | 290 static void PrepareForCodeFlushing(); |
183 | 291 |
184 // Marking operations for objects reachable from roots. | 292 // Marking operations for objects reachable from roots. |
185 static void MarkLiveObjects(); | 293 static void MarkLiveObjects(); |
186 | 294 |
187 static void MarkUnmarkedObject(HeapObject* obj); | |
188 | |
189 static inline void MarkObject(HeapObject* obj) { | 295 static inline void MarkObject(HeapObject* obj) { |
190 if (!obj->IsMarked()) MarkUnmarkedObject(obj); | 296 if (!Marking::TestAndMark(obj->address())) { |
| 297 tracer_->increment_marked_count(); |
| 298 #ifdef DEBUG |
| 299 UpdateLiveObjectCount(obj); |
| 300 #endif |
| 301 ProcessNewlyMarkedObject(obj); |
| 302 } |
191 } | 303 } |
192 | 304 |
193 static inline void SetMark(HeapObject* obj) { | 305 static inline void SetMark(HeapObject* obj) { |
| 306 Marking::SetMark(obj); |
194 tracer_->increment_marked_count(); | 307 tracer_->increment_marked_count(); |
195 #ifdef DEBUG | 308 #ifdef DEBUG |
196 UpdateLiveObjectCount(obj); | 309 UpdateLiveObjectCount(obj); |
197 #endif | 310 #endif |
198 obj->SetMark(); | |
199 } | 311 } |
200 | 312 |
| 313 static void ProcessNewlyMarkedObject(HeapObject* obj); |
| 314 |
201 // Creates back pointers for all map transitions, stores them in | 315 // Creates back pointers for all map transitions, stores them in |
202 // the prototype field. The original prototype pointers are restored | 316 // the prototype field. The original prototype pointers are restored |
203 // in ClearNonLiveTransitions(). All JSObject maps | 317 // in ClearNonLiveTransitions(). All JSObject maps |
204 // connected by map transitions have the same prototype object, which | 318 // connected by map transitions have the same prototype object, which |
205 // is why we can use this field temporarily for back pointers. | 319 // is why we can use this field temporarily for back pointers. |
206 static void CreateBackPointers(); | 320 static void CreateBackPointers(); |
207 | 321 |
208 // Mark a Map and its DescriptorArray together, skipping transitions. | 322 // Mark a Map and its DescriptorArray together, skipping transitions. |
209 static void MarkMapContents(Map* map); | 323 static void MarkMapContents(Map* map); |
210 static void MarkDescriptorArray(DescriptorArray* descriptors); | 324 static void MarkDescriptorArray(DescriptorArray* descriptors); |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
279 // Iterates the live objects between a range of addresses, returning the | 393 // Iterates the live objects between a range of addresses, returning the |
280 // number of live objects. | 394 // number of live objects. |
281 static int IterateLiveObjectsInRange(Address start, Address end, | 395 static int IterateLiveObjectsInRange(Address start, Address end, |
282 HeapObjectCallback size_func); | 396 HeapObjectCallback size_func); |
283 | 397 |
284 // If we are not compacting the heap, we simply sweep the spaces except | 398 // If we are not compacting the heap, we simply sweep the spaces except |
285 // for the large object space, clearing mark bits and adding unmarked | 399 // for the large object space, clearing mark bits and adding unmarked |
286 // regions to each space's free list. | 400 // regions to each space's free list. |
287 static void SweepSpaces(); | 401 static void SweepSpaces(); |
288 | 402 |
| 403 static void SweepNewSpace(NewSpace* space); |
| 404 static void SweepSpace(PagedSpace* space); |
| 405 |
289 #ifdef DEBUG | 406 #ifdef DEBUG |
290 // ----------------------------------------------------------------------- | 407 // ----------------------------------------------------------------------- |
291 // Debugging variables, functions and classes | 408 // Debugging variables, functions and classes |
292 // Counters used for debugging the marking phase of mark-compact or | 409 // Counters used for debugging the marking phase of mark-compact or |
293 // mark-sweep collection. | 410 // mark-sweep collection. |
294 | 411 |
295 // Size of live objects in Heap::to_space_. | 412 // Size of live objects in Heap::to_space_. |
296 static int live_young_objects_size_; | 413 static int live_young_objects_size_; |
297 | 414 |
298 // Size of live objects in Heap::old_pointer_space_. | 415 // Size of live objects in Heap::old_pointer_space_. |
(...skipping 22 matching lines...) Expand all Loading... |
321 | 438 |
322 friend class UnmarkObjectVisitor; | 439 friend class UnmarkObjectVisitor; |
323 static void UnmarkObject(HeapObject* obj); | 440 static void UnmarkObject(HeapObject* obj); |
324 #endif | 441 #endif |
325 }; | 442 }; |
326 | 443 |
327 | 444 |
328 } } // namespace v8::internal | 445 } } // namespace v8::internal |
329 | 446 |
330 #endif // V8_MARK_COMPACT_H_ | 447 #endif // V8_MARK_COMPACT_H_ |
OLD | NEW |