| 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 194 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 205           CodeStub::RecordWrite) { | 205           CodeStub::RecordWrite) { | 
| 206         Object* e = stubs->ValueAt(i); | 206         Object* e = stubs->ValueAt(i); | 
| 207         if (e->IsCode()) { | 207         if (e->IsCode()) { | 
| 208           RecordWriteStub::Patch(Code::cast(e), enable); | 208           RecordWriteStub::Patch(Code::cast(e), enable); | 
| 209         } | 209         } | 
| 210       } | 210       } | 
| 211     } | 211     } | 
| 212   } | 212   } | 
| 213 } | 213 } | 
| 214 | 214 | 
| 215 static VirtualMemory* marking_stack_memory = NULL; | 215 static VirtualMemory* marking_deque_memory = NULL; | 
| 216 | 216 | 
| 217 static void EnsureMarkingStackIsCommitted() { | 217 static void EnsureMarkingDequeIsCommitted() { | 
| 218   if (marking_stack_memory == NULL) { | 218   if (marking_deque_memory == NULL) { | 
| 219     marking_stack_memory = new VirtualMemory(4*MB); | 219     marking_deque_memory = new VirtualMemory(4*MB); | 
| 220     marking_stack_memory->Commit( | 220     marking_deque_memory->Commit( | 
| 221         reinterpret_cast<Address>(marking_stack_memory->address()), | 221         reinterpret_cast<Address>(marking_deque_memory->address()), | 
| 222         marking_stack_memory->size(), | 222         marking_deque_memory->size(), | 
| 223         false);  // Not executable. | 223         false);  // Not executable. | 
| 224   } | 224   } | 
| 225 } | 225 } | 
| 226 | 226 | 
| 227 | 227 | 
| 228 void IncrementalMarking::Start() { | 228 void IncrementalMarking::Start() { | 
| 229   if (FLAG_trace_incremental_marking) { | 229   if (FLAG_trace_incremental_marking) { | 
| 230     PrintF("[IncrementalMarking] Start\n"); | 230     PrintF("[IncrementalMarking] Start\n"); | 
| 231   } | 231   } | 
| 232   ASSERT(FLAG_incremental_marking); | 232   ASSERT(FLAG_incremental_marking); | 
| 233   ASSERT(state_ == STOPPED); | 233   ASSERT(state_ == STOPPED); | 
| 234   state_ = MARKING; | 234   state_ = MARKING; | 
| 235 | 235 | 
| 236   ResetStepCounters(); | 236   ResetStepCounters(); | 
| 237 | 237 | 
| 238   PatchIncrementalMarkingRecordWriteStubs(true); | 238   PatchIncrementalMarkingRecordWriteStubs(true); | 
| 239 | 239 | 
| 240   EnsureMarkingStackIsCommitted(); | 240   EnsureMarkingDequeIsCommitted(); | 
| 241 | 241 | 
| 242   // Initialize marking stack. | 242   // Initialize marking stack. | 
| 243   Address addr = static_cast<Address>(marking_stack_memory->address()); | 243   Address addr = static_cast<Address>(marking_deque_memory->address()); | 
| 244   marking_stack_.Initialize(addr, | 244   marking_deque_.Initialize(addr, | 
| 245                             addr + marking_stack_memory->size()); | 245                             addr + marking_deque_memory->size()); | 
| 246 | 246 | 
| 247   // Clear markbits. | 247   // Clear markbits. | 
| 248   Address new_space_low = heap_->new_space()->ToSpaceLow(); | 248   Address new_space_low = heap_->new_space()->ToSpaceLow(); | 
| 249   Address new_space_high = heap_->new_space()->ToSpaceHigh(); | 249   Address new_space_high = heap_->new_space()->ToSpaceHigh(); | 
| 250   heap_->marking()->ClearRange( | 250   heap_->marking()->ClearRange( | 
| 251       new_space_low, static_cast<int>(new_space_high - new_space_low)); | 251       new_space_low, static_cast<int>(new_space_high - new_space_low)); | 
| 252 | 252 | 
| 253   ClearMarkbits(); | 253   ClearMarkbits(); | 
| 254 | 254 | 
| 255 #ifdef DEBUG | 255 #ifdef DEBUG | 
| (...skipping 16 matching lines...) Expand all  Loading... | 
| 272 void IncrementalMarking::PrepareForScavenge() { | 272 void IncrementalMarking::PrepareForScavenge() { | 
| 273   if (IsStopped()) return; | 273   if (IsStopped()) return; | 
| 274 | 274 | 
| 275   Address new_space_low = heap_->new_space()->FromSpaceLow(); | 275   Address new_space_low = heap_->new_space()->FromSpaceLow(); | 
| 276   Address new_space_high = heap_->new_space()->FromSpaceHigh(); | 276   Address new_space_high = heap_->new_space()->FromSpaceHigh(); | 
| 277   heap_->marking()->ClearRange( | 277   heap_->marking()->ClearRange( | 
| 278       new_space_low, static_cast<int>(new_space_high - new_space_low)); | 278       new_space_low, static_cast<int>(new_space_high - new_space_low)); | 
| 279 } | 279 } | 
| 280 | 280 | 
| 281 | 281 | 
| 282 void IncrementalMarking::UpdateMarkingStackAfterScavenge() { | 282 void IncrementalMarking::UpdateMarkingDequeAfterScavenge() { | 
| 283   if (IsStopped()) return; | 283   if (IsStopped()) return; | 
| 284 | 284 | 
| 285   HeapObject** current = marking_stack_.low(); | 285   intptr_t current = marking_deque_.bottom(); | 
| 286   HeapObject** top = marking_stack_.top(); | 286   intptr_t mask = marking_deque_.mask(); | 
| 287   HeapObject** new_top = current; | 287   intptr_t limit = marking_deque_.top(); | 
|  | 288   HeapObject** array = marking_deque_.array(); | 
|  | 289   intptr_t new_top = current; | 
| 288 | 290 | 
| 289   while (current < top) { | 291   while (current != limit) { | 
| 290     HeapObject* obj = *current++; | 292     HeapObject* obj = array[current]; | 
|  | 293     current = ((current + 1) & mask); | 
| 291     if (heap_->InNewSpace(obj)) { | 294     if (heap_->InNewSpace(obj)) { | 
| 292       MapWord map_word = obj->map_word(); | 295       MapWord map_word = obj->map_word(); | 
| 293       if (map_word.IsForwardingAddress()) { | 296       if (map_word.IsForwardingAddress()) { | 
| 294         HeapObject* dest = map_word.ToForwardingAddress(); | 297         HeapObject* dest = map_word.ToForwardingAddress(); | 
| 295         WhiteToGrey(dest, heap_->marking()->MarkBitFrom(dest)); | 298         WhiteToGrey(dest, heap_->marking()->MarkBitFrom(dest)); | 
| 296         *new_top++ = dest; | 299         array[new_top] = dest; | 
|  | 300         new_top = ((new_top + 1) & mask); | 
| 297         ASSERT(Color(obj) == Color(dest)); | 301         ASSERT(Color(obj) == Color(dest)); | 
| 298       } | 302       } | 
| 299     } else { | 303     } else { | 
| 300       *new_top++ = obj; | 304       array[new_top] = obj; | 
|  | 305       new_top = ((new_top + 1) & mask); | 
| 301     } | 306     } | 
| 302   } | 307   } | 
| 303 | 308 | 
| 304   marking_stack_.set_top(new_top); | 309   marking_deque_.set_top(new_top); | 
| 305 } | 310 } | 
| 306 | 311 | 
| 307 | 312 | 
| 308 void IncrementalMarking::Hurry() { | 313 void IncrementalMarking::Hurry() { | 
| 309   if (state() == MARKING) { | 314   if (state() == MARKING) { | 
| 310     double start = 0.0; | 315     double start = 0.0; | 
| 311     if (FLAG_trace_incremental_marking) { | 316     if (FLAG_trace_incremental_marking) { | 
| 312       PrintF("[IncrementalMarking] Hurry\n"); | 317       PrintF("[IncrementalMarking] Hurry\n"); | 
| 313       start = OS::TimeCurrentMillis(); | 318       start = OS::TimeCurrentMillis(); | 
| 314     } | 319     } | 
| 315     // TODO(gc) hurry can mark objects it encounters black as mutator | 320     // TODO(gc) hurry can mark objects it encounters black as mutator | 
| 316     // was stopped. | 321     // was stopped. | 
| 317     Map* filler_map = heap_->one_pointer_filler_map(); | 322     Map* filler_map = heap_->one_pointer_filler_map(); | 
| 318     IncrementalMarkingMarkingVisitor marking_visitor(heap_, this); | 323     IncrementalMarkingMarkingVisitor marking_visitor(heap_, this); | 
| 319     while (!marking_stack_.is_empty()) { | 324     while (!marking_deque_.IsEmpty()) { | 
| 320       HeapObject* obj = marking_stack_.Pop(); | 325       HeapObject* obj = marking_deque_.Pop(); | 
| 321 | 326 | 
| 322       // Explicitly skip one word fillers. Incremental markbit patterns are | 327       // Explicitly skip one word fillers. Incremental markbit patterns are | 
| 323       // correct only for objects that occupy at least two words. | 328       // correct only for objects that occupy at least two words. | 
| 324       if (obj->map() != filler_map) { | 329       if (obj->map() != filler_map) { | 
| 325         obj->Iterate(&marking_visitor); | 330         obj->Iterate(&marking_visitor); | 
| 326         MarkBit mark_bit = heap_->marking()->MarkBitFrom(obj); | 331         MarkBit mark_bit = heap_->marking()->MarkBitFrom(obj); | 
| 327         MarkBlack(mark_bit); | 332         MarkBlack(mark_bit); | 
| 328       } | 333       } | 
| 329     } | 334     } | 
| 330     state_ = COMPLETE; | 335     state_ = COMPLETE; | 
| 331     if (FLAG_trace_incremental_marking) { | 336     if (FLAG_trace_incremental_marking) { | 
| 332       double end = OS::TimeCurrentMillis(); | 337       double end = OS::TimeCurrentMillis(); | 
| 333       PrintF("[IncrementalMarking] Complete (hurry), spent %d ms.\n", | 338       PrintF("[IncrementalMarking] Complete (hurry), spent %d ms.\n", | 
| 334              static_cast<int>(end - start)); | 339              static_cast<int>(end - start)); | 
| 335     } | 340     } | 
| 336   } | 341   } | 
| 337 } | 342 } | 
| 338 | 343 | 
| 339 | 344 | 
| 340 void IncrementalMarking::Finalize() { | 345 void IncrementalMarking::Finalize() { | 
| 341   Hurry(); | 346   Hurry(); | 
| 342   state_ = STOPPED; | 347   state_ = STOPPED; | 
| 343   heap_->new_space()->LowerInlineAllocationLimit(0); | 348   heap_->new_space()->LowerInlineAllocationLimit(0); | 
| 344   IncrementalMarking::set_should_hurry(false); | 349   IncrementalMarking::set_should_hurry(false); | 
| 345   ResetStepCounters(); | 350   ResetStepCounters(); | 
| 346   PatchIncrementalMarkingRecordWriteStubs(false); | 351   PatchIncrementalMarkingRecordWriteStubs(false); | 
| 347   ASSERT(marking_stack_.is_empty()); | 352   ASSERT(marking_deque_.IsEmpty()); | 
| 348   ISOLATE->stack_guard()->Continue(GC_REQUEST); | 353   ISOLATE->stack_guard()->Continue(GC_REQUEST); | 
| 349 } | 354 } | 
| 350 | 355 | 
| 351 | 356 | 
| 352 void IncrementalMarking::MarkingComplete() { | 357 void IncrementalMarking::MarkingComplete() { | 
| 353   state_ = COMPLETE; | 358   state_ = COMPLETE; | 
| 354   // We will set the stack guard to request a GC now.  This will mean the rest | 359   // We will set the stack guard to request a GC now.  This will mean the rest | 
| 355   // of the GC gets performed as soon as possible (we can't do a GC here in a | 360   // of the GC gets performed as soon as possible (we can't do a GC here in a | 
| 356   // record-write context).  If a few things get allocated between now and then | 361   // record-write context).  If a few things get allocated between now and then | 
| 357   // that shouldn't make us do a scavenge and keep being incremental, so we set | 362   // that shouldn't make us do a scavenge and keep being incremental, so we set | 
| (...skipping 19 matching lines...) Expand all  Loading... | 
| 377       if (FLAG_trace_incremental_marking || FLAG_trace_gc) { | 382       if (FLAG_trace_incremental_marking || FLAG_trace_gc) { | 
| 378         start = OS::TimeCurrentMillis(); | 383         start = OS::TimeCurrentMillis(); | 
| 379       } | 384       } | 
| 380 | 385 | 
| 381       intptr_t bytes_to_process = allocated_ * allocation_marking_factor_; | 386       intptr_t bytes_to_process = allocated_ * allocation_marking_factor_; | 
| 382       int count = 0; | 387       int count = 0; | 
| 383 | 388 | 
| 384       Map* filler_map = heap_->one_pointer_filler_map(); | 389       Map* filler_map = heap_->one_pointer_filler_map(); | 
| 385       IncrementalMarkingMarkingVisitor marking_visitor(heap_, this); | 390       IncrementalMarkingMarkingVisitor marking_visitor(heap_, this); | 
| 386       Marking* marking = heap_->marking(); | 391       Marking* marking = heap_->marking(); | 
| 387       while (!marking_stack_.is_empty() && bytes_to_process > 0) { | 392       while (!marking_deque_.IsEmpty() && bytes_to_process > 0) { | 
| 388         HeapObject* obj = marking_stack_.Pop(); | 393         HeapObject* obj = marking_deque_.Pop(); | 
| 389 | 394 | 
| 390         // Explicitly skip one word fillers. Incremental markbit patterns are | 395         // Explicitly skip one word fillers. Incremental markbit patterns are | 
| 391         // correct only for objects that occupy at least two words. | 396         // correct only for objects that occupy at least two words. | 
| 392         Map* map = obj->map(); | 397         Map* map = obj->map(); | 
| 393         if (map != filler_map) { | 398         if (map != filler_map) { | 
| 394           ASSERT(IsGrey(marking->MarkBitFrom(obj))); | 399           ASSERT(IsGrey(marking->MarkBitFrom(obj))); | 
| 395           int size = obj->SizeFromMap(map); | 400           int size = obj->SizeFromMap(map); | 
| 396           bytes_to_process -= size; | 401           bytes_to_process -= size; | 
| 397           MarkBit map_mark_bit = marking->MarkBitFromOldSpace(map); | 402           MarkBit map_mark_bit = marking->MarkBitFromOldSpace(map); | 
| 398           if (IsWhite(map_mark_bit)) WhiteToGreyAndPush(map, map_mark_bit); | 403           if (IsWhite(map_mark_bit)) WhiteToGreyAndPush(map, map_mark_bit); | 
| 399           // TODO(gc) switch to static visitor instead of normal visitor. | 404           // TODO(gc) switch to static visitor instead of normal visitor. | 
| 400           obj->IterateBody(map->instance_type(), size, &marking_visitor); | 405           obj->IterateBody(map->instance_type(), size, &marking_visitor); | 
| 401           MarkBit obj_mark_bit = marking->MarkBitFrom(obj); | 406           MarkBit obj_mark_bit = marking->MarkBitFrom(obj); | 
| 402           MarkBlack(obj_mark_bit); | 407           MarkBlack(obj_mark_bit); | 
| 403         } | 408         } | 
| 404         count++; | 409         count++; | 
| 405       } | 410       } | 
| 406       allocated_ = 0; | 411       allocated_ = 0; | 
| 407       if (marking_stack_.is_empty()) MarkingComplete(); | 412       if (marking_deque_.IsEmpty()) MarkingComplete(); | 
| 408       if (FLAG_trace_incremental_marking || FLAG_trace_gc) { | 413       if (FLAG_trace_incremental_marking || FLAG_trace_gc) { | 
| 409         double end = OS::TimeCurrentMillis(); | 414         double end = OS::TimeCurrentMillis(); | 
| 410         steps_took_ += (end - start); | 415         steps_took_ += (end - start); | 
| 411       } | 416       } | 
| 412 | 417 | 
| 413       steps_count_++; | 418       steps_count_++; | 
| 414 | 419 | 
| 415       if ((steps_count_ % kAllocationMarkingFactorSpeedupInterval) == 0) { | 420       if ((steps_count_ % kAllocationMarkingFactorSpeedupInterval) == 0) { | 
| 416         allocation_marking_factor_ += kAllocationMarkingFactorSpeedup; | 421         allocation_marking_factor_ += kAllocationMarkingFactorSpeedup; | 
| 417         allocation_marking_factor_ *= 1.3; | 422         allocation_marking_factor_ *= 1.3; | 
| 418         if (FLAG_trace_gc) { | 423         if (FLAG_trace_gc) { | 
| 419           PrintF("Marking speed increased to %d\n", allocation_marking_factor_); | 424           PrintF("Marking speed increased to %d\n", allocation_marking_factor_); | 
| 420         } | 425         } | 
| 421       } | 426       } | 
| 422     } | 427     } | 
| 423   } | 428   } | 
| 424 } | 429 } | 
| 425 | 430 | 
| 426 | 431 | 
| 427 } }  // namespace v8::internal | 432 } }  // namespace v8::internal | 
| OLD | NEW | 
|---|