blob: 80fea9bc4c908c323f23860fa5030d9f6f120723 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
|
// 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.
#ifndef V8_EXECUTION_OFF_THREAD_ISOLATE_H_
#define V8_EXECUTION_OFF_THREAD_ISOLATE_H_
#include "src/base/macros.h"
#include "src/execution/thread-id.h"
#include "src/handles/handles.h"
#include "src/handles/maybe-handles.h"
#include "src/heap/off-thread-factory.h"
#include "src/heap/off-thread-heap.h"
namespace v8 {
namespace internal {
class Isolate;
class OffThreadLogger;
class OffThreadTransferHandleStorage;
class OffThreadTransferHandleBase {
protected:
explicit OffThreadTransferHandleBase(OffThreadTransferHandleStorage* storage)
: storage_(storage) {}
V8_EXPORT_PRIVATE Address* ToHandleLocation() const;
private:
OffThreadTransferHandleStorage* storage_;
};
// Helper class for transferring ownership of an off-thread allocated object's
// handler to the main thread. OffThreadTransferHandles should be created before
// the OffThreadIsolate is finished, and can be accessed as a Handle after the
// OffThreadIsolate is published.
template <typename T>
class OffThreadTransferHandle : public OffThreadTransferHandleBase {
public:
OffThreadTransferHandle() : OffThreadTransferHandleBase(nullptr) {}
explicit OffThreadTransferHandle(OffThreadTransferHandleStorage* storage)
: OffThreadTransferHandleBase(storage) {}
Handle<T> ToHandle() const { return Handle<T>(ToHandleLocation()); }
};
template <typename T>
class OffThreadTransferMaybeHandle : public OffThreadTransferHandleBase {
public:
OffThreadTransferMaybeHandle() : OffThreadTransferHandleBase(nullptr) {}
explicit OffThreadTransferMaybeHandle(OffThreadTransferHandleStorage* storage)
: OffThreadTransferHandleBase(storage) {}
MaybeHandle<T> ToHandle() const {
Address* location = ToHandleLocation();
return location ? Handle<T>(location) : MaybeHandle<T>();
}
};
// HiddenOffThreadFactory parallels Isolate's HiddenFactory
class V8_EXPORT_PRIVATE HiddenOffThreadFactory : private OffThreadFactory {
public:
// Forward constructors.
using OffThreadFactory::OffThreadFactory;
};
// And Isolate-like class that can be passed in to templated methods that need
// an isolate syntactically, but are usable off-thread.
//
// This class holds an OffThreadFactory, but is otherwise effectively a stub
// implementation of an Isolate. In particular, it doesn't allow throwing
// exceptions, and hard crashes if you try.
class V8_EXPORT_PRIVATE OffThreadIsolate final
: private HiddenOffThreadFactory {
public:
using HandleScopeType = OffThreadHandleScope;
explicit OffThreadIsolate(Isolate* isolate, Zone* zone);
~OffThreadIsolate();
static OffThreadIsolate* FromHeap(OffThreadHeap* heap) {
return reinterpret_cast<OffThreadIsolate*>(
reinterpret_cast<Address>(heap) - OFFSET_OF(OffThreadIsolate, heap_));
}
OffThreadHeap* heap() { return &heap_; }
inline Address isolate_root() const;
v8::internal::OffThreadFactory* factory() {
// Upcast to the privately inherited base-class using c-style casts to avoid
// undefined behavior (as static_cast cannot cast across private bases).
// NOLINTNEXTLINE (google-readability-casting)
return (
v8::internal::OffThreadFactory*)this; // NOLINT(readability/casting)
}
// This method finishes the use of the off-thread Isolate, and can be safely
// called off-thread.
void FinishOffThread();
// This method publishes the off-thread Isolate to the main-thread Isolate,
// moving all off-thread allocated objects to be visible to the GC, and fixing
// up any other state (e.g. internalized strings). This method must be called
// on the main thread.
void Publish(Isolate* isolate);
bool has_pending_exception() const { return false; }
template <typename T>
Handle<T> Throw(Handle<Object> exception) {
UNREACHABLE();
}
[[noreturn]] void FatalProcessOutOfHeapMemory(const char* location) {
UNREACHABLE();
}
Address* NewHandle(Address object) {
DCHECK_NOT_NULL(handle_zone_);
Address* location =
static_cast<Address*>(handle_zone_->New(sizeof(Address)));
*location = object;
return location;
}
template <typename T>
OffThreadTransferHandle<T> TransferHandle(Handle<T> handle) {
DCHECK_NOT_NULL(handle_zone_);
if (handle.is_null()) {
return OffThreadTransferHandle<T>();
}
return OffThreadTransferHandle<T>(AddTransferHandleStorage(handle));
}
template <typename T>
OffThreadTransferMaybeHandle<T> TransferHandle(MaybeHandle<T> maybe_handle) {
DCHECK_NOT_NULL(handle_zone_);
Handle<T> handle;
if (!maybe_handle.ToHandle(&handle)) {
return OffThreadTransferMaybeHandle<T>();
}
return OffThreadTransferMaybeHandle<T>(AddTransferHandleStorage(handle));
}
int GetNextScriptId();
#if V8_SFI_HAS_UNIQUE_ID
int GetNextUniqueSharedFunctionInfoId();
#endif // V8_SFI_HAS_UNIQUE_ID
bool is_collecting_type_profile();
OffThreadLogger* logger() { return logger_.get(); }
void PinToCurrentThread();
ThreadId thread_id() { return thread_id_; }
private:
friend class v8::internal::OffThreadFactory;
OffThreadTransferHandleStorage* AddTransferHandleStorage(HandleBase handle);
OffThreadHeap heap_;
// TODO(leszeks): Extract out the fields of the Isolate we want and store
// those instead of the whole thing.
Isolate* isolate_;
std::unique_ptr<OffThreadLogger> logger_;
ThreadId thread_id_;
Zone* handle_zone_;
std::unique_ptr<OffThreadTransferHandleStorage>
off_thread_transfer_handles_head_;
};
} // namespace internal
} // namespace v8
#endif // V8_EXECUTION_OFF_THREAD_ISOLATE_H_
|