safepoint.cc 3.65 KB
Newer Older
1 2 3 4 5
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/heap/safepoint.h"
6 7

#include "src/handles/local-handles.h"
8
#include "src/handles/persistent-handles.h"
9 10 11 12 13 14
#include "src/heap/heap.h"
#include "src/heap/local-heap.h"

namespace v8 {
namespace internal {

15
GlobalSafepoint::GlobalSafepoint(Heap* heap)
16
    : heap_(heap), local_heaps_head_(nullptr), active_safepoint_scopes_(0) {}
17

18
void GlobalSafepoint::Start() { EnterSafepointScope(); }
19

20
void GlobalSafepoint::End() { LeaveSafepointScope(); }
21

22 23 24 25
void GlobalSafepoint::EnterSafepointScope() {
  if (!FLAG_local_heaps) return;

  if (++active_safepoint_scopes_ > 1) return;
26
  local_heaps_mutex_.Lock();
27 28 29

  barrier_.Arm();

30
  for (LocalHeap* current = local_heaps_head_; current;
31 32 33 34
       current = current->next_) {
    current->RequestSafepoint();
  }

35
  for (LocalHeap* current = local_heaps_head_; current;
36 37 38 39 40 41 42 43 44
       current = current->next_) {
    current->state_mutex_.Lock();

    while (current->state_ == LocalHeap::ThreadState::Running) {
      current->state_change_.Wait(&current->state_mutex_);
    }
  }
}

45 46 47 48 49
void GlobalSafepoint::LeaveSafepointScope() {
  if (!FLAG_local_heaps) return;

  DCHECK_GT(active_safepoint_scopes_, 0);
  if (--active_safepoint_scopes_ > 0) return;
50

51
  for (LocalHeap* current = local_heaps_head_; current;
52 53 54 55 56 57
       current = current->next_) {
    current->state_mutex_.Unlock();
  }

  barrier_.Disarm();

58
  local_heaps_mutex_.Unlock();
59 60
}

61
void GlobalSafepoint::EnterFromThread(LocalHeap* local_heap) {
62 63 64 65 66 67 68 69 70 71 72 73 74 75
  {
    base::MutexGuard guard(&local_heap->state_mutex_);
    local_heap->state_ = LocalHeap::ThreadState::Safepoint;
    local_heap->state_change_.NotifyAll();
  }

  barrier_.Wait();

  {
    base::MutexGuard guard(&local_heap->state_mutex_);
    local_heap->state_ = LocalHeap::ThreadState::Running;
  }
}

76
void GlobalSafepoint::Barrier::Arm() {
77 78 79 80 81
  base::MutexGuard guard(&mutex_);
  CHECK(!armed_);
  armed_ = true;
}

82
void GlobalSafepoint::Barrier::Disarm() {
83 84 85 86 87 88
  base::MutexGuard guard(&mutex_);
  CHECK(armed_);
  armed_ = false;
  cond_.NotifyAll();
}

89
void GlobalSafepoint::Barrier::Wait() {
90 91 92 93 94 95 96
  base::MutexGuard guard(&mutex_);
  while (armed_) {
    cond_.Wait(&mutex_);
  }
}

SafepointScope::SafepointScope(Heap* heap) : safepoint_(heap->safepoint()) {
97
  safepoint_->EnterSafepointScope();
98 99
}

100
SafepointScope::~SafepointScope() { safepoint_->LeaveSafepointScope(); }
101

102
void GlobalSafepoint::AddLocalHeap(LocalHeap* local_heap) {
103 104 105 106 107 108 109
  base::MutexGuard guard(&local_heaps_mutex_);
  if (local_heaps_head_) local_heaps_head_->prev_ = local_heap;
  local_heap->prev_ = nullptr;
  local_heap->next_ = local_heaps_head_;
  local_heaps_head_ = local_heap;
}

110
void GlobalSafepoint::RemoveLocalHeap(LocalHeap* local_heap) {
111 112 113 114 115 116 117 118
  base::MutexGuard guard(&local_heaps_mutex_);
  if (local_heap->next_) local_heap->next_->prev_ = local_heap->prev_;
  if (local_heap->prev_)
    local_heap->prev_->next_ = local_heap->next_;
  else
    local_heaps_head_ = local_heap->next_;
}

119
bool GlobalSafepoint::ContainsLocalHeap(LocalHeap* local_heap) {
120 121 122 123 124 125 126 127 128 129 130
  base::MutexGuard guard(&local_heaps_mutex_);
  LocalHeap* current = local_heaps_head_;

  while (current) {
    if (current == local_heap) return true;
    current = current->next_;
  }

  return false;
}

131
bool GlobalSafepoint::ContainsAnyLocalHeap() {
132 133 134 135
  base::MutexGuard guard(&local_heaps_mutex_);
  return local_heaps_head_ != nullptr;
}

136
void GlobalSafepoint::Iterate(RootVisitor* visitor) {
137
  DCHECK(IsActive());
138 139 140 141 142 143
  for (LocalHeap* current = local_heaps_head_; current;
       current = current->next_) {
    current->handles()->Iterate(visitor);
  }
}

144 145
}  // namespace internal
}  // namespace v8