Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(313)

Side by Side Diff: src/heap.cc

Issue 9605008: Merge 10601,10602,10616,10625,10647 from the bleeding edge to the 3.8 branch. (Closed) Base URL: http://v8.googlecode.com/svn/branches/3.8/
Patch Set: Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/heap.h ('k') | src/heap-inl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 218 matching lines...) Expand 10 before | Expand all | Expand 10 after
229 229
230 230
231 int Heap::GcSafeSizeOfOldObject(HeapObject* object) { 231 int Heap::GcSafeSizeOfOldObject(HeapObject* object) {
232 if (IntrusiveMarking::IsMarked(object)) { 232 if (IntrusiveMarking::IsMarked(object)) {
233 return IntrusiveMarking::SizeOfMarkedObject(object); 233 return IntrusiveMarking::SizeOfMarkedObject(object);
234 } 234 }
235 return object->SizeFromMap(object->map()); 235 return object->SizeFromMap(object->map());
236 } 236 }
237 237
238 238
239 GarbageCollector Heap::SelectGarbageCollector(AllocationSpace space) { 239 GarbageCollector Heap::SelectGarbageCollector(AllocationSpace space,
240 const char** reason) {
240 // Is global GC requested? 241 // Is global GC requested?
241 if (space != NEW_SPACE || FLAG_gc_global) { 242 if (space != NEW_SPACE || FLAG_gc_global) {
242 isolate_->counters()->gc_compactor_caused_by_request()->Increment(); 243 isolate_->counters()->gc_compactor_caused_by_request()->Increment();
244 *reason = "GC in old space requested";
243 return MARK_COMPACTOR; 245 return MARK_COMPACTOR;
244 } 246 }
245 247
246 // Is enough data promoted to justify a global GC? 248 // Is enough data promoted to justify a global GC?
247 if (OldGenerationPromotionLimitReached()) { 249 if (OldGenerationPromotionLimitReached()) {
248 isolate_->counters()->gc_compactor_caused_by_promoted_data()->Increment(); 250 isolate_->counters()->gc_compactor_caused_by_promoted_data()->Increment();
251 *reason = "promotion limit reached";
249 return MARK_COMPACTOR; 252 return MARK_COMPACTOR;
250 } 253 }
251 254
252 // Have allocation in OLD and LO failed? 255 // Have allocation in OLD and LO failed?
253 if (old_gen_exhausted_) { 256 if (old_gen_exhausted_) {
254 isolate_->counters()-> 257 isolate_->counters()->
255 gc_compactor_caused_by_oldspace_exhaustion()->Increment(); 258 gc_compactor_caused_by_oldspace_exhaustion()->Increment();
259 *reason = "old generations exhausted";
256 return MARK_COMPACTOR; 260 return MARK_COMPACTOR;
257 } 261 }
258 262
259 // Is there enough space left in OLD to guarantee that a scavenge can 263 // Is there enough space left in OLD to guarantee that a scavenge can
260 // succeed? 264 // succeed?
261 // 265 //
262 // Note that MemoryAllocator->MaxAvailable() undercounts the memory available 266 // Note that MemoryAllocator->MaxAvailable() undercounts the memory available
263 // for object promotion. It counts only the bytes that the memory 267 // for object promotion. It counts only the bytes that the memory
264 // allocator has not yet allocated from the OS and assigned to any space, 268 // allocator has not yet allocated from the OS and assigned to any space,
265 // and does not count available bytes already in the old space or code 269 // and does not count available bytes already in the old space or code
266 // space. Undercounting is safe---we may get an unrequested full GC when 270 // space. Undercounting is safe---we may get an unrequested full GC when
267 // a scavenge would have succeeded. 271 // a scavenge would have succeeded.
268 if (isolate_->memory_allocator()->MaxAvailable() <= new_space_.Size()) { 272 if (isolate_->memory_allocator()->MaxAvailable() <= new_space_.Size()) {
269 isolate_->counters()-> 273 isolate_->counters()->
270 gc_compactor_caused_by_oldspace_exhaustion()->Increment(); 274 gc_compactor_caused_by_oldspace_exhaustion()->Increment();
275 *reason = "scavenge might not succeed";
271 return MARK_COMPACTOR; 276 return MARK_COMPACTOR;
272 } 277 }
273 278
274 // Default 279 // Default
280 *reason = NULL;
275 return SCAVENGER; 281 return SCAVENGER;
276 } 282 }
277 283
278 284
279 // TODO(1238405): Combine the infrastructure for --heap-stats and 285 // TODO(1238405): Combine the infrastructure for --heap-stats and
280 // --log-gc to avoid the complicated preprocessor and flag testing. 286 // --log-gc to avoid the complicated preprocessor and flag testing.
281 void Heap::ReportStatisticsBeforeGC() { 287 void Heap::ReportStatisticsBeforeGC() {
282 // Heap::ReportHeapStatistics will also log NewSpace statistics when 288 // Heap::ReportHeapStatistics will also log NewSpace statistics when
283 // compiled --log-gc is set. The following logic is used to avoid 289 // compiled --log-gc is set. The following logic is used to avoid
284 // double logging. 290 // double logging.
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
424 symbol_table()->NumberOfElements()); 430 symbol_table()->NumberOfElements());
425 #if defined(DEBUG) 431 #if defined(DEBUG)
426 ReportStatisticsAfterGC(); 432 ReportStatisticsAfterGC();
427 #endif // DEBUG 433 #endif // DEBUG
428 #ifdef ENABLE_DEBUGGER_SUPPORT 434 #ifdef ENABLE_DEBUGGER_SUPPORT
429 isolate_->debug()->AfterGarbageCollection(); 435 isolate_->debug()->AfterGarbageCollection();
430 #endif // ENABLE_DEBUGGER_SUPPORT 436 #endif // ENABLE_DEBUGGER_SUPPORT
431 } 437 }
432 438
433 439
434 void Heap::CollectAllGarbage(int flags) { 440 void Heap::CollectAllGarbage(int flags, const char* gc_reason) {
435 // Since we are ignoring the return value, the exact choice of space does 441 // Since we are ignoring the return value, the exact choice of space does
436 // not matter, so long as we do not specify NEW_SPACE, which would not 442 // not matter, so long as we do not specify NEW_SPACE, which would not
437 // cause a full GC. 443 // cause a full GC.
438 mark_compact_collector_.SetFlags(flags); 444 mark_compact_collector_.SetFlags(flags);
439 CollectGarbage(OLD_POINTER_SPACE); 445 CollectGarbage(OLD_POINTER_SPACE, gc_reason);
440 mark_compact_collector_.SetFlags(kNoGCFlags); 446 mark_compact_collector_.SetFlags(kNoGCFlags);
441 } 447 }
442 448
443 449
444 void Heap::CollectAllAvailableGarbage() { 450 void Heap::CollectAllAvailableGarbage(const char* gc_reason) {
445 // Since we are ignoring the return value, the exact choice of space does 451 // Since we are ignoring the return value, the exact choice of space does
446 // not matter, so long as we do not specify NEW_SPACE, which would not 452 // not matter, so long as we do not specify NEW_SPACE, which would not
447 // cause a full GC. 453 // cause a full GC.
448 // Major GC would invoke weak handle callbacks on weakly reachable 454 // Major GC would invoke weak handle callbacks on weakly reachable
449 // handles, but won't collect weakly reachable objects until next 455 // handles, but won't collect weakly reachable objects until next
450 // major GC. Therefore if we collect aggressively and weak handle callback 456 // major GC. Therefore if we collect aggressively and weak handle callback
451 // has been invoked, we rerun major GC to release objects which become 457 // has been invoked, we rerun major GC to release objects which become
452 // garbage. 458 // garbage.
453 // Note: as weak callbacks can execute arbitrary code, we cannot 459 // Note: as weak callbacks can execute arbitrary code, we cannot
454 // hope that eventually there will be no weak callbacks invocations. 460 // hope that eventually there will be no weak callbacks invocations.
455 // Therefore stop recollecting after several attempts. 461 // Therefore stop recollecting after several attempts.
456 mark_compact_collector()->SetFlags(kMakeHeapIterableMask); 462 mark_compact_collector()->SetFlags(kMakeHeapIterableMask |
463 kReduceMemoryFootprintMask);
457 isolate_->compilation_cache()->Clear(); 464 isolate_->compilation_cache()->Clear();
458 const int kMaxNumberOfAttempts = 7; 465 const int kMaxNumberOfAttempts = 7;
459 for (int attempt = 0; attempt < kMaxNumberOfAttempts; attempt++) { 466 for (int attempt = 0; attempt < kMaxNumberOfAttempts; attempt++) {
460 if (!CollectGarbage(OLD_POINTER_SPACE, MARK_COMPACTOR)) { 467 if (!CollectGarbage(OLD_POINTER_SPACE, MARK_COMPACTOR, gc_reason, NULL)) {
461 break; 468 break;
462 } 469 }
463 } 470 }
464 mark_compact_collector()->SetFlags(kNoGCFlags); 471 mark_compact_collector()->SetFlags(kNoGCFlags);
465 new_space_.Shrink(); 472 new_space_.Shrink();
466 UncommitFromSpace(); 473 UncommitFromSpace();
467 Shrink(); 474 Shrink();
468 incremental_marking()->UncommitMarkingDeque(); 475 incremental_marking()->UncommitMarkingDeque();
469 } 476 }
470 477
471 478
472 bool Heap::CollectGarbage(AllocationSpace space, GarbageCollector collector) { 479 bool Heap::CollectGarbage(AllocationSpace space,
480 GarbageCollector collector,
481 const char* gc_reason,
482 const char* collector_reason) {
473 // The VM is in the GC state until exiting this function. 483 // The VM is in the GC state until exiting this function.
474 VMState state(isolate_, GC); 484 VMState state(isolate_, GC);
475 485
476 #ifdef DEBUG 486 #ifdef DEBUG
477 // Reset the allocation timeout to the GC interval, but make sure to 487 // Reset the allocation timeout to the GC interval, but make sure to
478 // allow at least a few allocations after a collection. The reason 488 // allow at least a few allocations after a collection. The reason
479 // for this is that we have a lot of allocation sequences and we 489 // for this is that we have a lot of allocation sequences and we
480 // assume that a garbage collection will allow the subsequent 490 // assume that a garbage collection will allow the subsequent
481 // allocation attempts to go through. 491 // allocation attempts to go through.
482 allocation_timeout_ = Max(6, FLAG_gc_interval); 492 allocation_timeout_ = Max(6, FLAG_gc_interval);
483 #endif 493 #endif
484 494
485 if (collector == SCAVENGER && !incremental_marking()->IsStopped()) { 495 if (collector == SCAVENGER && !incremental_marking()->IsStopped()) {
486 if (FLAG_trace_incremental_marking) { 496 if (FLAG_trace_incremental_marking) {
487 PrintF("[IncrementalMarking] Scavenge during marking.\n"); 497 PrintF("[IncrementalMarking] Scavenge during marking.\n");
488 } 498 }
489 } 499 }
490 500
491 if (collector == MARK_COMPACTOR && 501 if (collector == MARK_COMPACTOR &&
492 !mark_compact_collector()->PreciseSweepingRequired() && 502 !mark_compact_collector()->PreciseSweepingRequired() &&
493 !incremental_marking()->IsStopped() && 503 !incremental_marking()->IsStopped() &&
494 !incremental_marking()->should_hurry() && 504 !incremental_marking()->should_hurry() &&
495 FLAG_incremental_marking_steps) { 505 FLAG_incremental_marking_steps) {
496 if (FLAG_trace_incremental_marking) { 506 if (FLAG_trace_incremental_marking) {
497 PrintF("[IncrementalMarking] Delaying MarkSweep.\n"); 507 PrintF("[IncrementalMarking] Delaying MarkSweep.\n");
498 } 508 }
499 collector = SCAVENGER; 509 collector = SCAVENGER;
510 collector_reason = "incremental marking delaying mark-sweep";
500 } 511 }
501 512
502 bool next_gc_likely_to_collect_more = false; 513 bool next_gc_likely_to_collect_more = false;
503 514
504 { GCTracer tracer(this); 515 { GCTracer tracer(this, gc_reason, collector_reason);
505 GarbageCollectionPrologue(); 516 GarbageCollectionPrologue();
506 // The GC count was incremented in the prologue. Tell the tracer about 517 // The GC count was incremented in the prologue. Tell the tracer about
507 // it. 518 // it.
508 tracer.set_gc_count(gc_count_); 519 tracer.set_gc_count(gc_count_);
509 520
510 // Tell the tracer which collector we've selected. 521 // Tell the tracer which collector we've selected.
511 tracer.set_collector(collector); 522 tracer.set_collector(collector);
512 523
513 HistogramTimer* rate = (collector == SCAVENGER) 524 HistogramTimer* rate = (collector == SCAVENGER)
514 ? isolate_->counters()->gc_scavenger() 525 ? isolate_->counters()->gc_scavenger()
(...skipping 11 matching lines...) Expand all
526 if (incremental_marking()->WorthActivating() && NextGCIsLikelyToBeFull()) { 537 if (incremental_marking()->WorthActivating() && NextGCIsLikelyToBeFull()) {
527 incremental_marking()->Start(); 538 incremental_marking()->Start();
528 } 539 }
529 } 540 }
530 541
531 return next_gc_likely_to_collect_more; 542 return next_gc_likely_to_collect_more;
532 } 543 }
533 544
534 545
535 void Heap::PerformScavenge() { 546 void Heap::PerformScavenge() {
536 GCTracer tracer(this); 547 GCTracer tracer(this, NULL, NULL);
537 if (incremental_marking()->IsStopped()) { 548 if (incremental_marking()->IsStopped()) {
538 PerformGarbageCollection(SCAVENGER, &tracer); 549 PerformGarbageCollection(SCAVENGER, &tracer);
539 } else { 550 } else {
540 PerformGarbageCollection(MARK_COMPACTOR, &tracer); 551 PerformGarbageCollection(MARK_COMPACTOR, &tracer);
541 } 552 }
542 } 553 }
543 554
544 555
545 #ifdef DEBUG 556 #ifdef DEBUG
546 // Helper class for verifying the symbol table. 557 // Helper class for verifying the symbol table.
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
581 PagedSpace* code_space = Heap::code_space(); 592 PagedSpace* code_space = Heap::code_space();
582 PagedSpace* map_space = Heap::map_space(); 593 PagedSpace* map_space = Heap::map_space();
583 PagedSpace* cell_space = Heap::cell_space(); 594 PagedSpace* cell_space = Heap::cell_space();
584 LargeObjectSpace* lo_space = Heap::lo_space(); 595 LargeObjectSpace* lo_space = Heap::lo_space();
585 bool gc_performed = true; 596 bool gc_performed = true;
586 int counter = 0; 597 int counter = 0;
587 static const int kThreshold = 20; 598 static const int kThreshold = 20;
588 while (gc_performed && counter++ < kThreshold) { 599 while (gc_performed && counter++ < kThreshold) {
589 gc_performed = false; 600 gc_performed = false;
590 if (!new_space->ReserveSpace(new_space_size)) { 601 if (!new_space->ReserveSpace(new_space_size)) {
591 Heap::CollectGarbage(NEW_SPACE); 602 Heap::CollectGarbage(NEW_SPACE,
603 "failed to reserve space in the new space");
592 gc_performed = true; 604 gc_performed = true;
593 } 605 }
594 if (!old_pointer_space->ReserveSpace(pointer_space_size)) { 606 if (!old_pointer_space->ReserveSpace(pointer_space_size)) {
595 Heap::CollectGarbage(OLD_POINTER_SPACE); 607 Heap::CollectGarbage(OLD_POINTER_SPACE,
608 "failed to reserve space in the old pointer space");
596 gc_performed = true; 609 gc_performed = true;
597 } 610 }
598 if (!(old_data_space->ReserveSpace(data_space_size))) { 611 if (!(old_data_space->ReserveSpace(data_space_size))) {
599 Heap::CollectGarbage(OLD_DATA_SPACE); 612 Heap::CollectGarbage(OLD_DATA_SPACE,
613 "failed to reserve space in the old data space");
600 gc_performed = true; 614 gc_performed = true;
601 } 615 }
602 if (!(code_space->ReserveSpace(code_space_size))) { 616 if (!(code_space->ReserveSpace(code_space_size))) {
603 Heap::CollectGarbage(CODE_SPACE); 617 Heap::CollectGarbage(CODE_SPACE,
618 "failed to reserve space in the code space");
604 gc_performed = true; 619 gc_performed = true;
605 } 620 }
606 if (!(map_space->ReserveSpace(map_space_size))) { 621 if (!(map_space->ReserveSpace(map_space_size))) {
607 Heap::CollectGarbage(MAP_SPACE); 622 Heap::CollectGarbage(MAP_SPACE,
623 "failed to reserve space in the map space");
608 gc_performed = true; 624 gc_performed = true;
609 } 625 }
610 if (!(cell_space->ReserveSpace(cell_space_size))) { 626 if (!(cell_space->ReserveSpace(cell_space_size))) {
611 Heap::CollectGarbage(CELL_SPACE); 627 Heap::CollectGarbage(CELL_SPACE,
628 "failed to reserve space in the cell space");
612 gc_performed = true; 629 gc_performed = true;
613 } 630 }
614 // We add a slack-factor of 2 in order to have space for a series of 631 // We add a slack-factor of 2 in order to have space for a series of
615 // large-object allocations that are only just larger than the page size. 632 // large-object allocations that are only just larger than the page size.
616 large_object_size *= 2; 633 large_object_size *= 2;
617 // The ReserveSpace method on the large object space checks how much 634 // The ReserveSpace method on the large object space checks how much
618 // we can expand the old generation. This includes expansion caused by 635 // we can expand the old generation. This includes expansion caused by
619 // allocation in the other spaces. 636 // allocation in the other spaces.
620 large_object_size += cell_space_size + map_space_size + code_space_size + 637 large_object_size += cell_space_size + map_space_size + code_space_size +
621 data_space_size + pointer_space_size; 638 data_space_size + pointer_space_size;
622 if (!(lo_space->ReserveSpace(large_object_size))) { 639 if (!(lo_space->ReserveSpace(large_object_size))) {
623 Heap::CollectGarbage(LO_SPACE); 640 Heap::CollectGarbage(LO_SPACE,
641 "failed to reserve space in the large object space");
624 gc_performed = true; 642 gc_performed = true;
625 } 643 }
626 } 644 }
627 645
628 if (gc_performed) { 646 if (gc_performed) {
629 // Failed to reserve the space after several attempts. 647 // Failed to reserve the space after several attempts.
630 V8::FatalProcessOutOfMemory("Heap::ReserveSpace"); 648 V8::FatalProcessOutOfMemory("Heap::ReserveSpace");
631 } 649 }
632 } 650 }
633 651
(...skipping 3968 matching lines...) Expand 10 before | Expand all | Expand 10 after
4602 4620
4603 bool Heap::IsHeapIterable() { 4621 bool Heap::IsHeapIterable() {
4604 return (!old_pointer_space()->was_swept_conservatively() && 4622 return (!old_pointer_space()->was_swept_conservatively() &&
4605 !old_data_space()->was_swept_conservatively()); 4623 !old_data_space()->was_swept_conservatively());
4606 } 4624 }
4607 4625
4608 4626
4609 void Heap::EnsureHeapIsIterable() { 4627 void Heap::EnsureHeapIsIterable() {
4610 ASSERT(IsAllocationAllowed()); 4628 ASSERT(IsAllocationAllowed());
4611 if (!IsHeapIterable()) { 4629 if (!IsHeapIterable()) {
4612 CollectAllGarbage(kMakeHeapIterableMask); 4630 CollectAllGarbage(kMakeHeapIterableMask, "Heap::EnsureHeapIsIterable");
4613 } 4631 }
4614 ASSERT(IsHeapIterable()); 4632 ASSERT(IsHeapIterable());
4615 } 4633 }
4616 4634
4617 4635
4618 bool Heap::IdleNotification(int hint) { 4636 bool Heap::IdleNotification(int hint) {
4619 if (hint >= 1000) return IdleGlobalGC(); 4637 if (hint >= 1000) return IdleGlobalGC();
4620 if (contexts_disposed_ > 0 || !FLAG_incremental_marking || 4638 if (contexts_disposed_ > 0 || !FLAG_incremental_marking ||
4621 FLAG_expose_gc || Serializer::enabled()) { 4639 FLAG_expose_gc || Serializer::enabled()) {
4622 return true; 4640 return true;
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
4672 incremental_marking()->Step(step_size); 4690 incremental_marking()->Step(step_size);
4673 idle_notification_will_schedule_next_gc_ = false; 4691 idle_notification_will_schedule_next_gc_ = false;
4674 4692
4675 if (incremental_marking()->IsComplete()) { 4693 if (incremental_marking()->IsComplete()) {
4676 bool uncommit = false; 4694 bool uncommit = false;
4677 if (gc_count_at_last_idle_gc_ == gc_count_) { 4695 if (gc_count_at_last_idle_gc_ == gc_count_) {
4678 // No GC since the last full GC, the mutator is probably not active. 4696 // No GC since the last full GC, the mutator is probably not active.
4679 isolate_->compilation_cache()->Clear(); 4697 isolate_->compilation_cache()->Clear();
4680 uncommit = true; 4698 uncommit = true;
4681 } 4699 }
4682 CollectAllGarbage(kNoGCFlags); 4700 CollectAllGarbage(kNoGCFlags, "idle notification: finalize incremental");
4683 gc_count_at_last_idle_gc_ = gc_count_; 4701 gc_count_at_last_idle_gc_ = gc_count_;
4684 if (uncommit) { 4702 if (uncommit) {
4685 new_space_.Shrink(); 4703 new_space_.Shrink();
4686 UncommitFromSpace(); 4704 UncommitFromSpace();
4687 } 4705 }
4688 } 4706 }
4689 return false; 4707 return false;
4690 } 4708 }
4691 4709
4692 4710
(...skipping 20 matching lines...) Expand all
4713 number_idle_notifications_ = 4731 number_idle_notifications_ =
4714 Min(number_idle_notifications_ + 1, kMaxIdleCount); 4732 Min(number_idle_notifications_ + 1, kMaxIdleCount);
4715 } else { 4733 } else {
4716 number_idle_notifications_ = 0; 4734 number_idle_notifications_ = 0;
4717 last_idle_notification_gc_count_ = gc_count_; 4735 last_idle_notification_gc_count_ = gc_count_;
4718 } 4736 }
4719 4737
4720 if (number_idle_notifications_ == kIdlesBeforeScavenge) { 4738 if (number_idle_notifications_ == kIdlesBeforeScavenge) {
4721 if (contexts_disposed_ > 0) { 4739 if (contexts_disposed_ > 0) {
4722 HistogramTimerScope scope(isolate_->counters()->gc_context()); 4740 HistogramTimerScope scope(isolate_->counters()->gc_context());
4723 CollectAllGarbage(kNoGCFlags); 4741 CollectAllGarbage(kReduceMemoryFootprintMask,
4742 "idle notification: contexts disposed");
4724 } else { 4743 } else {
4725 CollectGarbage(NEW_SPACE); 4744 CollectGarbage(NEW_SPACE, "idle notification");
4726 } 4745 }
4727 new_space_.Shrink(); 4746 new_space_.Shrink();
4728 last_idle_notification_gc_count_ = gc_count_; 4747 last_idle_notification_gc_count_ = gc_count_;
4729 } else if (number_idle_notifications_ == kIdlesBeforeMarkSweep) { 4748 } else if (number_idle_notifications_ == kIdlesBeforeMarkSweep) {
4730 // Before doing the mark-sweep collections we clear the 4749 // Before doing the mark-sweep collections we clear the
4731 // compilation cache to avoid hanging on to source code and 4750 // compilation cache to avoid hanging on to source code and
4732 // generated code for cached functions. 4751 // generated code for cached functions.
4733 isolate_->compilation_cache()->Clear(); 4752 isolate_->compilation_cache()->Clear();
4734 4753
4735 CollectAllGarbage(kNoGCFlags); 4754 CollectAllGarbage(kReduceMemoryFootprintMask, "idle notification");
4736 new_space_.Shrink(); 4755 new_space_.Shrink();
4737 last_idle_notification_gc_count_ = gc_count_; 4756 last_idle_notification_gc_count_ = gc_count_;
4738 4757
4739 } else if (number_idle_notifications_ == kIdlesBeforeMarkCompact) { 4758 } else if (number_idle_notifications_ == kIdlesBeforeMarkCompact) {
4740 CollectAllGarbage(kNoGCFlags); 4759 CollectAllGarbage(kReduceMemoryFootprintMask, "idle notification");
4741 new_space_.Shrink(); 4760 new_space_.Shrink();
4742 last_idle_notification_gc_count_ = gc_count_; 4761 last_idle_notification_gc_count_ = gc_count_;
4743 number_idle_notifications_ = 0; 4762 number_idle_notifications_ = 0;
4744 finished = true; 4763 finished = true;
4745 } else if (contexts_disposed_ > 0) { 4764 } else if (contexts_disposed_ > 0) {
4746 if (FLAG_expose_gc) { 4765 if (FLAG_expose_gc) {
4747 contexts_disposed_ = 0; 4766 contexts_disposed_ = 0;
4748 } else { 4767 } else {
4749 HistogramTimerScope scope(isolate_->counters()->gc_context()); 4768 HistogramTimerScope scope(isolate_->counters()->gc_context());
4750 CollectAllGarbage(kNoGCFlags); 4769 CollectAllGarbage(kReduceMemoryFootprintMask,
4770 "idle notification: contexts disposed");
4751 last_idle_notification_gc_count_ = gc_count_; 4771 last_idle_notification_gc_count_ = gc_count_;
4752 } 4772 }
4753 // If this is the first idle notification, we reset the 4773 // If this is the first idle notification, we reset the
4754 // notification count to avoid letting idle notifications for 4774 // notification count to avoid letting idle notifications for
4755 // context disposal garbage collections start a potentially too 4775 // context disposal garbage collections start a potentially too
4756 // aggressive idle GC cycle. 4776 // aggressive idle GC cycle.
4757 if (number_idle_notifications_ <= 1) { 4777 if (number_idle_notifications_ <= 1) {
4758 number_idle_notifications_ = 0; 4778 number_idle_notifications_ = 0;
4759 uncommit = false; 4779 uncommit = false;
4760 } 4780 }
(...skipping 1610 matching lines...) Expand 10 before | Expand all | Expand 10 after
6371 OldSpaces spaces; 6391 OldSpaces spaces;
6372 for (OldSpace* space = spaces.next(); 6392 for (OldSpace* space = spaces.next();
6373 space != NULL; 6393 space != NULL;
6374 space = spaces.next()) { 6394 space = spaces.next()) {
6375 holes_size += space->Waste() + space->Available(); 6395 holes_size += space->Waste() + space->Available();
6376 } 6396 }
6377 return holes_size; 6397 return holes_size;
6378 } 6398 }
6379 6399
6380 6400
6381 GCTracer::GCTracer(Heap* heap) 6401 GCTracer::GCTracer(Heap* heap,
6402 const char* gc_reason,
6403 const char* collector_reason)
6382 : start_time_(0.0), 6404 : start_time_(0.0),
6383 start_size_(0), 6405 start_size_(0),
6384 gc_count_(0), 6406 gc_count_(0),
6385 full_gc_count_(0), 6407 full_gc_count_(0),
6386 allocated_since_last_gc_(0), 6408 allocated_since_last_gc_(0),
6387 spent_in_mutator_(0), 6409 spent_in_mutator_(0),
6388 promoted_objects_size_(0), 6410 promoted_objects_size_(0),
6389 heap_(heap) { 6411 heap_(heap),
6412 gc_reason_(gc_reason),
6413 collector_reason_(collector_reason) {
6390 if (!FLAG_trace_gc && !FLAG_print_cumulative_gc_stat) return; 6414 if (!FLAG_trace_gc && !FLAG_print_cumulative_gc_stat) return;
6391 start_time_ = OS::TimeCurrentMillis(); 6415 start_time_ = OS::TimeCurrentMillis();
6392 start_size_ = heap_->SizeOfObjects(); 6416 start_size_ = heap_->SizeOfObjects();
6393 6417
6394 for (int i = 0; i < Scope::kNumberOfScopes; i++) { 6418 for (int i = 0; i < Scope::kNumberOfScopes; i++) {
6395 scopes_[i] = 0; 6419 scopes_[i] = 0;
6396 } 6420 }
6397 6421
6398 in_free_list_or_wasted_before_gc_ = CountTotalHolesSize(); 6422 in_free_list_or_wasted_before_gc_ = CountTotalHolesSize();
6399 6423
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
6452 static_cast<int>(steps_took_since_last_gc_), 6476 static_cast<int>(steps_took_since_last_gc_),
6453 steps_count_since_last_gc_); 6477 steps_count_since_last_gc_);
6454 } else { 6478 } else {
6455 PrintF(" (+ %d ms in %d steps since start of marking, " 6479 PrintF(" (+ %d ms in %d steps since start of marking, "
6456 "biggest step %f ms)", 6480 "biggest step %f ms)",
6457 static_cast<int>(steps_took_), 6481 static_cast<int>(steps_took_),
6458 steps_count_, 6482 steps_count_,
6459 longest_step_); 6483 longest_step_);
6460 } 6484 }
6461 } 6485 }
6486
6487 if (gc_reason_ != NULL) {
6488 PrintF(" [%s]", gc_reason_);
6489 }
6490
6491 if (collector_reason_ != NULL) {
6492 PrintF(" [%s]", collector_reason_);
6493 }
6494
6462 PrintF(".\n"); 6495 PrintF(".\n");
6463 } else { 6496 } else {
6464 PrintF("pause=%d ", time); 6497 PrintF("pause=%d ", time);
6465 PrintF("mutator=%d ", 6498 PrintF("mutator=%d ",
6466 static_cast<int>(spent_in_mutator_)); 6499 static_cast<int>(spent_in_mutator_));
6467 6500
6468 PrintF("gc="); 6501 PrintF("gc=");
6469 switch (collector_) { 6502 switch (collector_) {
6470 case SCAVENGER: 6503 case SCAVENGER:
6471 PrintF("s"); 6504 PrintF("s");
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after
6709 isolate_->heap()->store_buffer()->Compact(); 6742 isolate_->heap()->store_buffer()->Compact();
6710 isolate_->heap()->store_buffer()->Filter(MemoryChunk::ABOUT_TO_BE_FREED); 6743 isolate_->heap()->store_buffer()->Filter(MemoryChunk::ABOUT_TO_BE_FREED);
6711 for (chunk = chunks_queued_for_free_; chunk != NULL; chunk = next) { 6744 for (chunk = chunks_queued_for_free_; chunk != NULL; chunk = next) {
6712 next = chunk->next_chunk(); 6745 next = chunk->next_chunk();
6713 isolate_->memory_allocator()->Free(chunk); 6746 isolate_->memory_allocator()->Free(chunk);
6714 } 6747 }
6715 chunks_queued_for_free_ = NULL; 6748 chunks_queued_for_free_ = NULL;
6716 } 6749 }
6717 6750
6718 } } // namespace v8::internal 6751 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/heap.h ('k') | src/heap-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698