| 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 |