| 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 |