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 2536 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4163 if (ShouldReduceMemory() || | 4159 if (ShouldReduceMemory() || |
4164 ((allocation_throughput != 0) && | 4160 ((allocation_throughput != 0) && |
4165 (allocation_throughput < kLowAllocationThroughput))) { | 4161 (allocation_throughput < kLowAllocationThroughput))) { |
4166 new_space_->Shrink(); | 4162 new_space_->Shrink(); |
4167 UncommitFromSpace(); | 4163 UncommitFromSpace(); |
4168 } | 4164 } |
4169 } | 4165 } |
4170 | 4166 |
4171 bool Heap::MarkingDequesAreEmpty() { | 4167 bool Heap::MarkingDequesAreEmpty() { |
4172 return mark_compact_collector()->marking_deque()->IsEmpty() && | 4168 return mark_compact_collector()->marking_deque()->IsEmpty() && |
4173 (!UsingEmbedderHeapTracer() || | 4169 local_embedder_heap_tracer()->NumberOfWrappersToTrace() == 0; |
4174 (wrappers_to_trace() == 0 && | |
4175 embedder_heap_tracer()->NumberOfWrappersToTrace() == 0)); | |
4176 } | 4170 } |
4177 | 4171 |
4178 void Heap::FinalizeIncrementalMarkingIfComplete( | 4172 void Heap::FinalizeIncrementalMarkingIfComplete( |
4179 GarbageCollectionReason gc_reason) { | 4173 GarbageCollectionReason gc_reason) { |
4180 if (incremental_marking()->IsMarking() && | 4174 if (incremental_marking()->IsMarking() && |
4181 (incremental_marking()->IsReadyToOverApproximateWeakClosure() || | 4175 (incremental_marking()->IsReadyToOverApproximateWeakClosure() || |
4182 (!incremental_marking()->finalize_marking_completed() && | 4176 (!incremental_marking()->finalize_marking_completed() && |
4183 MarkingDequesAreEmpty()))) { | 4177 MarkingDequesAreEmpty()))) { |
4184 FinalizeIncrementalMarking(gc_reason); | 4178 FinalizeIncrementalMarking(gc_reason); |
4185 } else if (incremental_marking()->IsComplete() || MarkingDequesAreEmpty()) { | 4179 } else if (incremental_marking()->IsComplete() || MarkingDequesAreEmpty()) { |
(...skipping 1281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5467 tracer_ = new GCTracer(this); | 5461 tracer_ = new GCTracer(this); |
5468 scavenge_collector_ = new Scavenger(this); | 5462 scavenge_collector_ = new Scavenger(this); |
5469 mark_compact_collector_ = new MarkCompactCollector(this); | 5463 mark_compact_collector_ = new MarkCompactCollector(this); |
5470 gc_idle_time_handler_ = new GCIdleTimeHandler(); | 5464 gc_idle_time_handler_ = new GCIdleTimeHandler(); |
5471 memory_reducer_ = new MemoryReducer(this); | 5465 memory_reducer_ = new MemoryReducer(this); |
5472 if (V8_UNLIKELY(FLAG_gc_stats)) { | 5466 if (V8_UNLIKELY(FLAG_gc_stats)) { |
5473 live_object_stats_ = new ObjectStats(this); | 5467 live_object_stats_ = new ObjectStats(this); |
5474 dead_object_stats_ = new ObjectStats(this); | 5468 dead_object_stats_ = new ObjectStats(this); |
5475 } | 5469 } |
5476 scavenge_job_ = new ScavengeJob(); | 5470 scavenge_job_ = new ScavengeJob(); |
| 5471 local_embedder_heap_tracer_ = new LocalEmbedderHeapTracer(); |
5477 | 5472 |
5478 LOG(isolate_, IntPtrTEvent("heap-capacity", Capacity())); | 5473 LOG(isolate_, IntPtrTEvent("heap-capacity", Capacity())); |
5479 LOG(isolate_, IntPtrTEvent("heap-available", Available())); | 5474 LOG(isolate_, IntPtrTEvent("heap-available", Available())); |
5480 | 5475 |
5481 store_buffer()->SetUp(); | 5476 store_buffer()->SetUp(); |
5482 | 5477 |
5483 mark_compact_collector()->SetUp(); | 5478 mark_compact_collector()->SetUp(); |
5484 | 5479 |
5485 idle_scavenge_observer_ = new IdleScavengeObserver( | 5480 idle_scavenge_observer_ = new IdleScavengeObserver( |
5486 *this, ScavengeJob::kBytesAllocatedBeforeNextIdleTask); | 5481 *this, ScavengeJob::kBytesAllocatedBeforeNextIdleTask); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5542 CHECK(p->NeverEvacuate()); | 5537 CHECK(p->NeverEvacuate()); |
5543 } | 5538 } |
5544 #endif // DEBUG | 5539 #endif // DEBUG |
5545 } | 5540 } |
5546 | 5541 |
5547 deserialization_complete_ = true; | 5542 deserialization_complete_ = true; |
5548 } | 5543 } |
5549 | 5544 |
5550 void Heap::SetEmbedderHeapTracer(EmbedderHeapTracer* tracer) { | 5545 void Heap::SetEmbedderHeapTracer(EmbedderHeapTracer* tracer) { |
5551 DCHECK_EQ(gc_state_, HeapState::NOT_IN_GC); | 5546 DCHECK_EQ(gc_state_, HeapState::NOT_IN_GC); |
5552 embedder_heap_tracer_ = tracer; | 5547 local_embedder_heap_tracer()->SetRemoteTracer(tracer); |
5553 } | |
5554 | |
5555 void Heap::RegisterWrappersWithEmbedderHeapTracer() { | |
5556 DCHECK(UsingEmbedderHeapTracer()); | |
5557 if (wrappers_to_trace_.empty()) { | |
5558 return; | |
5559 } | |
5560 embedder_heap_tracer()->RegisterV8References(wrappers_to_trace_); | |
5561 wrappers_to_trace_.clear(); | |
5562 } | 5548 } |
5563 | 5549 |
5564 void Heap::TracePossibleWrapper(JSObject* js_object) { | 5550 void Heap::TracePossibleWrapper(JSObject* js_object) { |
5565 DCHECK(js_object->WasConstructedFromApiFunction()); | 5551 DCHECK(js_object->WasConstructedFromApiFunction()); |
5566 if (js_object->GetInternalFieldCount() >= 2 && | 5552 if (js_object->GetInternalFieldCount() >= 2 && |
5567 js_object->GetInternalField(0) && | 5553 js_object->GetInternalField(0) && |
5568 js_object->GetInternalField(0) != undefined_value() && | 5554 js_object->GetInternalField(0) != undefined_value() && |
5569 js_object->GetInternalField(1) != undefined_value()) { | 5555 js_object->GetInternalField(1) != undefined_value()) { |
5570 DCHECK(reinterpret_cast<intptr_t>(js_object->GetInternalField(0)) % 2 == 0); | 5556 DCHECK(reinterpret_cast<intptr_t>(js_object->GetInternalField(0)) % 2 == 0); |
5571 wrappers_to_trace_.push_back(std::pair<void*, void*>( | 5557 local_embedder_heap_tracer()->AddWrapperToTrace(std::pair<void*, void*>( |
5572 reinterpret_cast<void*>(js_object->GetInternalField(0)), | 5558 reinterpret_cast<void*>(js_object->GetInternalField(0)), |
5573 reinterpret_cast<void*>(js_object->GetInternalField(1)))); | 5559 reinterpret_cast<void*>(js_object->GetInternalField(1)))); |
5574 } | 5560 } |
5575 } | 5561 } |
5576 | 5562 |
5577 bool Heap::RequiresImmediateWrapperProcessing() { | |
5578 const size_t kTooManyWrappers = 16000; | |
5579 return wrappers_to_trace_.size() > kTooManyWrappers; | |
5580 } | |
5581 | |
5582 void Heap::RegisterExternallyReferencedObject(Object** object) { | 5563 void Heap::RegisterExternallyReferencedObject(Object** object) { |
5583 HeapObject* heap_object = HeapObject::cast(*object); | 5564 HeapObject* heap_object = HeapObject::cast(*object); |
5584 DCHECK(Contains(heap_object)); | 5565 DCHECK(Contains(heap_object)); |
5585 if (FLAG_incremental_marking_wrappers && incremental_marking()->IsMarking()) { | 5566 if (FLAG_incremental_marking_wrappers && incremental_marking()->IsMarking()) { |
5586 IncrementalMarking::MarkGrey(this, heap_object); | 5567 IncrementalMarking::MarkGrey(this, heap_object); |
5587 } else { | 5568 } else { |
5588 DCHECK(mark_compact_collector()->in_use()); | 5569 DCHECK(mark_compact_collector()->in_use()); |
5589 MarkBit mark_bit = ObjectMarking::MarkBitFrom(heap_object); | 5570 MarkBit mark_bit = ObjectMarking::MarkBitFrom(heap_object); |
5590 mark_compact_collector()->MarkObject(heap_object, mark_bit); | 5571 mark_compact_collector()->MarkObject(heap_object, mark_bit); |
5591 } | 5572 } |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5648 if (live_object_stats_ != nullptr) { | 5629 if (live_object_stats_ != nullptr) { |
5649 delete live_object_stats_; | 5630 delete live_object_stats_; |
5650 live_object_stats_ = nullptr; | 5631 live_object_stats_ = nullptr; |
5651 } | 5632 } |
5652 | 5633 |
5653 if (dead_object_stats_ != nullptr) { | 5634 if (dead_object_stats_ != nullptr) { |
5654 delete dead_object_stats_; | 5635 delete dead_object_stats_; |
5655 dead_object_stats_ = nullptr; | 5636 dead_object_stats_ = nullptr; |
5656 } | 5637 } |
5657 | 5638 |
| 5639 delete local_embedder_heap_tracer_; |
| 5640 local_embedder_heap_tracer_ = nullptr; |
| 5641 |
5658 delete scavenge_job_; | 5642 delete scavenge_job_; |
5659 scavenge_job_ = nullptr; | 5643 scavenge_job_ = nullptr; |
5660 | 5644 |
5661 isolate_->global_handles()->TearDown(); | 5645 isolate_->global_handles()->TearDown(); |
5662 | 5646 |
5663 external_string_table_.TearDown(); | 5647 external_string_table_.TearDown(); |
5664 | 5648 |
5665 delete tracer_; | 5649 delete tracer_; |
5666 tracer_ = nullptr; | 5650 tracer_ = nullptr; |
5667 | 5651 |
(...skipping 822 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6490 } | 6474 } |
6491 | 6475 |
6492 | 6476 |
6493 // static | 6477 // static |
6494 int Heap::GetStaticVisitorIdForMap(Map* map) { | 6478 int Heap::GetStaticVisitorIdForMap(Map* map) { |
6495 return StaticVisitorBase::GetVisitorId(map); | 6479 return StaticVisitorBase::GetVisitorId(map); |
6496 } | 6480 } |
6497 | 6481 |
6498 } // namespace internal | 6482 } // namespace internal |
6499 } // namespace v8 | 6483 } // namespace v8 |
OLD | NEW |