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#ifndef V8_HANDLES_PERSISTENT_HANDLES_H_
6#define V8_HANDLES_PERSISTENT_HANDLES_H_
7
8#include <vector>
9
10#include "include/v8-internal.h"
11#include "src/api/api.h"
12#include "src/base/macros.h"
13#include "src/execution/isolate.h"
14#include "src/objects/visitors.h"
15#include "testing/gtest/include/gtest/gtest_prod.h"  // nogncheck
16
17namespace v8 {
18namespace internal {
19
20class Heap;
21
22// PersistentHandles serves as a container for handles that can be passed back
23// and forth between threads. Allocation and deallocation of this class is
24// thread-safe and the isolate tracks all PersistentHandles containers.
25class PersistentHandles {
26 public:
27  V8_EXPORT_PRIVATE explicit PersistentHandles(Isolate* isolate);
28  V8_EXPORT_PRIVATE ~PersistentHandles();
29
30  PersistentHandles(const PersistentHandles&) = delete;
31  PersistentHandles& operator=(const PersistentHandles&) = delete;
32
33  V8_EXPORT_PRIVATE void Iterate(RootVisitor* visitor);
34
35  template <typename T>
36  Handle<T> NewHandle(T obj) {
37#ifdef DEBUG
38    CheckOwnerIsNotParked();
39#endif
40    return Handle<T>(GetHandle(obj.ptr()));
41  }
42
43  template <typename T>
44  Handle<T> NewHandle(Handle<T> obj) {
45    return NewHandle(*obj);
46  }
47
48#ifdef DEBUG
49  V8_EXPORT_PRIVATE bool Contains(Address* location);
50#endif
51
52 private:
53  void AddBlock();
54  V8_EXPORT_PRIVATE Address* GetHandle(Address value);
55
56#ifdef DEBUG
57  void Attach(LocalHeap* local_heap);
58  void Detach();
59  V8_EXPORT_PRIVATE void CheckOwnerIsNotParked();
60
61  LocalHeap* owner_ = nullptr;
62
63#else
64  void Attach(LocalHeap*) {}
65  void Detach() {}
66#endif
67
68  Isolate* isolate_;
69  std::vector<Address*> blocks_;
70
71  Address* block_next_;
72  Address* block_limit_;
73
74  PersistentHandles* prev_;
75  PersistentHandles* next_;
76
77#ifdef DEBUG
78  std::set<Address*> ordered_blocks_;
79#endif
80
81  friend class HandleScopeImplementer;
82  friend class LocalHeap;
83  friend class PersistentHandlesList;
84
85  FRIEND_TEST(PersistentHandlesTest, OrderOfBlocks);
86};
87
88class PersistentHandlesList {
89 public:
90  PersistentHandlesList() : persistent_handles_head_(nullptr) {}
91
92  void Iterate(RootVisitor* visitor, Isolate* isolate);
93
94 private:
95  void Add(PersistentHandles* persistent_handles);
96  void Remove(PersistentHandles* persistent_handles);
97
98  base::Mutex persistent_handles_mutex_;
99  PersistentHandles* persistent_handles_head_;
100
101  friend class PersistentHandles;
102};
103
104// PersistentHandlesScope sets up a scope in which all created main thread
105// handles become persistent handles that can be sent to another thread.
106class V8_NODISCARD PersistentHandlesScope {
107 public:
108  V8_EXPORT_PRIVATE explicit PersistentHandlesScope(Isolate* isolate);
109  V8_EXPORT_PRIVATE ~PersistentHandlesScope();
110
111  // Moves all blocks of this scope into PersistentHandles and returns it.
112  V8_EXPORT_PRIVATE std::unique_ptr<PersistentHandles> Detach();
113
114 private:
115  Address* prev_limit_;
116  Address* prev_next_;
117  HandleScopeImplementer* const impl_;
118
119#ifdef DEBUG
120  bool handles_detached_ = false;
121  int prev_level_;
122#endif
123};
124
125}  // namespace internal
126}  // namespace v8
127
128#endif  // V8_HANDLES_PERSISTENT_HANDLES_H_
129