• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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()15 void CollectionBarrier::ResumeThreadsAwaitingCollection() {
16   base::MutexGuard guard(&mutex_);
17   ClearCollectionRequested();
18   cond_.NotifyAll();
19 }
20 
ShutdownRequested()21 void 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()43 void 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()61 void 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()79 void 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()89 void 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