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

Side by Side Diff: src/heap.cc

Issue 8519002: Start incremental marking on idle notification. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Addressed comments, tuned idle round starting conditions. Created 9 years 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
OLDNEW
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 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
136 max_alive_after_gc_(0), 136 max_alive_after_gc_(0),
137 min_in_mutator_(kMaxInt), 137 min_in_mutator_(kMaxInt),
138 alive_after_last_gc_(0), 138 alive_after_last_gc_(0),
139 last_gc_end_timestamp_(0.0), 139 last_gc_end_timestamp_(0.0),
140 store_buffer_(this), 140 store_buffer_(this),
141 marking_(this), 141 marking_(this),
142 incremental_marking_(this), 142 incremental_marking_(this),
143 number_idle_notifications_(0), 143 number_idle_notifications_(0),
144 last_idle_notification_gc_count_(0), 144 last_idle_notification_gc_count_(0),
145 last_idle_notification_gc_count_init_(false), 145 last_idle_notification_gc_count_init_(false),
146 idle_notification_will_schedule_next_gc_(false),
147 mark_sweeps_since_idle_round_started_(0),
148 ms_count_at_last_idle_notification_(0),
149 gc_count_at_last_idle_gc_(0),
150 scavenges_since_last_idle_round_(kIdleScavengeThreshold),
ulan 2011/11/23 16:18:06 The initial value allows to start the idle round o
146 configured_(false), 151 configured_(false),
147 chunks_queued_for_free_(NULL) { 152 chunks_queued_for_free_(NULL) {
148 // Allow build-time customization of the max semispace size. Building 153 // Allow build-time customization of the max semispace size. Building
149 // V8 with snapshots and a non-default max semispace size is much 154 // V8 with snapshots and a non-default max semispace size is much
150 // easier if you can define it as part of the build environment. 155 // easier if you can define it as part of the build environment.
151 #if defined(V8_MAX_SEMISPACE_SIZE) 156 #if defined(V8_MAX_SEMISPACE_SIZE)
152 max_semispace_size_ = reserved_semispace_size_ = V8_MAX_SEMISPACE_SIZE; 157 max_semispace_size_ = reserved_semispace_size_ = V8_MAX_SEMISPACE_SIZE;
153 #endif 158 #endif
154 159
155 intptr_t max_virtual = OS::MaxVirtualMemory(); 160 intptr_t max_virtual = OS::MaxVirtualMemory();
(...skipping 847 matching lines...) Expand 10 before | Expand all | Expand 10 after
1003 1008
1004 // Used for updating survived_since_last_expansion_ at function end. 1009 // Used for updating survived_since_last_expansion_ at function end.
1005 intptr_t survived_watermark = PromotedSpaceSize(); 1010 intptr_t survived_watermark = PromotedSpaceSize();
1006 1011
1007 CheckNewSpaceExpansionCriteria(); 1012 CheckNewSpaceExpansionCriteria();
1008 1013
1009 SelectScavengingVisitorsTable(); 1014 SelectScavengingVisitorsTable();
1010 1015
1011 incremental_marking()->PrepareForScavenge(); 1016 incremental_marking()->PrepareForScavenge();
1012 1017
1013 old_pointer_space()->AdvanceSweeper(new_space_.Size()); 1018 AdvanceSweepers(new_space_.Size());
1014 old_data_space()->AdvanceSweeper(new_space_.Size());
1015 1019
1016 // Flip the semispaces. After flipping, to space is empty, from space has 1020 // Flip the semispaces. After flipping, to space is empty, from space has
1017 // live objects. 1021 // live objects.
1018 new_space_.Flip(); 1022 new_space_.Flip();
1019 new_space_.ResetAllocationInfo(); 1023 new_space_.ResetAllocationInfo();
1020 1024
1021 // We need to sweep newly copied objects which can be either in the 1025 // We need to sweep newly copied objects which can be either in the
1022 // to space or promoted to the old generation. For to-space 1026 // to space or promoted to the old generation. For to-space
1023 // objects, we treat the bottom of the to space as a queue. Newly 1027 // objects, we treat the bottom of the to space as a queue. Newly
1024 // copied and unswept objects lie between a 'front' mark and the 1028 // copied and unswept objects lie between a 'front' mark and the
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
1092 new_space_.LowerInlineAllocationLimit( 1096 new_space_.LowerInlineAllocationLimit(
1093 new_space_.inline_allocation_limit_step()); 1097 new_space_.inline_allocation_limit_step());
1094 1098
1095 // Update how much has survived scavenge. 1099 // Update how much has survived scavenge.
1096 IncrementYoungSurvivorsCounter(static_cast<int>( 1100 IncrementYoungSurvivorsCounter(static_cast<int>(
1097 (PromotedSpaceSize() - survived_watermark) + new_space_.Size())); 1101 (PromotedSpaceSize() - survived_watermark) + new_space_.Size()));
1098 1102
1099 LOG(isolate_, ResourceEvent("scavenge", "end")); 1103 LOG(isolate_, ResourceEvent("scavenge", "end"));
1100 1104
1101 gc_state_ = NOT_IN_GC; 1105 gc_state_ = NOT_IN_GC;
1106
1107 scavenges_since_last_idle_round_++;
1102 } 1108 }
1103 1109
1104 1110
1105 String* Heap::UpdateNewSpaceReferenceInExternalStringTableEntry(Heap* heap, 1111 String* Heap::UpdateNewSpaceReferenceInExternalStringTableEntry(Heap* heap,
1106 Object** p) { 1112 Object** p) {
1107 MapWord first_word = HeapObject::cast(*p)->map_word(); 1113 MapWord first_word = HeapObject::cast(*p)->map_word();
1108 1114
1109 if (!first_word.IsForwardingAddress()) { 1115 if (!first_word.IsForwardingAddress()) {
1110 // Unreachable external string can be finalized. 1116 // Unreachable external string can be finalized.
1111 heap->FinalizeExternalString(String::cast(*p)); 1117 heap->FinalizeExternalString(String::cast(*p));
(...skipping 3341 matching lines...) Expand 10 before | Expand all | Expand 10 after
4453 4459
4454 void Heap::EnsureHeapIsIterable() { 4460 void Heap::EnsureHeapIsIterable() {
4455 ASSERT(IsAllocationAllowed()); 4461 ASSERT(IsAllocationAllowed());
4456 if (!IsHeapIterable()) { 4462 if (!IsHeapIterable()) {
4457 CollectAllGarbage(kMakeHeapIterableMask); 4463 CollectAllGarbage(kMakeHeapIterableMask);
4458 } 4464 }
4459 ASSERT(IsHeapIterable()); 4465 ASSERT(IsHeapIterable());
4460 } 4466 }
4461 4467
4462 4468
4463 bool Heap::IdleNotification() { 4469 bool Heap::IdleNotification(int hint) {
4470 if (!FLAG_incremental_marking || FLAG_expose_gc) {
4471 return hint < 1000 ? true : IdleGlobalGC();
4472 }
4473
4474 // By doing small chunks of GC work in each IdleNotification,
4475 // perform a round of incremental GCs and after that wait until
4476 // the mutator creates enough garbage to justify a new round.
4477 // An incremental GC progresses as follows:
4478 // 1. many incremental marking steps,
4479 // 2. one old space mark-sweep-compact,
4480 // 3. many lazy sweep steps.
4481 // Use mark-sweep-compact events to count incremental GCs in a round.
4482
4483 intptr_t size_factor = Min(Max(hint, 30), 1000) / 10;
4484 // The size factor is in range [3..100].
4485 intptr_t step_size = size_factor * IncrementalMarking::kAllocatedThreshold;
4486
4487 if (incremental_marking()->IsStopped()) {
4488 if (!IsSweepingComplete() && !AdvanceSweepers(step_size)) {
4489 return false;
4490 }
4491 }
4492
4493 if (mark_sweeps_since_idle_round_started_ >= kMaxMarkSweepsInIdleRound) {
4494 if (EnoughGarbageSinceLastIdleRound()) {
4495 StartIdleRound();
4496 } else {
4497 return true;
4498 }
4499 }
4500
4501 int new_mark_sweeps = ms_count_ - ms_count_at_last_idle_notification_;
4502 mark_sweeps_since_idle_round_started_ += new_mark_sweeps;
4503 ms_count_at_last_idle_notification_ = ms_count_;
4504
4505 if (mark_sweeps_since_idle_round_started_ >= kMaxMarkSweepsInIdleRound) {
4506 FinishIdleRound();
4507 return true;
4508 }
4509
4510 if (incremental_marking()->IsStopped()) {
4511 if (hint < 1000 && !WorthStartingGCWhenIdle()) {
ulan 2011/11/23 16:18:06 If hint >= 1000 then the embedder is asking us to
4512 FinishIdleRound();
4513 return true;
4514 }
4515 incremental_marking()->Start();
4516 }
4517
4518 // This flag prevents incremental marking from requesting GC via stack guard
4519 idle_notification_will_schedule_next_gc_ = true;
4520 incremental_marking()->Step(step_size);
4521 idle_notification_will_schedule_next_gc_ = false;
4522
4523 if (incremental_marking()->IsComplete()) {
4524 bool uncommit = false;
4525 if (gc_count_at_last_idle_gc_ == gc_count_) {
4526 // No GC since the last full GC, the mutator is probably not active.
4527 isolate_->compilation_cache()->Clear();
4528 uncommit = true;
4529 }
4530 CollectAllGarbage(kNoGCFlags);
4531 gc_count_at_last_idle_gc_ = gc_count_;
4532 if (uncommit) {
4533 new_space_.Shrink();
4534 UncommitFromSpace();
4535 }
4536 }
4537 return false;
4538 }
4539
4540
4541 bool Heap::IdleGlobalGC() {
4464 static const int kIdlesBeforeScavenge = 4; 4542 static const int kIdlesBeforeScavenge = 4;
4465 static const int kIdlesBeforeMarkSweep = 7; 4543 static const int kIdlesBeforeMarkSweep = 7;
4466 static const int kIdlesBeforeMarkCompact = 8; 4544 static const int kIdlesBeforeMarkCompact = 8;
4467 static const int kMaxIdleCount = kIdlesBeforeMarkCompact + 1; 4545 static const int kMaxIdleCount = kIdlesBeforeMarkCompact + 1;
4468 static const unsigned int kGCsBetweenCleanup = 4; 4546 static const unsigned int kGCsBetweenCleanup = 4;
4469 4547
4470 if (!last_idle_notification_gc_count_init_) { 4548 if (!last_idle_notification_gc_count_init_) {
4471 last_idle_notification_gc_count_ = gc_count_; 4549 last_idle_notification_gc_count_ = gc_count_;
4472 last_idle_notification_gc_count_init_ = true; 4550 last_idle_notification_gc_count_init_ = true;
4473 } 4551 }
(...skipping 1939 matching lines...) Expand 10 before | Expand all | Expand 10 after
6413 isolate_->heap()->store_buffer()->Compact(); 6491 isolate_->heap()->store_buffer()->Compact();
6414 isolate_->heap()->store_buffer()->Filter(MemoryChunk::ABOUT_TO_BE_FREED); 6492 isolate_->heap()->store_buffer()->Filter(MemoryChunk::ABOUT_TO_BE_FREED);
6415 for (chunk = chunks_queued_for_free_; chunk != NULL; chunk = next) { 6493 for (chunk = chunks_queued_for_free_; chunk != NULL; chunk = next) {
6416 next = chunk->next_chunk(); 6494 next = chunk->next_chunk();
6417 isolate_->memory_allocator()->Free(chunk); 6495 isolate_->memory_allocator()->Free(chunk);
6418 } 6496 }
6419 chunks_queued_for_free_ = NULL; 6497 chunks_queued_for_free_ = NULL;
6420 } 6498 }
6421 6499
6422 } } // namespace v8::internal 6500 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698