blob: ab8ed0920a4c637b6c0bc67775c801ee287f2ec1 [file] [log] [blame]
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001// Copyright 2011 the V8 project authors. All rights reserved.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Steve Blocka7e24c12009-10-30 11:49:00 +00004
5#ifndef V8_HANDLES_H_
6#define V8_HANDLES_H_
7
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008#include "include/v8.h"
9#include "src/base/functional.h"
10#include "src/base/macros.h"
11#include "src/checks.h"
12#include "src/globals.h"
13#include "src/zone.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000014
15namespace v8 {
16namespace internal {
17
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018// Forward declarations.
19class DeferredHandles;
20class HandleScopeImplementer;
21class Isolate;
22class Object;
23
24
25// ----------------------------------------------------------------------------
26// Base class for Handle instantiations. Don't use directly.
27class HandleBase {
28 public:
29 V8_INLINE explicit HandleBase(Object** location) : location_(location) {}
30 V8_INLINE explicit HandleBase(Object* object, Isolate* isolate);
31
32 // Check if this handle refers to the exact same object as the other handle.
33 V8_INLINE bool is_identical_to(const HandleBase that) const {
34 // Dereferencing deferred handles to check object equality is safe.
35 SLOW_DCHECK((this->location_ == nullptr ||
36 this->IsDereferenceAllowed(NO_DEFERRED_CHECK)) &&
37 (that.location_ == nullptr ||
38 that.IsDereferenceAllowed(NO_DEFERRED_CHECK)));
39 if (this->location_ == that.location_) return true;
40 if (this->location_ == NULL || that.location_ == NULL) return false;
41 return *this->location_ == *that.location_;
42 }
43
44 V8_INLINE bool is_null() const { return location_ == nullptr; }
45
Ben Murdochc5610432016-08-08 18:44:38 +010046 // Returns the raw address where this handle is stored. This should only be
47 // used for hashing handles; do not ever try to dereference it.
48 V8_INLINE Address address() const { return bit_cast<Address>(location_); }
49
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000050 protected:
51 // Provides the C++ dereference operator.
52 V8_INLINE Object* operator*() const {
53 SLOW_DCHECK(IsDereferenceAllowed(INCLUDE_DEFERRED_CHECK));
54 return *location_;
55 }
56
57 // Returns the address to where the raw pointer is stored.
58 V8_INLINE Object** location() const {
59 SLOW_DCHECK(location_ == nullptr ||
60 IsDereferenceAllowed(INCLUDE_DEFERRED_CHECK));
61 return location_;
62 }
63
64 enum DereferenceCheckMode { INCLUDE_DEFERRED_CHECK, NO_DEFERRED_CHECK };
65#ifdef DEBUG
66 bool IsDereferenceAllowed(DereferenceCheckMode mode) const;
67#else
68 V8_INLINE
69 bool IsDereferenceAllowed(DereferenceCheckMode mode) const { return true; }
70#endif // DEBUG
71
72 Object** location_;
73};
74
75
76// ----------------------------------------------------------------------------
77// A Handle provides a reference to an object that survives relocation by
78// the garbage collector.
79//
80// Handles are only valid within a HandleScope. When a handle is created
81// for an object a cell is allocated in the current HandleScope.
82//
83// Also note that Handles do not provide default equality comparison or hashing
84// operators on purpose. Such operators would be misleading, because intended
85// semantics is ambiguous between Handle location and object identity. Instead
86// use either {is_identical_to} or {location} explicitly.
87template <typename T>
88class Handle final : public HandleBase {
89 public:
90 V8_INLINE explicit Handle(T** location = nullptr)
91 : HandleBase(reinterpret_cast<Object**>(location)) {
92 Object* a = nullptr;
93 T* b = nullptr;
94 a = b; // Fake assignment to enforce type checks.
95 USE(a);
96 }
97 V8_INLINE explicit Handle(T* object) : Handle(object, object->GetIsolate()) {}
98 V8_INLINE Handle(T* object, Isolate* isolate) : HandleBase(object, isolate) {}
99
100 // Allocate a new handle for the object, do not canonicalize.
101 V8_INLINE static Handle<T> New(T* object, Isolate* isolate);
102
103 // Constructor for handling automatic up casting.
104 // Ex. Handle<JSFunction> can be passed when Handle<Object> is expected.
105 template <typename S>
106 V8_INLINE Handle(Handle<S> handle)
107 : HandleBase(handle) {
108 T* a = nullptr;
109 S* b = nullptr;
110 a = b; // Fake assignment to enforce type checks.
111 USE(a);
112 }
113
114 V8_INLINE T* operator->() const { return operator*(); }
115
116 // Provides the C++ dereference operator.
117 V8_INLINE T* operator*() const {
118 return reinterpret_cast<T*>(HandleBase::operator*());
119 }
120
121 // Returns the address to where the raw pointer is stored.
122 V8_INLINE T** location() const {
123 return reinterpret_cast<T**>(HandleBase::location());
124 }
125
126 template <typename S>
127 static const Handle<T> cast(Handle<S> that) {
128 T::cast(*reinterpret_cast<T**>(that.location_));
129 return Handle<T>(reinterpret_cast<T**>(that.location_));
130 }
131
132 // TODO(yangguo): Values that contain empty handles should be declared as
133 // MaybeHandle to force validation before being used as handles.
134 static const Handle<T> null() { return Handle<T>(); }
135
136 // Provide function object for location equality comparison.
137 struct equal_to : public std::binary_function<Handle<T>, Handle<T>, bool> {
138 V8_INLINE bool operator()(Handle<T> lhs, Handle<T> rhs) const {
Ben Murdochc5610432016-08-08 18:44:38 +0100139 return lhs.address() == rhs.address();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000140 }
141 };
142
143 // Provide function object for location hashing.
144 struct hash : public std::unary_function<Handle<T>, size_t> {
145 V8_INLINE size_t operator()(Handle<T> const& handle) const {
Ben Murdochc5610432016-08-08 18:44:38 +0100146 return base::hash<void*>()(handle.address());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000147 }
148 };
149
150 private:
151 // Handles of different classes are allowed to access each other's location_.
152 template <typename>
153 friend class Handle;
154 // MaybeHandle is allowed to access location_.
155 template <typename>
156 friend class MaybeHandle;
157};
158
159template <typename T>
160inline std::ostream& operator<<(std::ostream& os, Handle<T> handle);
161
162template <typename T>
163V8_INLINE Handle<T> handle(T* object, Isolate* isolate) {
164 return Handle<T>(object, isolate);
165}
166
167template <typename T>
168V8_INLINE Handle<T> handle(T* object) {
169 return Handle<T>(object);
170}
171
172
173// ----------------------------------------------------------------------------
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000174// A Handle can be converted into a MaybeHandle. Converting a MaybeHandle
175// into a Handle requires checking that it does not point to NULL. This
176// ensures NULL checks before use.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000177//
178// Also note that Handles do not provide default equality comparison or hashing
179// operators on purpose. Such operators would be misleading, because intended
180// semantics is ambiguous between Handle location and object identity.
181template <typename T>
182class MaybeHandle final {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000183 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000184 V8_INLINE MaybeHandle() {}
185 V8_INLINE ~MaybeHandle() {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000186
187 // Constructor for handling automatic up casting from Handle.
188 // Ex. Handle<JSArray> can be passed when MaybeHandle<Object> is expected.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000189 template <typename S>
190 V8_INLINE MaybeHandle(Handle<S> handle)
191 : location_(reinterpret_cast<T**>(handle.location_)) {
192 T* a = nullptr;
193 S* b = nullptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000194 a = b; // Fake assignment to enforce type checks.
195 USE(a);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000196 }
197
198 // Constructor for handling automatic up casting.
199 // Ex. MaybeHandle<JSArray> can be passed when Handle<Object> is expected.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000200 template <typename S>
201 V8_INLINE MaybeHandle(MaybeHandle<S> maybe_handle)
202 : location_(reinterpret_cast<T**>(maybe_handle.location_)) {
203 T* a = nullptr;
204 S* b = nullptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000205 a = b; // Fake assignment to enforce type checks.
206 USE(a);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000207 }
208
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000209 V8_INLINE void Assert() const { DCHECK_NOT_NULL(location_); }
210 V8_INLINE void Check() const { CHECK_NOT_NULL(location_); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000211
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000212 V8_INLINE Handle<T> ToHandleChecked() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000213 Check();
214 return Handle<T>(location_);
215 }
216
217 // Convert to a Handle with a type that can be upcasted to.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000218 template <typename S>
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400219 V8_INLINE bool ToHandle(Handle<S>* out) const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000220 if (location_ == nullptr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000221 *out = Handle<T>::null();
222 return false;
223 } else {
224 *out = Handle<T>(location_);
225 return true;
226 }
227 }
228
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000229 bool is_null() const { return location_ == nullptr; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000230
231 protected:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000232 T** location_ = nullptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000233
234 // MaybeHandles of different classes are allowed to access each
235 // other's location_.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000236 template <typename>
237 friend class MaybeHandle;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000238};
239
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000240
Steve Blocka7e24c12009-10-30 11:49:00 +0000241// ----------------------------------------------------------------------------
Steve Blocka7e24c12009-10-30 11:49:00 +0000242// A stack-allocated class that governs a number of local handles.
243// After a handle scope has been created, all local handles will be
244// allocated within that handle scope until either the handle scope is
245// deleted or another handle scope is created. If there is already a
246// handle scope and a new one is created, all allocations will take
247// place in the new handle scope until it is deleted. After that,
248// new handles will again be allocated in the original handle scope.
249//
250// After the handle scope of a local handle has been deleted the
251// garbage collector will no longer track the object stored in the
252// handle and may deallocate it. The behavior of accessing a handle
253// for which the handle scope has been deleted is undefined.
254class HandleScope {
255 public:
Steve Block44f0eee2011-05-26 01:26:41 +0100256 explicit inline HandleScope(Isolate* isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000257
Steve Block44f0eee2011-05-26 01:26:41 +0100258 inline ~HandleScope();
Steve Blocka7e24c12009-10-30 11:49:00 +0000259
260 // Counts the number of allocated handles.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000261 static int NumberOfHandles(Isolate* isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000262
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000263 // Create a new handle or lookup a canonical handle.
264 V8_INLINE static Object** GetHandle(Isolate* isolate, Object* value);
265
Steve Blocka7e24c12009-10-30 11:49:00 +0000266 // Creates a new handle with the given value.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000267 V8_INLINE static Object** CreateHandle(Isolate* isolate, Object* value);
Steve Blocka7e24c12009-10-30 11:49:00 +0000268
Steve Blockd0582a62009-12-15 09:54:21 +0000269 // Deallocates any extensions used by the current scope.
Steve Block44f0eee2011-05-26 01:26:41 +0100270 static void DeleteExtensions(Isolate* isolate);
Steve Blockd0582a62009-12-15 09:54:21 +0000271
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000272 static Address current_next_address(Isolate* isolate);
273 static Address current_limit_address(Isolate* isolate);
274 static Address current_level_address(Isolate* isolate);
Steve Blockd0582a62009-12-15 09:54:21 +0000275
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100276 // Closes the HandleScope (invalidating all handles
277 // created in the scope of the HandleScope) and returns
278 // a Handle backed by the parent scope holding the
279 // value of the argument handle.
280 template <typename T>
Steve Block44f0eee2011-05-26 01:26:41 +0100281 Handle<T> CloseAndEscape(Handle<T> handle_value);
282
283 Isolate* isolate() { return isolate_; }
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100284
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000285 // Limit for number of handles with --check-handle-count. This is
286 // large enough to compile natives and pass unit tests with some
287 // slack for future changes to natives.
288 static const int kCheckHandleThreshold = 30 * 1024;
289
Steve Blocka7e24c12009-10-30 11:49:00 +0000290 private:
291 // Prevent heap allocation or illegal handle scopes.
292 HandleScope(const HandleScope&);
293 void operator=(const HandleScope&);
294 void* operator new(size_t size);
295 void operator delete(void* size_t);
296
Steve Block44f0eee2011-05-26 01:26:41 +0100297 Isolate* isolate_;
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100298 Object** prev_next_;
299 Object** prev_limit_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000300
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000301 // Close the handle scope resetting limits to a previous state.
302 static inline void CloseScope(Isolate* isolate,
303 Object** prev_next,
304 Object** prev_limit);
Steve Blocka7e24c12009-10-30 11:49:00 +0000305
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000306 // Extend the handle scope making room for more handles.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000307 static Object** Extend(Isolate* isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000308
309#ifdef ENABLE_HANDLE_ZAPPING
Steve Blocka7e24c12009-10-30 11:49:00 +0000310 // Zaps the handles in the half-open interval [start, end).
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000311 static void ZapRange(Object** start, Object** end);
312#endif
Steve Blocka7e24c12009-10-30 11:49:00 +0000313
314 friend class v8::HandleScope;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000315 friend class DeferredHandles;
316 friend class DeferredHandleScope;
317 friend class HandleScopeImplementer;
318 friend class Isolate;
Steve Blocka7e24c12009-10-30 11:49:00 +0000319};
320
321
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000322// Forward declarations for CanonicalHandleScope.
323template <typename V>
324class IdentityMap;
325class RootIndexMap;
Steve Blocka7e24c12009-10-30 11:49:00 +0000326
327
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000328// A CanonicalHandleScope does not open a new HandleScope. It changes the
329// existing HandleScope so that Handles created within are canonicalized.
330// This does not apply to nested inner HandleScopes unless a nested
331// CanonicalHandleScope is introduced. Handles are only canonicalized within
332// the same CanonicalHandleScope, but not across nested ones.
333class CanonicalHandleScope final {
334 public:
335 explicit CanonicalHandleScope(Isolate* isolate);
336 ~CanonicalHandleScope();
337
338 private:
339 Object** Lookup(Object* object);
340
341 Isolate* isolate_;
342 Zone zone_;
343 RootIndexMap* root_index_map_;
344 IdentityMap<Object**>* identity_map_;
345 // Ordinary nested handle scopes within the current one are not canonical.
346 int canonical_level_;
347 // We may have nested canonical scopes. Handles are canonical within each one.
348 CanonicalHandleScope* prev_canonical_scope_;
349
350 friend class HandleScope;
351};
352
353
354class DeferredHandleScope final {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000355 public:
356 explicit DeferredHandleScope(Isolate* isolate);
357 // The DeferredHandles object returned stores the Handles created
358 // since the creation of this DeferredHandleScope. The Handles are
359 // alive as long as the DeferredHandles object is alive.
360 DeferredHandles* Detach();
361 ~DeferredHandleScope();
Steve Blocka7e24c12009-10-30 11:49:00 +0000362
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000363 private:
364 Object** prev_limit_;
365 Object** prev_next_;
366 HandleScopeImplementer* impl_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000367
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000368#ifdef DEBUG
369 bool handles_detached_;
370 int prev_level_;
371#endif
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100372
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000373 friend class HandleScopeImplementer;
374};
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000375
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000376
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000377// Seal off the current HandleScope so that new handles can only be created
378// if a new HandleScope is entered.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000379class SealHandleScope final {
Steve Blocka7e24c12009-10-30 11:49:00 +0000380 public:
381#ifndef DEBUG
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000382 explicit SealHandleScope(Isolate* isolate) {}
383 ~SealHandleScope() {}
Steve Blocka7e24c12009-10-30 11:49:00 +0000384#else
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000385 explicit inline SealHandleScope(Isolate* isolate);
386 inline ~SealHandleScope();
Steve Blocka7e24c12009-10-30 11:49:00 +0000387 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000388 Isolate* isolate_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000389 Object** prev_limit_;
390 int prev_sealed_level_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000391#endif
392};
393
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000394
395struct HandleScopeData final {
396 Object** next;
397 Object** limit;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000398 int level;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000399 int sealed_level;
400 CanonicalHandleScope* canonical_scope;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000401
402 void Initialize() {
403 next = limit = NULL;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000404 sealed_level = level = 0;
405 canonical_scope = NULL;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000406 }
407};
408
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000409} // namespace internal
410} // namespace v8
Steve Blocka7e24c12009-10-30 11:49:00 +0000411
412#endif // V8_HANDLES_H_