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

Side by Side Diff: src/heap/heap.cc

Issue 492763002: Move idle notification handling to GCIdleTimeHandler. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Casts Created 6 years, 4 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/heap.h ('k') | test/heap-unittests/heap-unittest.cc » ('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 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/v8.h" 5 #include "src/v8.h"
6 6
7 #include "src/accessors.h" 7 #include "src/accessors.h"
8 #include "src/api.h" 8 #include "src/api.h"
9 #include "src/base/once.h" 9 #include "src/base/once.h"
10 #include "src/base/utils/random-number-generator.h" 10 #include "src/base/utils/random-number-generator.h"
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
113 max_gc_pause_(0.0), 113 max_gc_pause_(0.0),
114 total_gc_time_ms_(0.0), 114 total_gc_time_ms_(0.0),
115 max_alive_after_gc_(0), 115 max_alive_after_gc_(0),
116 min_in_mutator_(kMaxInt), 116 min_in_mutator_(kMaxInt),
117 marking_time_(0.0), 117 marking_time_(0.0),
118 sweeping_time_(0.0), 118 sweeping_time_(0.0),
119 mark_compact_collector_(this), 119 mark_compact_collector_(this),
120 store_buffer_(this), 120 store_buffer_(this),
121 marking_(this), 121 marking_(this),
122 incremental_marking_(this), 122 incremental_marking_(this),
123 number_idle_notifications_(0),
124 last_idle_notification_gc_count_(0),
125 last_idle_notification_gc_count_init_(false),
126 mark_sweeps_since_idle_round_started_(0),
127 gc_count_at_last_idle_gc_(0), 123 gc_count_at_last_idle_gc_(0),
128 scavenges_since_last_idle_round_(kIdleScavengeThreshold),
129 full_codegen_bytes_generated_(0), 124 full_codegen_bytes_generated_(0),
130 crankshaft_codegen_bytes_generated_(0), 125 crankshaft_codegen_bytes_generated_(0),
131 gcs_since_last_deopt_(0), 126 gcs_since_last_deopt_(0),
132 #ifdef VERIFY_HEAP 127 #ifdef VERIFY_HEAP
133 no_weak_object_verification_scope_depth_(0), 128 no_weak_object_verification_scope_depth_(0),
134 #endif 129 #endif
135 allocation_sites_scratchpad_length_(0), 130 allocation_sites_scratchpad_length_(0),
136 promotion_queue_(this), 131 promotion_queue_(this),
137 configured_(false), 132 configured_(false),
138 external_string_table_(this), 133 external_string_table_(this),
(...skipping 1413 matching lines...) Expand 10 before | Expand all | Expand 10 after
1552 new_space_.inline_allocation_limit_step()); 1547 new_space_.inline_allocation_limit_step());
1553 1548
1554 // Update how much has survived scavenge. 1549 // Update how much has survived scavenge.
1555 IncrementYoungSurvivorsCounter(static_cast<int>( 1550 IncrementYoungSurvivorsCounter(static_cast<int>(
1556 (PromotedSpaceSizeOfObjects() - survived_watermark) + new_space_.Size())); 1551 (PromotedSpaceSizeOfObjects() - survived_watermark) + new_space_.Size()));
1557 1552
1558 LOG(isolate_, ResourceEvent("scavenge", "end")); 1553 LOG(isolate_, ResourceEvent("scavenge", "end"));
1559 1554
1560 gc_state_ = NOT_IN_GC; 1555 gc_state_ = NOT_IN_GC;
1561 1556
1562 scavenges_since_last_idle_round_++; 1557 gc_idle_time_handler_.NotifyScavenge();
1563 } 1558 }
1564 1559
1565 1560
1566 String* Heap::UpdateNewSpaceReferenceInExternalStringTableEntry(Heap* heap, 1561 String* Heap::UpdateNewSpaceReferenceInExternalStringTableEntry(Heap* heap,
1567 Object** p) { 1562 Object** p) {
1568 MapWord first_word = HeapObject::cast(*p)->map_word(); 1563 MapWord first_word = HeapObject::cast(*p)->map_word();
1569 1564
1570 if (!first_word.IsForwardingAddress()) { 1565 if (!first_word.IsForwardingAddress()) {
1571 // Unreachable external string can be finalized. 1566 // Unreachable external string can be finalized.
1572 heap->FinalizeExternalString(String::cast(*p)); 1567 heap->FinalizeExternalString(String::cast(*p));
(...skipping 2684 matching lines...) Expand 10 before | Expand all | Expand 10 after
4257 if (!IsHeapIterable()) { 4252 if (!IsHeapIterable()) {
4258 CollectAllGarbage(kMakeHeapIterableMask, "Heap::MakeHeapIterable"); 4253 CollectAllGarbage(kMakeHeapIterableMask, "Heap::MakeHeapIterable");
4259 } 4254 }
4260 if (mark_compact_collector()->sweeping_in_progress()) { 4255 if (mark_compact_collector()->sweeping_in_progress()) {
4261 mark_compact_collector()->EnsureSweepingCompleted(); 4256 mark_compact_collector()->EnsureSweepingCompleted();
4262 } 4257 }
4263 DCHECK(IsHeapIterable()); 4258 DCHECK(IsHeapIterable());
4264 } 4259 }
4265 4260
4266 4261
4267 void Heap::AdvanceIdleIncrementalMarking(int idle_time_in_ms) { 4262 void Heap::AdvanceIdleIncrementalMarking(intptr_t step_size) {
4268 intptr_t step_size =
4269 static_cast<size_t>(GCIdleTimeHandler::EstimateMarkingStepSize(
4270 idle_time_in_ms,
4271 tracer_.IncrementalMarkingSpeedInBytesPerMillisecond()));
4272
4273 incremental_marking()->Step(step_size, 4263 incremental_marking()->Step(step_size,
4274 IncrementalMarking::NO_GC_VIA_STACK_GUARD, true); 4264 IncrementalMarking::NO_GC_VIA_STACK_GUARD, true);
4275 4265
4276 if (incremental_marking()->IsComplete()) { 4266 if (incremental_marking()->IsComplete()) {
4277 bool uncommit = false; 4267 bool uncommit = false;
4278 if (gc_count_at_last_idle_gc_ == gc_count_) { 4268 if (gc_count_at_last_idle_gc_ == gc_count_) {
4279 // No GC since the last full GC, the mutator is probably not active. 4269 // No GC since the last full GC, the mutator is probably not active.
4280 isolate_->compilation_cache()->Clear(); 4270 isolate_->compilation_cache()->Clear();
4281 uncommit = true; 4271 uncommit = true;
4282 } 4272 }
4283 CollectAllGarbage(kReduceMemoryFootprintMask, 4273 CollectAllGarbage(kReduceMemoryFootprintMask,
4284 "idle notification: finalize incremental"); 4274 "idle notification: finalize incremental");
4285 mark_sweeps_since_idle_round_started_++; 4275 gc_idle_time_handler_.NotifyIdleMarkCompact();
4286 gc_count_at_last_idle_gc_ = gc_count_; 4276 gc_count_at_last_idle_gc_ = gc_count_;
4287 if (uncommit) { 4277 if (uncommit) {
4288 new_space_.Shrink(); 4278 new_space_.Shrink();
4289 UncommitFromSpace(); 4279 UncommitFromSpace();
4290 } 4280 }
4291 } 4281 }
4292 } 4282 }
4293 4283
4294 4284
4295 bool Heap::IdleNotification(int idle_time_in_ms) { 4285 bool Heap::IdleNotification(int idle_time_in_ms) {
4296 // If incremental marking is off, we do not perform idle notification. 4286 // If incremental marking is off, we do not perform idle notification.
4297 if (!FLAG_incremental_marking) return true; 4287 if (!FLAG_incremental_marking) return true;
4298
4299 // Minimal hint that allows to do full GC.
4300 const int kMinHintForFullGC = 100;
4301 isolate()->counters()->gc_idle_time_allotted_in_ms()->AddSample( 4288 isolate()->counters()->gc_idle_time_allotted_in_ms()->AddSample(
4302 idle_time_in_ms); 4289 idle_time_in_ms);
4303 HistogramTimerScope idle_notification_scope( 4290 HistogramTimerScope idle_notification_scope(
4304 isolate_->counters()->gc_idle_notification()); 4291 isolate_->counters()->gc_idle_notification());
4305 4292
4306 if (contexts_disposed_ > 0) { 4293 GCIdleTimeAction action = gc_idle_time_handler_.Compute(
4307 contexts_disposed_ = 0; 4294 idle_time_in_ms, contexts_disposed_, static_cast<size_t>(SizeOfObjects()),
4308 int mark_sweep_time = Min(TimeMarkSweepWouldTakeInMs(), 1000); 4295 incremental_marking()->IsStopped(), tracer());
4309 if (idle_time_in_ms >= mark_sweep_time && !FLAG_expose_gc && 4296 contexts_disposed_ = 0;
4310 incremental_marking()->IsStopped()) { 4297 bool result = false;
4298 switch (action.type) {
4299 case DO_INCREMENTAL_MARKING:
4300 if (incremental_marking()->IsStopped()) {
4301 incremental_marking()->Start();
4302 }
4303 AdvanceIdleIncrementalMarking(action.parameter);
4304 break;
4305 case DO_FULL_GC: {
4311 HistogramTimerScope scope(isolate_->counters()->gc_context()); 4306 HistogramTimerScope scope(isolate_->counters()->gc_context());
4312 CollectAllGarbage(kReduceMemoryFootprintMask, 4307 const char* message = contexts_disposed_
4313 "idle notification: contexts disposed"); 4308 ? "idle notification: contexts disposed"
4314 } else { 4309 : "idle notification: finalize idle round";
4315 AdvanceIdleIncrementalMarking(idle_time_in_ms); 4310 CollectAllGarbage(kReduceMemoryFootprintMask, message);
4311 gc_idle_time_handler_.NotifyIdleMarkCompact();
4312 break;
4316 } 4313 }
4317 4314 case DO_SCAVENGE:
4318 // After context disposal there is likely a lot of garbage remaining, reset 4315 CollectGarbage(NEW_SPACE, "idle notification: scavenge");
4319 // the idle notification counters in order to trigger more incremental GCs 4316 break;
4320 // on subsequent idle notifications. 4317 case DO_NOTHING:
4321 StartIdleRound(); 4318 result = true;
4322 return false; 4319 break;
4323 } 4320 }
4324
4325 // By doing small chunks of GC work in each IdleNotification,
4326 // perform a round of incremental GCs and after that wait until
4327 // the mutator creates enough garbage to justify a new round.
4328 // An incremental GC progresses as follows:
4329 // 1. many incremental marking steps,
4330 // 2. one old space mark-sweep-compact,
4331 // Use mark-sweep-compact events to count incremental GCs in a round.
4332
4333 if (mark_sweeps_since_idle_round_started_ >= kMaxMarkSweepsInIdleRound) {
4334 if (EnoughGarbageSinceLastIdleRound()) {
4335 StartIdleRound();
4336 } else {
4337 return true;
4338 }
4339 }
4340
4341 int remaining_mark_sweeps =
4342 kMaxMarkSweepsInIdleRound - mark_sweeps_since_idle_round_started_;
4343
4344 if (incremental_marking()->IsStopped()) {
4345 // If there are no more than two GCs left in this idle round and we are
4346 // allowed to do a full GC, then make those GCs full in order to compact
4347 // the code space.
4348 // TODO(ulan): Once we enable code compaction for incremental marking,
4349 // we can get rid of this special case and always start incremental marking.
4350 if (remaining_mark_sweeps <= 2 && idle_time_in_ms >= kMinHintForFullGC) {
4351 CollectAllGarbage(kReduceMemoryFootprintMask,
4352 "idle notification: finalize idle round");
4353 mark_sweeps_since_idle_round_started_++;
4354 } else {
4355 incremental_marking()->Start();
4356 }
4357 }
4358 if (!incremental_marking()->IsStopped()) {
4359 AdvanceIdleIncrementalMarking(idle_time_in_ms);
4360 }
4361
4362 if (mark_sweeps_since_idle_round_started_ >= kMaxMarkSweepsInIdleRound) {
4363 FinishIdleRound();
4364 return true;
4365 }
4366
4367 // If the IdleNotifcation is called with a large hint we will wait for 4321 // If the IdleNotifcation is called with a large hint we will wait for
4368 // the sweepter threads here. 4322 // the sweepter threads here.
4323 // TODO(ulan): move this in GCIdleTimeHandler.
4324 const int kMinHintForFullGC = 100;
4369 if (idle_time_in_ms >= kMinHintForFullGC && 4325 if (idle_time_in_ms >= kMinHintForFullGC &&
4370 mark_compact_collector()->sweeping_in_progress()) { 4326 mark_compact_collector()->sweeping_in_progress()) {
4371 mark_compact_collector()->EnsureSweepingCompleted(); 4327 mark_compact_collector()->EnsureSweepingCompleted();
4372 } 4328 }
4373 4329
4374 return false; 4330 return result;
4375 } 4331 }
4376 4332
4377 4333
4378 #ifdef DEBUG 4334 #ifdef DEBUG
4379 4335
4380 void Heap::Print() { 4336 void Heap::Print() {
4381 if (!HasBeenSetUp()) return; 4337 if (!HasBeenSetUp()) return;
4382 isolate()->PrintStack(stdout); 4338 isolate()->PrintStack(stdout);
4383 AllSpaces spaces(this); 4339 AllSpaces spaces(this);
4384 for (Space* space = spaces.next(); space != NULL; space = spaces.next()) { 4340 for (Space* space = spaces.next(); space != NULL; space = spaces.next()) {
(...skipping 1758 matching lines...) Expand 10 before | Expand all | Expand 10 after
6143 static_cast<int>(object_sizes_last_time_[index])); 6099 static_cast<int>(object_sizes_last_time_[index]));
6144 CODE_AGE_LIST_COMPLETE(ADJUST_LAST_TIME_OBJECT_COUNT) 6100 CODE_AGE_LIST_COMPLETE(ADJUST_LAST_TIME_OBJECT_COUNT)
6145 #undef ADJUST_LAST_TIME_OBJECT_COUNT 6101 #undef ADJUST_LAST_TIME_OBJECT_COUNT
6146 6102
6147 MemCopy(object_counts_last_time_, object_counts_, sizeof(object_counts_)); 6103 MemCopy(object_counts_last_time_, object_counts_, sizeof(object_counts_));
6148 MemCopy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_)); 6104 MemCopy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_));
6149 ClearObjectStats(); 6105 ClearObjectStats();
6150 } 6106 }
6151 } 6107 }
6152 } // namespace v8::internal 6108 } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/heap/heap.h ('k') | test/heap-unittests/heap-unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698