OLD | NEW |
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/heap/heap.h" | 5 #include "src/heap/heap.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/ast/scopeinfo.h" | 9 #include "src/ast/scopeinfo.h" |
10 #include "src/base/bits.h" | 10 #include "src/base/bits.h" |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
61 : AllocationObserver(step_size), heap_(heap) {} | 61 : AllocationObserver(step_size), heap_(heap) {} |
62 | 62 |
63 void Step(int bytes_allocated, Address, size_t) override { | 63 void Step(int bytes_allocated, Address, size_t) override { |
64 heap_.ScheduleIdleScavengeIfNeeded(bytes_allocated); | 64 heap_.ScheduleIdleScavengeIfNeeded(bytes_allocated); |
65 } | 65 } |
66 | 66 |
67 private: | 67 private: |
68 Heap& heap_; | 68 Heap& heap_; |
69 }; | 69 }; |
70 | 70 |
71 | |
72 Heap::Heap() | 71 Heap::Heap() |
73 : amount_of_external_allocated_memory_(0), | 72 : amount_of_external_allocated_memory_(0), |
74 amount_of_external_allocated_memory_at_last_global_gc_(0), | 73 amount_of_external_allocated_memory_at_last_global_gc_(0), |
75 isolate_(NULL), | 74 isolate_(NULL), |
76 code_range_size_(0), | 75 code_range_size_(0), |
77 // semispace_size_ should be a power of 2 and old_generation_size_ should | 76 // semispace_size_ should be a power of 2 and old_generation_size_ should |
78 // be a multiple of Page::kPageSize. | 77 // be a multiple of Page::kPageSize. |
79 reserved_semispace_size_(8 * (kPointerSize / 4) * MB), | 78 reserved_semispace_size_(8 * (kPointerSize / 4) * MB), |
80 max_semi_space_size_(8 * (kPointerSize / 4) * MB), | 79 max_semi_space_size_(8 * (kPointerSize / 4) * MB), |
81 initial_semispace_size_(Page::kPageSize), | 80 initial_semispace_size_(Page::kPageSize), |
82 max_old_generation_size_(700ul * (kPointerSize / 4) * MB), | 81 max_old_generation_size_(700ul * (kPointerSize / 4) * MB), |
83 initial_old_generation_size_(max_old_generation_size_ / | 82 initial_old_generation_size_(max_old_generation_size_ / |
84 kInitalOldGenerationLimitFactor), | 83 kInitalOldGenerationLimitFactor), |
85 old_generation_size_configured_(false), | 84 old_generation_size_configured_(false), |
86 max_executable_size_(256ul * (kPointerSize / 4) * MB), | 85 max_executable_size_(256ul * (kPointerSize / 4) * MB), |
87 // Variables set based on semispace_size_ and old_generation_size_ in | 86 // Variables set based on semispace_size_ and old_generation_size_ in |
88 // ConfigureHeap. | 87 // ConfigureHeap. |
89 // Will be 4 * reserved_semispace_size_ to ensure that young | 88 // Will be 4 * reserved_semispace_size_ to ensure that young |
90 // generation can be aligned to its size. | 89 // generation can be aligned to its size. |
91 maximum_committed_(0), | 90 maximum_committed_(0), |
92 survived_since_last_expansion_(0), | 91 survived_since_last_expansion_(0), |
93 survived_last_scavenge_(0), | 92 survived_last_scavenge_(0), |
94 always_allocate_scope_count_(0), | 93 always_allocate_scope_count_(0), |
| 94 memory_pressure_level_(MemoryPressureLevel::kNone), |
95 contexts_disposed_(0), | 95 contexts_disposed_(0), |
96 number_of_disposed_maps_(0), | 96 number_of_disposed_maps_(0), |
97 global_ic_age_(0), | 97 global_ic_age_(0), |
98 new_space_(this), | 98 new_space_(this), |
99 old_space_(NULL), | 99 old_space_(NULL), |
100 code_space_(NULL), | 100 code_space_(NULL), |
101 map_space_(NULL), | 101 map_space_(NULL), |
102 lo_space_(NULL), | 102 lo_space_(NULL), |
103 gc_state_(NOT_IN_GC), | 103 gc_state_(NOT_IN_GC), |
104 gc_post_processing_depth_(0), | 104 gc_post_processing_depth_(0), |
(...skipping 678 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
783 ~GCCallbacksScope() { heap_->gc_callbacks_depth_--; } | 783 ~GCCallbacksScope() { heap_->gc_callbacks_depth_--; } |
784 | 784 |
785 bool CheckReenter() { return heap_->gc_callbacks_depth_ == 1; } | 785 bool CheckReenter() { return heap_->gc_callbacks_depth_ == 1; } |
786 | 786 |
787 private: | 787 private: |
788 Heap* heap_; | 788 Heap* heap_; |
789 }; | 789 }; |
790 | 790 |
791 | 791 |
792 void Heap::HandleGCRequest() { | 792 void Heap::HandleGCRequest() { |
793 if (incremental_marking()->request_type() == | 793 if (HighMemoryPressure()) { |
794 IncrementalMarking::COMPLETE_MARKING) { | 794 incremental_marking()->reset_request_type(); |
| 795 CheckMemoryPressure(); |
| 796 } else if (incremental_marking()->request_type() == |
| 797 IncrementalMarking::COMPLETE_MARKING) { |
| 798 incremental_marking()->reset_request_type(); |
795 CollectAllGarbage(current_gc_flags_, "GC interrupt", | 799 CollectAllGarbage(current_gc_flags_, "GC interrupt", |
796 current_gc_callback_flags_); | 800 current_gc_callback_flags_); |
797 } else if (incremental_marking()->IsMarking() && | 801 } else if (incremental_marking()->request_type() == |
| 802 IncrementalMarking::FINALIZATION && |
| 803 incremental_marking()->IsMarking() && |
798 !incremental_marking()->finalize_marking_completed()) { | 804 !incremental_marking()->finalize_marking_completed()) { |
| 805 incremental_marking()->reset_request_type(); |
799 FinalizeIncrementalMarking("GC interrupt: finalize incremental marking"); | 806 FinalizeIncrementalMarking("GC interrupt: finalize incremental marking"); |
800 } | 807 } |
801 } | 808 } |
802 | 809 |
803 | 810 |
804 void Heap::ScheduleIdleScavengeIfNeeded(int bytes_allocated) { | 811 void Heap::ScheduleIdleScavengeIfNeeded(int bytes_allocated) { |
805 scavenge_job_->ScheduleIdleTaskIfNeeded(this, bytes_allocated); | 812 scavenge_job_->ScheduleIdleTaskIfNeeded(this, bytes_allocated); |
806 } | 813 } |
807 | 814 |
808 | 815 |
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1029 // - this GC decreased committed memory, | 1036 // - this GC decreased committed memory, |
1030 // - there is high fragmentation, | 1037 // - there is high fragmentation, |
1031 // - there are live detached contexts. | 1038 // - there are live detached contexts. |
1032 event.next_gc_likely_to_collect_more = | 1039 event.next_gc_likely_to_collect_more = |
1033 (committed_memory_before - committed_memory_after) > MB || | 1040 (committed_memory_before - committed_memory_after) > MB || |
1034 HasHighFragmentation(used_memory_after, committed_memory_after) || | 1041 HasHighFragmentation(used_memory_after, committed_memory_after) || |
1035 (detached_contexts()->length() > 0); | 1042 (detached_contexts()->length() > 0); |
1036 if (deserialization_complete_) { | 1043 if (deserialization_complete_) { |
1037 memory_reducer_->NotifyMarkCompact(event); | 1044 memory_reducer_->NotifyMarkCompact(event); |
1038 } | 1045 } |
| 1046 memory_pressure_level_.SetValue(MemoryPressureLevel::kNone); |
1039 } | 1047 } |
1040 | 1048 |
1041 tracer()->Stop(collector); | 1049 tracer()->Stop(collector); |
1042 } | 1050 } |
1043 | 1051 |
1044 if (collector == MARK_COMPACTOR && | 1052 if (collector == MARK_COMPACTOR && |
1045 (gc_callback_flags & (kGCCallbackFlagForced | | 1053 (gc_callback_flags & (kGCCallbackFlagForced | |
1046 kGCCallbackFlagCollectAllAvailableGarbage)) != 0) { | 1054 kGCCallbackFlagCollectAllAvailableGarbage)) != 0) { |
1047 isolate()->CountUsage(v8::Isolate::kForcedGC); | 1055 isolate()->CountUsage(v8::Isolate::kForcedGC); |
1048 } | 1056 } |
(...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1448 | 1456 |
1449 | 1457 |
1450 void Heap::MarkCompactEpilogue() { | 1458 void Heap::MarkCompactEpilogue() { |
1451 gc_state_ = NOT_IN_GC; | 1459 gc_state_ = NOT_IN_GC; |
1452 | 1460 |
1453 isolate_->counters()->objs_since_last_full()->Set(0); | 1461 isolate_->counters()->objs_since_last_full()->Set(0); |
1454 | 1462 |
1455 incremental_marking()->Epilogue(); | 1463 incremental_marking()->Epilogue(); |
1456 | 1464 |
1457 PreprocessStackTraces(); | 1465 PreprocessStackTraces(); |
1458 | |
1459 DCHECK(incremental_marking()->IsStopped()); | 1466 DCHECK(incremental_marking()->IsStopped()); |
1460 | 1467 |
1461 // We finished a marking cycle. We can uncommit the marking deque until | 1468 // We finished a marking cycle. We can uncommit the marking deque until |
1462 // we start marking again. | 1469 // we start marking again. |
1463 mark_compact_collector()->marking_deque()->Uninitialize(); | 1470 mark_compact_collector()->marking_deque()->Uninitialize(); |
1464 mark_compact_collector()->EnsureMarkingDequeIsCommitted( | 1471 mark_compact_collector()->EnsureMarkingDequeIsCommitted( |
1465 MarkCompactCollector::kMinMarkingDequeSize); | 1472 MarkCompactCollector::kMinMarkingDequeSize); |
1466 } | 1473 } |
1467 | 1474 |
1468 | 1475 |
(...skipping 2947 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4416 return result; | 4423 return result; |
4417 } | 4424 } |
4418 | 4425 |
4419 | 4426 |
4420 bool Heap::RecentIdleNotificationHappened() { | 4427 bool Heap::RecentIdleNotificationHappened() { |
4421 return (last_idle_notification_time_ + | 4428 return (last_idle_notification_time_ + |
4422 GCIdleTimeHandler::kMaxScheduledIdleTime) > | 4429 GCIdleTimeHandler::kMaxScheduledIdleTime) > |
4423 MonotonicallyIncreasingTimeInMs(); | 4430 MonotonicallyIncreasingTimeInMs(); |
4424 } | 4431 } |
4425 | 4432 |
| 4433 class MemoryPressureInterruptTask : public CancelableTask { |
| 4434 public: |
| 4435 explicit MemoryPressureInterruptTask(Heap* heap) |
| 4436 : CancelableTask(heap->isolate()), heap_(heap) {} |
| 4437 |
| 4438 virtual ~MemoryPressureInterruptTask() {} |
| 4439 |
| 4440 private: |
| 4441 // v8::internal::CancelableTask overrides. |
| 4442 void RunInternal() override { heap_->CheckMemoryPressure(); } |
| 4443 |
| 4444 Heap* heap_; |
| 4445 DISALLOW_COPY_AND_ASSIGN(MemoryPressureInterruptTask); |
| 4446 }; |
| 4447 |
| 4448 void Heap::CheckMemoryPressure() { |
| 4449 if (memory_pressure_level_.Value() == MemoryPressureLevel::kCritical) { |
| 4450 CollectGarbageOnMemoryPressure("memory pressure"); |
| 4451 } else if (memory_pressure_level_.Value() == MemoryPressureLevel::kModerate) { |
| 4452 if (FLAG_incremental_marking && incremental_marking()->IsStopped()) { |
| 4453 StartIdleIncrementalMarking(); |
| 4454 } |
| 4455 } |
| 4456 MemoryReducer::Event event; |
| 4457 event.type = MemoryReducer::kPossibleGarbage; |
| 4458 event.time_ms = MonotonicallyIncreasingTimeInMs(); |
| 4459 memory_reducer_->NotifyPossibleGarbage(event); |
| 4460 } |
| 4461 |
| 4462 void Heap::CollectGarbageOnMemoryPressure(const char* source) { |
| 4463 CollectAllGarbage(kReduceMemoryFootprintMask | kAbortIncrementalMarkingMask, |
| 4464 source); |
| 4465 } |
| 4466 |
| 4467 void Heap::MemoryPressureNotification(MemoryPressureLevel level, |
| 4468 bool is_isolate_locked) { |
| 4469 MemoryPressureLevel previous = memory_pressure_level_.Value(); |
| 4470 memory_pressure_level_.SetValue(level); |
| 4471 if ((previous != MemoryPressureLevel::kCritical && |
| 4472 level == MemoryPressureLevel::kCritical) || |
| 4473 (previous == MemoryPressureLevel::kNone && |
| 4474 level == MemoryPressureLevel::kModerate)) { |
| 4475 if (is_isolate_locked) { |
| 4476 CheckMemoryPressure(); |
| 4477 } else { |
| 4478 ExecutionAccess access(isolate()); |
| 4479 isolate()->stack_guard()->RequestGC(); |
| 4480 V8::GetCurrentPlatform()->CallOnForegroundThread( |
| 4481 reinterpret_cast<v8::Isolate*>(isolate()), |
| 4482 new MemoryPressureInterruptTask(this)); |
| 4483 } |
| 4484 } |
| 4485 } |
4426 | 4486 |
4427 #ifdef DEBUG | 4487 #ifdef DEBUG |
4428 | 4488 |
4429 void Heap::Print() { | 4489 void Heap::Print() { |
4430 if (!HasBeenSetUp()) return; | 4490 if (!HasBeenSetUp()) return; |
4431 isolate()->PrintStack(stdout); | 4491 isolate()->PrintStack(stdout); |
4432 AllSpaces spaces(this); | 4492 AllSpaces spaces(this); |
4433 for (Space* space = spaces.next(); space != NULL; space = spaces.next()) { | 4493 for (Space* space = spaces.next(); space != NULL; space = spaces.next()) { |
4434 space->Print(); | 4494 space->Print(); |
4435 } | 4495 } |
(...skipping 1977 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6413 } | 6473 } |
6414 | 6474 |
6415 | 6475 |
6416 // static | 6476 // static |
6417 int Heap::GetStaticVisitorIdForMap(Map* map) { | 6477 int Heap::GetStaticVisitorIdForMap(Map* map) { |
6418 return StaticVisitorBase::GetVisitorId(map); | 6478 return StaticVisitorBase::GetVisitorId(map); |
6419 } | 6479 } |
6420 | 6480 |
6421 } // namespace internal | 6481 } // namespace internal |
6422 } // namespace v8 | 6482 } // namespace v8 |
OLD | NEW |