1 // Copyright 2020 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "src/heap/collection-barrier.h" 6 7 #include "src/base/platform/time.h" 8 #include "src/heap/gc-tracer.h" 9 #include "src/heap/heap-inl.h" 10 #include "src/heap/heap.h" 11 12 namespace v8 { 13 namespace internal { 14 ResumeThreadsAwaitingCollection()15void CollectionBarrier::ResumeThreadsAwaitingCollection() { 16 base::MutexGuard guard(&mutex_); 17 ClearCollectionRequested(); 18 cond_.NotifyAll(); 19 } 20 ShutdownRequested()21void CollectionBarrier::ShutdownRequested() { 22 base::MutexGuard guard(&mutex_); 23 if (timer_.IsStarted()) timer_.Stop(); 24 state_.store(RequestState::kShutdown); 25 cond_.NotifyAll(); 26 } 27 28 class BackgroundCollectionInterruptTask : public CancelableTask { 29 public: BackgroundCollectionInterruptTask(Heap * heap)30 explicit BackgroundCollectionInterruptTask(Heap* heap) 31 : CancelableTask(heap->isolate()), heap_(heap) {} 32 33 ~BackgroundCollectionInterruptTask() override = default; 34 35 private: 36 // v8::internal::CancelableTask overrides. RunInternal()37 void RunInternal() override { heap_->CheckCollectionRequested(); } 38 39 Heap* heap_; 40 DISALLOW_COPY_AND_ASSIGN(BackgroundCollectionInterruptTask); 41 }; 42 AwaitCollectionBackground()43void CollectionBarrier::AwaitCollectionBackground() { 44 bool first; 45 46 { 47 base::MutexGuard guard(&mutex_); 48 first = FirstCollectionRequest(); 49 if (first) timer_.Start(); 50 } 51 52 if (first) { 53 // This is the first background thread requesting collection, ask the main 54 // thread for GC. 55 ActivateStackGuardAndPostTask(); 56 } 57 58 BlockUntilCollected(); 59 } 60 StopTimeToCollectionTimer()61void CollectionBarrier::StopTimeToCollectionTimer() { 62 base::MutexGuard guard(&mutex_); 63 RequestState old_state = state_.exchange(RequestState::kCollectionStarted, 64 std::memory_order_relaxed); 65 if (old_state == RequestState::kCollectionRequested) { 66 DCHECK(timer_.IsStarted()); 67 base::TimeDelta delta = timer_.Elapsed(); 68 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("v8.gc"), 69 "V8.TimeToCollection", TRACE_EVENT_SCOPE_THREAD, 70 "duration", delta.InMillisecondsF()); 71 heap_->isolate()->counters()->time_to_collection()->AddTimedSample(delta); 72 timer_.Stop(); 73 } else { 74 DCHECK_EQ(old_state, RequestState::kDefault); 75 DCHECK(!timer_.IsStarted()); 76 } 77 } 78 ActivateStackGuardAndPostTask()79void CollectionBarrier::ActivateStackGuardAndPostTask() { 80 Isolate* isolate = heap_->isolate(); 81 ExecutionAccess access(isolate); 82 isolate->stack_guard()->RequestGC(); 83 auto taskrunner = V8::GetCurrentPlatform()->GetForegroundTaskRunner( 84 reinterpret_cast<v8::Isolate*>(isolate)); 85 taskrunner->PostTask( 86 std::make_unique<BackgroundCollectionInterruptTask>(heap_)); 87 } 88 BlockUntilCollected()89void CollectionBarrier::BlockUntilCollected() { 90 TRACE_BACKGROUND_GC(heap_->tracer(), 91 GCTracer::BackgroundScope::BACKGROUND_COLLECTION); 92 base::MutexGuard guard(&mutex_); 93 94 while (CollectionRequested()) { 95 cond_.Wait(&mutex_); 96 } 97 } 98 99 } // namespace internal 100 } // namespace v8 101