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/context-slot-cache.h" | 9 #include "src/ast/context-slot-cache.h" |
10 #include "src/base/bits.h" | 10 #include "src/base/bits.h" |
11 #include "src/base/once.h" | 11 #include "src/base/once.h" |
12 #include "src/base/utils/random-number-generator.h" | 12 #include "src/base/utils/random-number-generator.h" |
13 #include "src/bootstrapper.h" | 13 #include "src/bootstrapper.h" |
14 #include "src/codegen.h" | 14 #include "src/codegen.h" |
15 #include "src/compilation-cache.h" | 15 #include "src/compilation-cache.h" |
16 #include "src/compiler-dispatcher/optimizing-compile-dispatcher.h" | 16 #include "src/compiler-dispatcher/optimizing-compile-dispatcher.h" |
17 #include "src/conversions.h" | 17 #include "src/conversions.h" |
18 #include "src/debug/debug.h" | 18 #include "src/debug/debug.h" |
19 #include "src/deoptimizer.h" | 19 #include "src/deoptimizer.h" |
20 #include "src/global-handles.h" | 20 #include "src/global-handles.h" |
21 #include "src/heap/array-buffer-tracker-inl.h" | 21 #include "src/heap/array-buffer-tracker-inl.h" |
22 #include "src/heap/code-stats.h" | 22 #include "src/heap/code-stats.h" |
| 23 #include "src/heap/embedder-tracing.h" |
23 #include "src/heap/gc-idle-time-handler.h" | 24 #include "src/heap/gc-idle-time-handler.h" |
24 #include "src/heap/gc-tracer.h" | 25 #include "src/heap/gc-tracer.h" |
25 #include "src/heap/incremental-marking.h" | 26 #include "src/heap/incremental-marking.h" |
26 #include "src/heap/mark-compact-inl.h" | 27 #include "src/heap/mark-compact-inl.h" |
27 #include "src/heap/mark-compact.h" | 28 #include "src/heap/mark-compact.h" |
28 #include "src/heap/memory-reducer.h" | 29 #include "src/heap/memory-reducer.h" |
29 #include "src/heap/object-stats.h" | 30 #include "src/heap/object-stats.h" |
30 #include "src/heap/objects-visiting-inl.h" | 31 #include "src/heap/objects-visiting-inl.h" |
31 #include "src/heap/objects-visiting.h" | 32 #include "src/heap/objects-visiting.h" |
32 #include "src/heap/remembered-set.h" | 33 #include "src/heap/remembered-set.h" |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
148 ring_buffer_end_(0), | 149 ring_buffer_end_(0), |
149 promotion_queue_(this), | 150 promotion_queue_(this), |
150 configured_(false), | 151 configured_(false), |
151 current_gc_flags_(Heap::kNoGCFlags), | 152 current_gc_flags_(Heap::kNoGCFlags), |
152 current_gc_callback_flags_(GCCallbackFlags::kNoGCCallbackFlags), | 153 current_gc_callback_flags_(GCCallbackFlags::kNoGCCallbackFlags), |
153 external_string_table_(this), | 154 external_string_table_(this), |
154 gc_callbacks_depth_(0), | 155 gc_callbacks_depth_(0), |
155 deserialization_complete_(false), | 156 deserialization_complete_(false), |
156 strong_roots_list_(NULL), | 157 strong_roots_list_(NULL), |
157 heap_iterator_depth_(0), | 158 heap_iterator_depth_(0), |
158 embedder_heap_tracer_(nullptr), | 159 local_embedder_heap_tracer_(nullptr), |
159 force_oom_(false), | 160 force_oom_(false), |
160 delay_sweeper_tasks_for_testing_(false) { | 161 delay_sweeper_tasks_for_testing_(false) { |
161 // Allow build-time customization of the max semispace size. Building | 162 // Allow build-time customization of the max semispace size. Building |
162 // V8 with snapshots and a non-default max semispace size is much | 163 // V8 with snapshots and a non-default max semispace size is much |
163 // easier if you can define it as part of the build environment. | 164 // easier if you can define it as part of the build environment. |
164 #if defined(V8_MAX_SEMISPACE_SIZE) | 165 #if defined(V8_MAX_SEMISPACE_SIZE) |
165 max_semi_space_size_ = reserved_semispace_size_ = V8_MAX_SEMISPACE_SIZE; | 166 max_semi_space_size_ = reserved_semispace_size_ = V8_MAX_SEMISPACE_SIZE; |
166 #endif | 167 #endif |
167 | 168 |
168 // Ensure old_generation_size_ is a multiple of kPageSize. | 169 // Ensure old_generation_size_ is a multiple of kPageSize. |
(...skipping 1432 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1601 SetGCState(SCAVENGE); | 1602 SetGCState(SCAVENGE); |
1602 | 1603 |
1603 // Implements Cheney's copying algorithm | 1604 // Implements Cheney's copying algorithm |
1604 LOG(isolate_, ResourceEvent("scavenge", "begin")); | 1605 LOG(isolate_, ResourceEvent("scavenge", "begin")); |
1605 | 1606 |
1606 // Used for updating survived_since_last_expansion_ at function end. | 1607 // Used for updating survived_since_last_expansion_ at function end. |
1607 size_t survived_watermark = PromotedSpaceSizeOfObjects(); | 1608 size_t survived_watermark = PromotedSpaceSizeOfObjects(); |
1608 | 1609 |
1609 scavenge_collector_->SelectScavengingVisitorsTable(); | 1610 scavenge_collector_->SelectScavengingVisitorsTable(); |
1610 | 1611 |
1611 if (UsingEmbedderHeapTracer()) { | 1612 local_embedder_heap_tracer()->RegisterWrappersWithRemoteTracer(); |
1612 // Register found wrappers with embedder so it can add them to its marking | |
1613 // deque and correctly manage the case when v8 scavenger collects the | |
1614 // wrappers by either keeping wrappables alive, or cleaning marking deque. | |
1615 RegisterWrappersWithEmbedderHeapTracer(); | |
1616 } | |
1617 | 1613 |
1618 // Flip the semispaces. After flipping, to space is empty, from space has | 1614 // Flip the semispaces. After flipping, to space is empty, from space has |
1619 // live objects. | 1615 // live objects. |
1620 new_space_->Flip(); | 1616 new_space_->Flip(); |
1621 new_space_->ResetAllocationInfo(); | 1617 new_space_->ResetAllocationInfo(); |
1622 | 1618 |
1623 // We need to sweep newly copied objects which can be either in the | 1619 // We need to sweep newly copied objects which can be either in the |
1624 // to space or promoted to the old generation. For to-space | 1620 // to space or promoted to the old generation. For to-space |
1625 // objects, we treat the bottom of the to space as a queue. Newly | 1621 // objects, we treat the bottom of the to space as a queue. Newly |
1626 // copied and unswept objects lie between a 'front' mark and the | 1622 // copied and unswept objects lie between a 'front' mark and the |
(...skipping 2548 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4175 if (ShouldReduceMemory() || | 4171 if (ShouldReduceMemory() || |
4176 ((allocation_throughput != 0) && | 4172 ((allocation_throughput != 0) && |
4177 (allocation_throughput < kLowAllocationThroughput))) { | 4173 (allocation_throughput < kLowAllocationThroughput))) { |
4178 new_space_->Shrink(); | 4174 new_space_->Shrink(); |
4179 UncommitFromSpace(); | 4175 UncommitFromSpace(); |
4180 } | 4176 } |
4181 } | 4177 } |
4182 | 4178 |
4183 bool Heap::MarkingDequesAreEmpty() { | 4179 bool Heap::MarkingDequesAreEmpty() { |
4184 return mark_compact_collector()->marking_deque()->IsEmpty() && | 4180 return mark_compact_collector()->marking_deque()->IsEmpty() && |
4185 (!UsingEmbedderHeapTracer() || | 4181 local_embedder_heap_tracer()->NumberOfWrappersToTrace() == 0; |
4186 (wrappers_to_trace() == 0 && | |
4187 embedder_heap_tracer()->NumberOfWrappersToTrace() == 0)); | |
4188 } | 4182 } |
4189 | 4183 |
4190 void Heap::FinalizeIncrementalMarkingIfComplete( | 4184 void Heap::FinalizeIncrementalMarkingIfComplete( |
4191 GarbageCollectionReason gc_reason) { | 4185 GarbageCollectionReason gc_reason) { |
4192 if (incremental_marking()->IsMarking() && | 4186 if (incremental_marking()->IsMarking() && |
4193 (incremental_marking()->IsReadyToOverApproximateWeakClosure() || | 4187 (incremental_marking()->IsReadyToOverApproximateWeakClosure() || |
4194 (!incremental_marking()->finalize_marking_completed() && | 4188 (!incremental_marking()->finalize_marking_completed() && |
4195 MarkingDequesAreEmpty()))) { | 4189 MarkingDequesAreEmpty()))) { |
4196 FinalizeIncrementalMarking(gc_reason); | 4190 FinalizeIncrementalMarking(gc_reason); |
4197 } else if (incremental_marking()->IsComplete() || MarkingDequesAreEmpty()) { | 4191 } else if (incremental_marking()->IsComplete() || MarkingDequesAreEmpty()) { |
(...skipping 1294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5492 tracer_ = new GCTracer(this); | 5486 tracer_ = new GCTracer(this); |
5493 scavenge_collector_ = new Scavenger(this); | 5487 scavenge_collector_ = new Scavenger(this); |
5494 mark_compact_collector_ = new MarkCompactCollector(this); | 5488 mark_compact_collector_ = new MarkCompactCollector(this); |
5495 gc_idle_time_handler_ = new GCIdleTimeHandler(); | 5489 gc_idle_time_handler_ = new GCIdleTimeHandler(); |
5496 memory_reducer_ = new MemoryReducer(this); | 5490 memory_reducer_ = new MemoryReducer(this); |
5497 if (V8_UNLIKELY(FLAG_gc_stats)) { | 5491 if (V8_UNLIKELY(FLAG_gc_stats)) { |
5498 live_object_stats_ = new ObjectStats(this); | 5492 live_object_stats_ = new ObjectStats(this); |
5499 dead_object_stats_ = new ObjectStats(this); | 5493 dead_object_stats_ = new ObjectStats(this); |
5500 } | 5494 } |
5501 scavenge_job_ = new ScavengeJob(); | 5495 scavenge_job_ = new ScavengeJob(); |
| 5496 local_embedder_heap_tracer_ = new LocalEmbedderHeapTracer(); |
5502 | 5497 |
5503 LOG(isolate_, IntPtrTEvent("heap-capacity", Capacity())); | 5498 LOG(isolate_, IntPtrTEvent("heap-capacity", Capacity())); |
5504 LOG(isolate_, IntPtrTEvent("heap-available", Available())); | 5499 LOG(isolate_, IntPtrTEvent("heap-available", Available())); |
5505 | 5500 |
5506 store_buffer()->SetUp(); | 5501 store_buffer()->SetUp(); |
5507 | 5502 |
5508 mark_compact_collector()->SetUp(); | 5503 mark_compact_collector()->SetUp(); |
5509 | 5504 |
5510 idle_scavenge_observer_ = new IdleScavengeObserver( | 5505 idle_scavenge_observer_ = new IdleScavengeObserver( |
5511 *this, ScavengeJob::kBytesAllocatedBeforeNextIdleTask); | 5506 *this, ScavengeJob::kBytesAllocatedBeforeNextIdleTask); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5567 CHECK(p->NeverEvacuate()); | 5562 CHECK(p->NeverEvacuate()); |
5568 } | 5563 } |
5569 #endif // DEBUG | 5564 #endif // DEBUG |
5570 } | 5565 } |
5571 | 5566 |
5572 deserialization_complete_ = true; | 5567 deserialization_complete_ = true; |
5573 } | 5568 } |
5574 | 5569 |
5575 void Heap::SetEmbedderHeapTracer(EmbedderHeapTracer* tracer) { | 5570 void Heap::SetEmbedderHeapTracer(EmbedderHeapTracer* tracer) { |
5576 DCHECK_EQ(gc_state_, HeapState::NOT_IN_GC); | 5571 DCHECK_EQ(gc_state_, HeapState::NOT_IN_GC); |
5577 embedder_heap_tracer_ = tracer; | 5572 local_embedder_heap_tracer()->SetRemoteTracer(tracer); |
5578 } | |
5579 | |
5580 void Heap::RegisterWrappersWithEmbedderHeapTracer() { | |
5581 DCHECK(UsingEmbedderHeapTracer()); | |
5582 if (wrappers_to_trace_.empty()) { | |
5583 return; | |
5584 } | |
5585 embedder_heap_tracer()->RegisterV8References(wrappers_to_trace_); | |
5586 wrappers_to_trace_.clear(); | |
5587 } | 5573 } |
5588 | 5574 |
5589 void Heap::TracePossibleWrapper(JSObject* js_object) { | 5575 void Heap::TracePossibleWrapper(JSObject* js_object) { |
5590 DCHECK(js_object->WasConstructedFromApiFunction()); | 5576 DCHECK(js_object->WasConstructedFromApiFunction()); |
5591 if (js_object->GetInternalFieldCount() >= 2 && | 5577 if (js_object->GetInternalFieldCount() >= 2 && |
5592 js_object->GetInternalField(0) && | 5578 js_object->GetInternalField(0) && |
5593 js_object->GetInternalField(0) != undefined_value() && | 5579 js_object->GetInternalField(0) != undefined_value() && |
5594 js_object->GetInternalField(1) != undefined_value()) { | 5580 js_object->GetInternalField(1) != undefined_value()) { |
5595 DCHECK(reinterpret_cast<intptr_t>(js_object->GetInternalField(0)) % 2 == 0); | 5581 DCHECK(reinterpret_cast<intptr_t>(js_object->GetInternalField(0)) % 2 == 0); |
5596 wrappers_to_trace_.push_back(std::pair<void*, void*>( | 5582 local_embedder_heap_tracer()->AddWrapperToTrace(std::pair<void*, void*>( |
5597 reinterpret_cast<void*>(js_object->GetInternalField(0)), | 5583 reinterpret_cast<void*>(js_object->GetInternalField(0)), |
5598 reinterpret_cast<void*>(js_object->GetInternalField(1)))); | 5584 reinterpret_cast<void*>(js_object->GetInternalField(1)))); |
5599 } | 5585 } |
5600 } | 5586 } |
5601 | 5587 |
5602 bool Heap::RequiresImmediateWrapperProcessing() { | |
5603 const size_t kTooManyWrappers = 16000; | |
5604 return wrappers_to_trace_.size() > kTooManyWrappers; | |
5605 } | |
5606 | |
5607 void Heap::RegisterExternallyReferencedObject(Object** object) { | 5588 void Heap::RegisterExternallyReferencedObject(Object** object) { |
5608 HeapObject* heap_object = HeapObject::cast(*object); | 5589 HeapObject* heap_object = HeapObject::cast(*object); |
5609 DCHECK(Contains(heap_object)); | 5590 DCHECK(Contains(heap_object)); |
5610 if (FLAG_incremental_marking_wrappers && incremental_marking()->IsMarking()) { | 5591 if (FLAG_incremental_marking_wrappers && incremental_marking()->IsMarking()) { |
5611 IncrementalMarking::MarkGrey(this, heap_object); | 5592 IncrementalMarking::MarkGrey(this, heap_object); |
5612 } else { | 5593 } else { |
5613 DCHECK(mark_compact_collector()->in_use()); | 5594 DCHECK(mark_compact_collector()->in_use()); |
5614 MarkBit mark_bit = ObjectMarking::MarkBitFrom(heap_object); | 5595 MarkBit mark_bit = ObjectMarking::MarkBitFrom(heap_object); |
5615 mark_compact_collector()->MarkObject(heap_object, mark_bit); | 5596 mark_compact_collector()->MarkObject(heap_object, mark_bit); |
5616 } | 5597 } |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5673 if (live_object_stats_ != nullptr) { | 5654 if (live_object_stats_ != nullptr) { |
5674 delete live_object_stats_; | 5655 delete live_object_stats_; |
5675 live_object_stats_ = nullptr; | 5656 live_object_stats_ = nullptr; |
5676 } | 5657 } |
5677 | 5658 |
5678 if (dead_object_stats_ != nullptr) { | 5659 if (dead_object_stats_ != nullptr) { |
5679 delete dead_object_stats_; | 5660 delete dead_object_stats_; |
5680 dead_object_stats_ = nullptr; | 5661 dead_object_stats_ = nullptr; |
5681 } | 5662 } |
5682 | 5663 |
| 5664 delete local_embedder_heap_tracer_; |
| 5665 local_embedder_heap_tracer_ = nullptr; |
| 5666 |
5683 delete scavenge_job_; | 5667 delete scavenge_job_; |
5684 scavenge_job_ = nullptr; | 5668 scavenge_job_ = nullptr; |
5685 | 5669 |
5686 isolate_->global_handles()->TearDown(); | 5670 isolate_->global_handles()->TearDown(); |
5687 | 5671 |
5688 external_string_table_.TearDown(); | 5672 external_string_table_.TearDown(); |
5689 | 5673 |
5690 delete tracer_; | 5674 delete tracer_; |
5691 tracer_ = nullptr; | 5675 tracer_ = nullptr; |
5692 | 5676 |
(...skipping 822 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6515 } | 6499 } |
6516 | 6500 |
6517 | 6501 |
6518 // static | 6502 // static |
6519 int Heap::GetStaticVisitorIdForMap(Map* map) { | 6503 int Heap::GetStaticVisitorIdForMap(Map* map) { |
6520 return StaticVisitorBase::GetVisitorId(map); | 6504 return StaticVisitorBase::GetVisitorId(map); |
6521 } | 6505 } |
6522 | 6506 |
6523 } // namespace internal | 6507 } // namespace internal |
6524 } // namespace v8 | 6508 } // namespace v8 |
OLD | NEW |