| 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 19 matching lines...) Expand all Loading... |
| 30 #include "incremental-marking.h" | 30 #include "incremental-marking.h" |
| 31 | 31 |
| 32 #include "code-stubs.h" | 32 #include "code-stubs.h" |
| 33 | 33 |
| 34 namespace v8 { | 34 namespace v8 { |
| 35 namespace internal { | 35 namespace internal { |
| 36 | 36 |
| 37 IncrementalMarking::State IncrementalMarking::state_ = STOPPED; | 37 IncrementalMarking::State IncrementalMarking::state_ = STOPPED; |
| 38 MarkingStack IncrementalMarking::marking_stack_; | 38 MarkingStack IncrementalMarking::marking_stack_; |
| 39 | 39 |
| 40 static double steps_took = 0; |
| 41 static int steps_count = 0; |
| 42 |
| 40 static intptr_t allocated = 0; | 43 static intptr_t allocated = 0; |
| 41 | 44 |
| 42 class IncrementalMarkingMarkingVisitor : public ObjectVisitor { | 45 class IncrementalMarkingMarkingVisitor : public ObjectVisitor { |
| 43 public: | 46 public: |
| 44 void VisitPointer(Object** p) { | 47 void VisitPointer(Object** p) { |
| 45 MarkObjectByPointer(p); | 48 MarkObjectByPointer(p); |
| 46 } | 49 } |
| 47 | 50 |
| 48 void VisitPointers(Object** start, Object** end) { | 51 void VisitPointers(Object** start, Object** end) { |
| 49 for (Object** p = start; p < end; p++) MarkObjectByPointer(p); | 52 for (Object** p = start; p < end; p++) MarkObjectByPointer(p); |
| 50 } | 53 } |
| 51 | 54 |
| 52 private: | 55 private: |
| 53 // Mark object pointed to by p. | 56 // Mark object pointed to by p. |
| 54 INLINE(static void MarkObjectByPointer(Object** p)) { | 57 INLINE(static void MarkObjectByPointer(Object** p)) { |
| 55 Object* obj = *p; | 58 Object* obj = *p; |
| 56 if (obj->IsHeapObject()) { | 59 if (obj->IsHeapObject()) { |
| 57 HeapObject* heap_object = HeapObject::cast(obj); | 60 HeapObject* heap_object = HeapObject::cast(obj); |
| 58 MarkBit mark_bit = Marking::MarkBitFrom(heap_object); | 61 MarkBit mark_bit = Marking::MarkBitFrom(heap_object); |
| 59 if (IncrementalMarking::IsWhite(mark_bit)) { | 62 if (IncrementalMarking::IsWhite(mark_bit)) { |
| 60 IncrementalMarking::WhiteToGrey(heap_object, mark_bit); | 63 IncrementalMarking::WhiteToGreyAndPush(heap_object, mark_bit); |
| 61 } | 64 } |
| 62 } | 65 } |
| 63 } | 66 } |
| 64 }; | 67 }; |
| 65 | 68 |
| 66 | 69 |
| 67 static IncrementalMarkingMarkingVisitor marking_visitor; | 70 static IncrementalMarkingMarkingVisitor marking_visitor; |
| 68 | 71 |
| 69 class IncrementalMarkingRootMarkingVisitor : public ObjectVisitor { | 72 class IncrementalMarkingRootMarkingVisitor : public ObjectVisitor { |
| 70 public: | 73 public: |
| 71 void VisitPointer(Object** p) { | 74 void VisitPointer(Object** p) { |
| 72 MarkObjectByPointer(p); | 75 MarkObjectByPointer(p); |
| 73 } | 76 } |
| 74 | 77 |
| 75 void VisitPointers(Object** start, Object** end) { | 78 void VisitPointers(Object** start, Object** end) { |
| 76 for (Object** p = start; p < end; p++) MarkObjectByPointer(p); | 79 for (Object** p = start; p < end; p++) MarkObjectByPointer(p); |
| 77 } | 80 } |
| 78 | 81 |
| 79 private: | 82 private: |
| 80 void MarkObjectByPointer(Object** p) { | 83 void MarkObjectByPointer(Object** p) { |
| 81 Object* obj = *p; | 84 Object* obj = *p; |
| 82 if (!obj->IsHeapObject()) return; | 85 if (!obj->IsHeapObject()) return; |
| 83 | 86 |
| 84 HeapObject* heap_object = HeapObject::cast(obj); | 87 HeapObject* heap_object = HeapObject::cast(obj); |
| 85 MarkBit mark_bit = Marking::MarkBitFrom(heap_object); | 88 MarkBit mark_bit = Marking::MarkBitFrom(heap_object); |
| 86 if (IncrementalMarking::IsWhite(mark_bit)) { | 89 if (IncrementalMarking::IsWhite(mark_bit)) { |
| 87 IncrementalMarking::WhiteToGrey(heap_object, mark_bit); | 90 IncrementalMarking::WhiteToGreyAndPush(heap_object, mark_bit); |
| 88 } | 91 } |
| 89 } | 92 } |
| 90 }; | 93 }; |
| 91 | 94 |
| 92 | 95 |
| 93 static void ClearMarkbits(PagedSpace* space) { | 96 static void ClearMarkbits(PagedSpace* space) { |
| 94 PageIterator it(space); | 97 PageIterator it(space); |
| 95 | 98 |
| 96 while (it.has_next()) { | 99 while (it.has_next()) { |
| 97 Page* p = it.next(); | 100 Page* p = it.next(); |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 156 CodeStub::IncrementalMarkingRecordWrite) { | 159 CodeStub::IncrementalMarkingRecordWrite) { |
| 157 Object* e = stubs->ValueAt(i); | 160 Object* e = stubs->ValueAt(i); |
| 158 if (e->IsCode()) { | 161 if (e->IsCode()) { |
| 159 IncrementalMarkingRecordWriteStub::Patch(Code::cast(e), enable); | 162 IncrementalMarkingRecordWriteStub::Patch(Code::cast(e), enable); |
| 160 } | 163 } |
| 161 } | 164 } |
| 162 } | 165 } |
| 163 } | 166 } |
| 164 } | 167 } |
| 165 | 168 |
| 169 static VirtualMemory* marking_stack_memory = NULL; |
| 170 |
| 171 static void EnsureMarkingStackIsCommitted() { |
| 172 if (marking_stack_memory == NULL) { |
| 173 marking_stack_memory = new VirtualMemory(4*MB); |
| 174 marking_stack_memory->Commit( |
| 175 reinterpret_cast<Address>(marking_stack_memory->address()), |
| 176 marking_stack_memory->size(), |
| 177 false); // Not executable. |
| 178 } |
| 179 } |
| 180 |
| 166 | 181 |
| 167 void IncrementalMarking::Start() { | 182 void IncrementalMarking::Start() { |
| 168 if (FLAG_trace_incremental_marking) { | 183 if (FLAG_trace_incremental_marking) { |
| 169 PrintF("[IncrementalMarking] Start\n"); | 184 PrintF("[IncrementalMarking] Start\n"); |
| 170 } | 185 } |
| 171 ASSERT(FLAG_incremental_marking); | 186 ASSERT(FLAG_incremental_marking); |
| 172 ASSERT(state_ == STOPPED); | 187 ASSERT(state_ == STOPPED); |
| 173 state_ = MARKING; | 188 state_ = MARKING; |
| 189 steps_took = 0; |
| 190 steps_count = 0; |
| 174 | 191 |
| 175 PatchIncrementalMarkingRecordWriteStubs(true); | 192 PatchIncrementalMarkingRecordWriteStubs(true); |
| 176 | 193 |
| 177 Heap::EnsureFromSpaceIsCommitted(); | 194 EnsureMarkingStackIsCommitted(); |
| 178 | 195 |
| 179 // Initialize marking stack. | 196 // Initialize marking stack. |
| 180 marking_stack_.Initialize(Heap::new_space()->FromSpaceLow(), | 197 Address addr = static_cast<Address>(marking_stack_memory->address()); |
| 181 Heap::new_space()->FromSpaceHigh()); | 198 marking_stack_.Initialize(addr, |
| 199 addr + marking_stack_memory->size()); |
| 182 | 200 |
| 183 // Clear markbits. | 201 // Clear markbits. |
| 184 Address new_space_bottom = Heap::new_space()->bottom(); | 202 Address new_space_low = Heap::new_space()->ToSpaceLow(); |
| 185 uintptr_t new_space_size = | 203 Address new_space_high = Heap::new_space()->ToSpaceHigh(); |
| 186 RoundUp(Heap::new_space()->top() - new_space_bottom, 32 * kPointerSize); | 204 Marking::ClearRange(new_space_low, |
| 187 | 205 static_cast<int>(new_space_high - new_space_low)); |
| 188 Marking::ClearRange(new_space_bottom, new_space_size); | |
| 189 | 206 |
| 190 ClearMarkbits(); | 207 ClearMarkbits(); |
| 191 | 208 |
| 192 #ifdef DEBUG | 209 #ifdef DEBUG |
| 193 VerifyMarkbitsAreClean(); | 210 VerifyMarkbitsAreClean(); |
| 194 #endif | 211 #endif |
| 195 | 212 |
| 196 // Mark strong roots grey. | 213 // Mark strong roots grey. |
| 197 IncrementalMarkingRootMarkingVisitor visitor; | 214 IncrementalMarkingRootMarkingVisitor visitor; |
| 198 Heap::IterateStrongRoots(&visitor, VISIT_ONLY_STRONG); | 215 Heap::IterateStrongRoots(&visitor, VISIT_ONLY_STRONG); |
| 199 | 216 |
| 200 // Ready to start incremental marking. | 217 // Ready to start incremental marking. |
| 201 if (FLAG_trace_incremental_marking) { | 218 if (FLAG_trace_incremental_marking) { |
| 202 PrintF("[IncrementalMarking] Running\n"); | 219 PrintF("[IncrementalMarking] Running\n"); |
| 203 } | 220 } |
| 204 } | 221 } |
| 205 | 222 |
| 206 | 223 |
| 224 void IncrementalMarking::PrepareForScavenge() { |
| 225 if (IsStopped()) return; |
| 226 |
| 227 Address new_space_low = Heap::new_space()->FromSpaceLow(); |
| 228 Address new_space_high = Heap::new_space()->FromSpaceHigh(); |
| 229 Marking::ClearRange(new_space_low, |
| 230 static_cast<int>(new_space_high - new_space_low)); |
| 231 } |
| 232 |
| 233 |
| 234 void IncrementalMarking::UpdateMarkingStackAfterScavenge() { |
| 235 if (IsStopped()) return; |
| 236 |
| 237 HeapObject** current = marking_stack_.low(); |
| 238 HeapObject** top = marking_stack_.top(); |
| 239 HeapObject** new_top = current; |
| 240 |
| 241 while (current < top) { |
| 242 HeapObject* obj = *current++; |
| 243 if (Heap::InNewSpace(obj)) { |
| 244 MapWord map_word = obj->map_word(); |
| 245 if (map_word.IsForwardingAddress()) { |
| 246 HeapObject* dest = map_word.ToForwardingAddress(); |
| 247 WhiteToGrey(dest, Marking::MarkBitFrom(dest)); |
| 248 *new_top++ = dest; |
| 249 ASSERT(Color(obj) == Color(dest)); |
| 250 } |
| 251 } else { |
| 252 *new_top++ = obj; |
| 253 } |
| 254 } |
| 255 |
| 256 marking_stack_.set_top(new_top); |
| 257 } |
| 258 |
| 259 |
| 207 void IncrementalMarking::Hurry() { | 260 void IncrementalMarking::Hurry() { |
| 208 if (state() == MARKING) { | 261 if (state() == MARKING) { |
| 209 double start = 0.0; | 262 double start = 0.0; |
| 210 if (FLAG_trace_incremental_marking) { | 263 if (FLAG_trace_incremental_marking) { |
| 211 PrintF("[IncrementalMarking] Hurry\n"); | 264 PrintF("[IncrementalMarking] Hurry\n"); |
| 212 start = OS::TimeCurrentMillis(); | 265 start = OS::TimeCurrentMillis(); |
| 213 } | 266 } |
| 214 // TODO(gc) hurry can mark objects it encounters black as mutator | 267 // TODO(gc) hurry can mark objects it encounters black as mutator |
| 215 // was stopped. | 268 // was stopped. |
| 216 Map* filler_map = Heap::one_pointer_filler_map(); | 269 Map* filler_map = Heap::one_pointer_filler_map(); |
| 217 while (!marking_stack_.is_empty()) { | 270 while (!marking_stack_.is_empty()) { |
| 218 HeapObject* obj = marking_stack_.Pop(); | 271 HeapObject* obj = marking_stack_.Pop(); |
| 219 | 272 |
| 220 // Explicitly skip one word fillers. Incremental markbit patterns are | 273 // Explicitly skip one word fillers. Incremental markbit patterns are |
| 221 // correct only for objects that occupy at least two words. | 274 // correct only for objects that occupy at least two words. |
| 222 if (obj->map() != filler_map) { | 275 if (obj->map() != filler_map) { |
| 223 obj->Iterate(&marking_visitor); | 276 obj->Iterate(&marking_visitor); |
| 224 MarkBit mark_bit = Marking::MarkBitFrom(obj); | 277 MarkBit mark_bit = Marking::MarkBitFrom(obj); |
| 225 MarkBlack(mark_bit); | 278 MarkBlack(mark_bit); |
| 226 } | 279 } |
| 227 } | 280 } |
| 228 state_ = COMPLETE; | 281 state_ = COMPLETE; |
| 229 if (FLAG_trace_incremental_marking) { | 282 if (FLAG_trace_incremental_marking) { |
| 230 double end = OS::TimeCurrentMillis(); | 283 double end = OS::TimeCurrentMillis(); |
| 231 PrintF("[IncrementalMarking] Complete (hurry), spent %d ms\n", | 284 PrintF("[IncrementalMarking] Complete (hurry), " |
| 232 static_cast<int>(end - start)); | 285 "spent %d ms, %d steps took %d ms (avg %d ms)\n", |
| 286 static_cast<int>(end - start), |
| 287 steps_count, |
| 288 static_cast<int>(steps_took), |
| 289 static_cast<int>(steps_took / steps_count)); |
| 233 } | 290 } |
| 234 } | 291 } |
| 235 } | 292 } |
| 236 | 293 |
| 237 | 294 |
| 238 void IncrementalMarking::Finalize() { | 295 void IncrementalMarking::Finalize() { |
| 239 Hurry(); | 296 Hurry(); |
| 240 state_ = STOPPED; | 297 state_ = STOPPED; |
| 241 PatchIncrementalMarkingRecordWriteStubs(false); | 298 PatchIncrementalMarkingRecordWriteStubs(false); |
| 242 ASSERT(marking_stack_.is_empty()); | 299 ASSERT(marking_stack_.is_empty()); |
| 243 } | 300 } |
| 244 | 301 |
| 245 | 302 |
| 246 void IncrementalMarking::MarkingComplete() { | 303 void IncrementalMarking::MarkingComplete() { |
| 247 state_ = COMPLETE; | 304 state_ = COMPLETE; |
| 248 // We completed marking. | 305 // We completed marking. |
| 249 if (FLAG_trace_incremental_marking) { | 306 if (FLAG_trace_incremental_marking) { |
| 250 PrintF("[IncrementalMarking] Complete (normal)\n"); | 307 PrintF("[IncrementalMarking] Complete (normal), " |
| 308 "%d steps took %d ms (avg %d ms).\n", |
| 309 steps_count, |
| 310 static_cast<int>(steps_took), |
| 311 static_cast<int>(steps_took / steps_count)); |
| 251 } | 312 } |
| 252 StackGuard::RequestGC(); | 313 StackGuard::RequestGC(); |
| 253 } | 314 } |
| 254 | 315 |
| 255 | 316 |
| 256 void IncrementalMarking::Step(intptr_t allocated_bytes) { | 317 void IncrementalMarking::Step(intptr_t allocated_bytes) { |
| 257 if (state_ == MARKING) { | 318 if (state_ == MARKING && Heap::gc_state() == Heap::NOT_IN_GC) { |
| 258 allocated += allocated_bytes; | 319 allocated += allocated_bytes; |
| 259 | 320 |
| 260 if (allocated >= kAllocatedThreshold) { | 321 if (allocated >= kAllocatedThreshold) { |
| 322 double start = 0; |
| 323 if (FLAG_trace_incremental_marking) start = OS::TimeCurrentMillis(); |
| 261 intptr_t bytes_to_process = allocated * kAllocationMarkingFactor; | 324 intptr_t bytes_to_process = allocated * kAllocationMarkingFactor; |
| 262 int count = 0; | 325 int count = 0; |
| 263 double start = 0; | |
| 264 if (FLAG_trace_incremental_marking) { | |
| 265 PrintF("[IncrementalMarking] Marking %d bytes\n", bytes_to_process); | |
| 266 start = OS::TimeCurrentMillis(); | |
| 267 } | |
| 268 | 326 |
| 269 Map* filler_map = Heap::one_pointer_filler_map(); | 327 Map* filler_map = Heap::one_pointer_filler_map(); |
| 270 while (!marking_stack_.is_empty() && bytes_to_process > 0) { | 328 while (!marking_stack_.is_empty() && bytes_to_process > 0) { |
| 271 HeapObject* obj = marking_stack_.Pop(); | 329 HeapObject* obj = marking_stack_.Pop(); |
| 272 | 330 |
| 273 // Explicitly skip one word fillers. Incremental markbit patterns are | 331 // Explicitly skip one word fillers. Incremental markbit patterns are |
| 274 // correct only for objects that occupy at least two words. | 332 // correct only for objects that occupy at least two words. |
| 275 if (obj->map() != filler_map) { | 333 if (obj->map() != filler_map) { |
| 276 ASSERT(IsGrey(Marking::MarkBitFrom(obj))); | 334 ASSERT(IsGrey(Marking::MarkBitFrom(obj))); |
| 335 // TODO(gc) switch to static visitor instead of normal visitor. |
| 277 Map* map = obj->map(); | 336 Map* map = obj->map(); |
| 278 int size = obj->SizeFromMap(map); | 337 int size = obj->SizeFromMap(map); |
| 279 bytes_to_process -= size; | 338 bytes_to_process -= size; |
| 280 MarkBit map_mark_bit = Marking::MarkBitFrom(map); | 339 MarkBit map_mark_bit = Marking::MarkBitFrom(map); |
| 281 if (IsWhite(map_mark_bit)) WhiteToGrey(map, map_mark_bit); | 340 if (IsWhite(map_mark_bit)) WhiteToGreyAndPush(map, map_mark_bit); |
| 282 obj->IterateBody(map->instance_type(), size, &marking_visitor); | 341 obj->IterateBody(map->instance_type(), size, &marking_visitor); |
| 283 MarkBit obj_mark_bit = Marking::MarkBitFrom(obj); | 342 MarkBit obj_mark_bit = Marking::MarkBitFrom(obj); |
| 284 MarkBlack(obj_mark_bit); | 343 MarkBlack(obj_mark_bit); |
| 285 } | 344 } |
| 286 count++; | 345 count++; |
| 287 } | 346 } |
| 347 allocated = 0; |
| 348 if (marking_stack_.is_empty()) MarkingComplete(); |
| 288 if (FLAG_trace_incremental_marking) { | 349 if (FLAG_trace_incremental_marking) { |
| 289 double end = OS::TimeCurrentMillis(); | 350 double end = OS::TimeCurrentMillis(); |
| 290 PrintF("[IncrementalMarking] %d objects marked, spent %d ms\n", | 351 steps_took += (end - start); |
| 291 count, | 352 steps_count++; |
| 292 static_cast<int>(end - start)); | |
| 293 } | 353 } |
| 294 allocated = 0; | |
| 295 if (marking_stack_.is_empty()) MarkingComplete(); | |
| 296 } | 354 } |
| 297 } | 355 } |
| 298 } | 356 } |
| 299 | 357 |
| 300 | 358 |
| 301 } } // namespace v8::internal | 359 } } // namespace v8::internal |
| OLD | NEW |