v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
handles-inl.h
Go to the documentation of this file.
1// Copyright 2006-2008 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_HANDLES_INL_H_
6#define V8_HANDLES_HANDLES_INL_H_
7
9// Include the non-inl header before the rest of the headers.
10
15#include "src/objects/casting.h"
16#include "src/objects/objects.h"
17
18#ifdef DEBUG
19#include "src/utils/ostreams.h"
20#endif
21
22namespace v8 {
23namespace internal {
24
25class LocalHeap;
26
28 : location_(HandleScope::CreateHandle(isolate, object)) {}
29
31 : location_(LocalHandleScope::GetHandle(isolate->heap(), object)) {}
32
34 : location_(LocalHandleScope::GetHandle(local_heap, object)) {}
35
36bool HandleBase::is_identical_to(const HandleBase& that) const {
37 SLOW_DCHECK((this->location_ == nullptr || this->IsDereferenceAllowed()) &&
38 (that.location_ == nullptr || that.IsDereferenceAllowed()));
39 if (this->location_ == that.location_) return true;
40 if (this->location_ == nullptr || that.location_ == nullptr) return false;
41 return Tagged<Object>(*this->location_) == Tagged<Object>(*that.location_);
42}
43
44// Allocate a new handle for the object, do not canonicalize.
45template <typename T>
47 return Handle(HandleScope::CreateHandle(isolate, object.ptr()));
48}
49
50template <typename T, typename U>
51inline bool Is(IndirectHandle<U> value) {
52 return value.is_null() || Is<T>(*value);
53}
54template <typename To, typename From>
56 return Handle<To>(value.location());
57}
58
59template <typename T>
61 : HandleBase(object.ptr(), isolate) {}
62
63template <typename T>
65 : HandleBase(object.ptr(), isolate) {}
66
67template <typename T>
69 : HandleBase(object.ptr(), local_heap) {}
70
71template <typename T>
73 return Handle<T>(object, isolate);
74}
75
76template <typename T>
78 return Handle<T>(object, isolate);
79}
80
81template <typename T>
83 return Handle<T>(object, local_heap);
84}
85
86template <typename T>
88 static_assert(kTaggedCanConvertToRawObjects);
89 return handle(Tagged<T>(object), isolate);
90}
91
92template <typename T>
94 static_assert(kTaggedCanConvertToRawObjects);
95 return handle(Tagged<T>(object), isolate);
96}
97
98template <typename T>
100 static_assert(kTaggedCanConvertToRawObjects);
101 return handle(Tagged<T>(object), local_heap);
102}
103
104template <typename T>
105inline std::ostream& operator<<(std::ostream& os, IndirectHandle<T> handle) {
106 return os << Brief(*handle);
107}
108
109#ifdef V8_ENABLE_DIRECT_HANDLE
110
111template <typename T>
113 : DirectHandle(object.ptr()) {}
114
115template <typename T, typename U>
116inline bool Is(DirectHandle<U> value) {
117 return value.is_null() || Is<T>(*value);
118}
119template <typename To, typename From>
120inline DirectHandle<To> UncheckedCast(DirectHandle<From> value) {
121 return DirectHandle<To>(value.obj_);
122}
123
124#else
125
126template <typename T, typename U>
127inline bool Is(DirectHandle<U> value) {
128 return value.is_null() || Is<T>(*value);
129}
130template <typename To, typename From>
132 return DirectHandle<To>(UncheckedCast<To>(value.handle_));
133}
134
135#endif // V8_ENABLE_DIRECT_HANDLE
136
137template <typename T>
138inline std::ostream& operator<<(std::ostream& os, DirectHandle<T> handle) {
139 return os << Brief(*handle);
140}
141
142template <typename T>
144 return DirectHandle<T>(object, isolate);
145}
146
147template <typename T>
149 LocalIsolate* isolate) {
150 return DirectHandle<T>(object, isolate);
151}
152
153template <typename T>
155 LocalHeap* local_heap) {
156 return DirectHandle<T>(object, local_heap);
157}
158
159template <typename T>
161 static_assert(kTaggedCanConvertToRawObjects);
162 return direct_handle(Tagged<T>(object), isolate);
163}
164
165template <typename T>
167 static_assert(kTaggedCanConvertToRawObjects);
168 return direct_handle(Tagged<T>(object), isolate);
169}
170
171template <typename T>
173 static_assert(kTaggedCanConvertToRawObjects);
174 return direct_handle(Tagged<T>(object), local_heap);
175}
176
178 HandleScopeData* data = isolate->handle_scope_data();
180 prev_next_ = data->next;
181 prev_limit_ = data->limit;
182 data->level++;
183#ifdef V8_ENABLE_CHECKS
184 scope_level_ = data->level;
185#endif
186}
187
189 : isolate_(other.isolate_),
190 prev_next_(other.prev_next_),
191 prev_limit_(other.prev_limit_) {
192 other.isolate_ = nullptr;
193#ifdef V8_ENABLE_CHECKS
194 scope_level_ = other.scope_level_;
195#endif
196}
197
199 if (V8_UNLIKELY(isolate_ == nullptr)) return;
200#ifdef V8_ENABLE_CHECKS
201 CHECK_EQ(scope_level_, isolate_->handle_scope_data()->level);
202#endif
203 CloseScope(isolate_, prev_next_, prev_limit_);
204}
205
207 if (isolate_ == nullptr) {
208 isolate_ = other.isolate_;
209 } else {
210 DCHECK_EQ(isolate_, other.isolate_);
211#ifdef V8_ENABLE_CHECKS
212 CHECK_EQ(scope_level_, isolate_->handle_scope_data()->level);
213#endif
214 CloseScope(isolate_, prev_next_, prev_limit_);
215 }
216 prev_next_ = other.prev_next_;
217 prev_limit_ = other.prev_limit_;
218 other.isolate_ = nullptr;
219#ifdef V8_ENABLE_CHECKS
220 scope_level_ = other.scope_level_;
221#endif
222 return *this;
223}
224
225void HandleScope::CloseScope(Isolate* isolate, Address* prev_next,
226 Address* prev_limit) {
227#ifdef DEBUG
228 int before = v8_flags.check_handle_count ? NumberOfHandles(isolate) : 0;
229#endif
230 DCHECK_NOT_NULL(isolate);
231 HandleScopeData* current = isolate->handle_scope_data();
232
233 std::swap(current->next, prev_next);
234 current->level--;
235 Address* limit = prev_next;
236 if (V8_UNLIKELY(current->limit != prev_limit)) {
237 current->limit = prev_limit;
238 limit = prev_limit;
239 DeleteExtensions(isolate);
240 }
241#ifdef ENABLE_LOCAL_HANDLE_ZAPPING
242 ZapRange(current->next, limit);
243#endif
245 current->next,
246 static_cast<size_t>(reinterpret_cast<Address>(limit) -
247 reinterpret_cast<Address>(current->next)));
248#ifdef DEBUG
249 int after = v8_flags.check_handle_count ? NumberOfHandles(isolate) : 0;
250 DCHECK_LT(after - before, kCheckHandleThreshold);
251 DCHECK_LT(before, kCheckHandleThreshold);
252#endif
253}
254
255template <typename T, template <typename> typename HandleType>
256 requires(std::is_convertible_v<HandleType<T>, DirectHandle<T>>)
257HandleType<T> HandleScope::CloseAndEscape(HandleType<T> handle_value) {
258 HandleScopeData* current = isolate_->handle_scope_data();
259 Tagged<T> value = *handle_value;
260#ifdef V8_ENABLE_CHECKS
261 CHECK_EQ(scope_level_, isolate_->handle_scope_data()->level);
262#endif
263 // Throw away all handles in the current scope.
264 CloseScope(isolate_, prev_next_, prev_limit_);
265 // Allocate one handle in the parent scope.
266 DCHECK(current->level > current->sealed_level);
267 HandleType<T> result(value, isolate_);
268 // Reinitialize the current scope (so that it's ready
269 // to be used or closed again).
270 prev_next_ = current->next;
271 prev_limit_ = current->limit;
272 current->level++;
273 return result;
274}
275
276Address* HandleScope::CreateHandle(Isolate* isolate, Address value) {
277 DCHECK(AllowHandleAllocation::IsAllowed());
278#ifdef DEBUG
279 if (!AllowHandleUsageOnAllThreads::IsAllowed()) {
280 DCHECK(isolate->main_thread_local_heap()->IsRunning());
282 isolate->thread_id() == ThreadId::Current(),
283 "main-thread handle can only be created on the main thread.");
284 }
285#endif
286 HandleScopeData* data = isolate->handle_scope_data();
287 Address* result = data->next;
288 if (V8_UNLIKELY(result == data->limit)) {
289 result = Extend(isolate);
290 }
291 // Update the current next field, set the value in the created handle,
292 // and return the result.
293 DCHECK_LT(reinterpret_cast<Address>(result),
294 reinterpret_cast<Address>(data->limit));
295 data->next = reinterpret_cast<Address*>(reinterpret_cast<Address>(result) +
296 sizeof(Address));
297 *result = value;
298 return result;
299}
300
301#ifdef DEBUG
302inline SealHandleScope::SealHandleScope(Isolate* isolate) : isolate_(isolate) {
303 // Make sure the current thread is allowed to create handles to begin with.
304 DCHECK(AllowHandleAllocation::IsAllowed());
306 // Shrink the current handle scope to make it impossible to do
307 // handle allocations without an explicit handle scope.
308 prev_limit_ = current->limit;
309 current->limit = current->next;
310 prev_sealed_level_ = current->sealed_level;
311 current->sealed_level = current->level;
312}
313
315 // Restore state in current handle scope to re-enable handle
316 // allocations.
317 HandleScopeData* current = isolate_->handle_scope_data();
318 DCHECK_EQ(current->next, current->limit);
319 current->limit = prev_limit_;
320 DCHECK_EQ(current->level, current->sealed_level);
321 current->sealed_level = prev_sealed_level_;
322}
323#endif // DEBUG
324
325#ifdef V8_ENABLE_DIRECT_HANDLE
326bool HandleBase::is_identical_to(const DirectHandleBase& that) const {
328 (this->location_ == nullptr || this->IsDereferenceAllowed()) &&
329 (that.address() == kTaggedNullAddress || that.IsDereferenceAllowed()));
330 if (this->location_ == nullptr && that.address() == kTaggedNullAddress)
331 return true;
332 if (this->location_ == nullptr || that.address() == kTaggedNullAddress)
333 return false;
334 return Tagged<Object>(*this->location_) == Tagged<Object>(that.address());
335}
336
337bool DirectHandleBase::is_identical_to(const HandleBase& that) const {
339 (this->address() == kTaggedNullAddress || this->IsDereferenceAllowed()) &&
340 (that.location_ == nullptr || that.IsDereferenceAllowed()));
341 if (this->address() == kTaggedNullAddress && that.location_ == nullptr)
342 return true;
343 if (this->address() == kTaggedNullAddress || that.location_ == nullptr)
344 return false;
345 return Tagged<Object>(this->address()) == Tagged<Object>(*that.location_);
346}
347
348bool DirectHandleBase::is_identical_to(const DirectHandleBase& that) const {
350 (this->address() == kTaggedNullAddress || this->IsDereferenceAllowed()) &&
351 (that.address() == kTaggedNullAddress || that.IsDereferenceAllowed()));
352 if (this->address() == kTaggedNullAddress &&
353 that.address() == kTaggedNullAddress)
354 return true;
355 if (this->address() == kTaggedNullAddress ||
356 that.address() == kTaggedNullAddress)
357 return false;
358 return Tagged<Object>(this->address()) == Tagged<Object>(that.address());
359}
360#endif // V8_ENABLE_DIRECT_HANDLE
361
362} // namespace internal
363} // namespace v8
364
365#endif // V8_HANDLES_HANDLES_INL_H_
Isolate * isolate_
#define SLOW_DCHECK(condition)
Definition checks.h:21
internal::Address * prev_next_
void operator=(const HandleScope &)=delete
static int NumberOfHandles(Isolate *isolate)
Definition api.cc:728
V8_INLINE HandleScope()=default
internal::Address * prev_limit_
static internal::Address * CreateHandle(internal::Isolate *i_isolate, internal::Address value)
static V8_INLINE Local< T > New(Isolate *isolate, Local< T > that)
SealHandleScope(Isolate *isolate)
Definition api.cc:761
friend class DirectHandle
Definition handles.h:730
V8_INLINE HandleBase(Address *location)
Definition handles.h:120
V8_INLINE bool is_identical_to(const HandleBase &that) const
Definition handles-inl.h:36
V8_INLINE bool IsDereferenceAllowed() const
Definition handles.h:128
static V8_INLINE Address * CreateHandle(Isolate *isolate, Address value)
V8_INLINE HandleScopeData * handle_scope_data()
Definition isolate.h:1393
Isolate * isolate
ZoneVector< RpoNumber > & result
LinkageLocation location_
#define MSAN_ALLOCATED_UNINITIALIZED_MEMORY(start, size)
Definition msan.h:29
V8_INLINE IndirectHandle< T > handle(Tagged< T > object, Isolate *isolate)
Definition handles-inl.h:72
constexpr Address kTaggedNullAddress
Definition handles.h:53
bool Is(IndirectHandle< U > value)
Definition handles-inl.h:51
static constexpr bool kTaggedCanConvertToRawObjects
Definition tagged.h:329
V8_INLINE DirectHandle< T > direct_handle(Tagged< T > object, Isolate *isolate)
std::ostream & operator<<(std::ostream &os, AtomicMemoryOrder order)
Handle< To > UncheckedCast(Handle< From > value)
Definition handles-inl.h:55
V8_EXPORT_PRIVATE FlagValues v8_flags
Local< T > Handle
std::ostream & operator<<(std::ostream &os, const Operation &operation)
Definition operation.h:49
#define V8_NOEXCEPT
#define DCHECK_WITH_MSG(condition, msg)
Definition logging.h:182
#define DCHECK_NOT_NULL(val)
Definition logging.h:492
#define CHECK_EQ(lhs, rhs)
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_LT(v1, v2)
Definition logging.h:489
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
#define V8_INLINE
Definition v8config.h:500
#define V8_UNLIKELY(condition)
Definition v8config.h:660
std::unique_ptr< ValueMirror > value