blob: 1f97d6ff7e6d95c76b521baf45938e5f1c5f8243 [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
46 protected:
47 // Provides the C++ dereference operator.
48 V8_INLINE Object* operator*() const {
49 SLOW_DCHECK(IsDereferenceAllowed(INCLUDE_DEFERRED_CHECK));
50 return *location_;
51 }
52
53 // Returns the address to where the raw pointer is stored.
54 V8_INLINE Object** location() const {
55 SLOW_DCHECK(location_ == nullptr ||
56 IsDereferenceAllowed(INCLUDE_DEFERRED_CHECK));
57 return location_;
58 }
59
60 enum DereferenceCheckMode { INCLUDE_DEFERRED_CHECK, NO_DEFERRED_CHECK };
61#ifdef DEBUG
62 bool IsDereferenceAllowed(DereferenceCheckMode mode) const;
63#else
64 V8_INLINE
65 bool IsDereferenceAllowed(DereferenceCheckMode mode) const { return true; }
66#endif // DEBUG
67
68 Object** location_;
69};
70
71
72// ----------------------------------------------------------------------------
73// A Handle provides a reference to an object that survives relocation by
74// the garbage collector.
75//
76// Handles are only valid within a HandleScope. When a handle is created
77// for an object a cell is allocated in the current HandleScope.
78//
79// Also note that Handles do not provide default equality comparison or hashing
80// operators on purpose. Such operators would be misleading, because intended
81// semantics is ambiguous between Handle location and object identity. Instead
82// use either {is_identical_to} or {location} explicitly.
83template <typename T>
84class Handle final : public HandleBase {
85 public:
86 V8_INLINE explicit Handle(T** location = nullptr)
87 : HandleBase(reinterpret_cast<Object**>(location)) {
88 Object* a = nullptr;
89 T* b = nullptr;
90 a = b; // Fake assignment to enforce type checks.
91 USE(a);
92 }
93 V8_INLINE explicit Handle(T* object) : Handle(object, object->GetIsolate()) {}
94 V8_INLINE Handle(T* object, Isolate* isolate) : HandleBase(object, isolate) {}
95
96 // Allocate a new handle for the object, do not canonicalize.
97 V8_INLINE static Handle<T> New(T* object, Isolate* isolate);
98
99 // Constructor for handling automatic up casting.
100 // Ex. Handle<JSFunction> can be passed when Handle<Object> is expected.
101 template <typename S>
102 V8_INLINE Handle(Handle<S> handle)
103 : HandleBase(handle) {
104 T* a = nullptr;
105 S* b = nullptr;
106 a = b; // Fake assignment to enforce type checks.
107 USE(a);
108 }
109
110 V8_INLINE T* operator->() const { return operator*(); }
111
112 // Provides the C++ dereference operator.
113 V8_INLINE T* operator*() const {
114 return reinterpret_cast<T*>(HandleBase::operator*());
115 }
116
117 // Returns the address to where the raw pointer is stored.
118 V8_INLINE T** location() const {
119 return reinterpret_cast<T**>(HandleBase::location());
120 }
121
122 template <typename S>
123 static const Handle<T> cast(Handle<S> that) {
124 T::cast(*reinterpret_cast<T**>(that.location_));
125 return Handle<T>(reinterpret_cast<T**>(that.location_));
126 }
127
128 // TODO(yangguo): Values that contain empty handles should be declared as
129 // MaybeHandle to force validation before being used as handles.
130 static const Handle<T> null() { return Handle<T>(); }
131
132 // Provide function object for location equality comparison.
133 struct equal_to : public std::binary_function<Handle<T>, Handle<T>, bool> {
134 V8_INLINE bool operator()(Handle<T> lhs, Handle<T> rhs) const {
135 return lhs.location() == rhs.location();
136 }
137 };
138
139 // Provide function object for location hashing.
140 struct hash : public std::unary_function<Handle<T>, size_t> {
141 V8_INLINE size_t operator()(Handle<T> const& handle) const {
142 return base::hash<void*>()(handle.location());
143 }
144 };
145
146 private:
147 // Handles of different classes are allowed to access each other's location_.
148 template <typename>
149 friend class Handle;
150 // MaybeHandle is allowed to access location_.
151 template <typename>
152 friend class MaybeHandle;
153};
154
155template <typename T>
156inline std::ostream& operator<<(std::ostream& os, Handle<T> handle);
157
158template <typename T>
159V8_INLINE Handle<T> handle(T* object, Isolate* isolate) {
160 return Handle<T>(object, isolate);
161}
162
163template <typename T>
164V8_INLINE Handle<T> handle(T* object) {
165 return Handle<T>(object);
166}
167
168
169// ----------------------------------------------------------------------------
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000170// A Handle can be converted into a MaybeHandle. Converting a MaybeHandle
171// into a Handle requires checking that it does not point to NULL. This
172// ensures NULL checks before use.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000173//
174// Also note that Handles do not provide default equality comparison or hashing
175// operators on purpose. Such operators would be misleading, because intended
176// semantics is ambiguous between Handle location and object identity.
177template <typename T>
178class MaybeHandle final {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000179 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000180 V8_INLINE MaybeHandle() {}
181 V8_INLINE ~MaybeHandle() {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000182
183 // Constructor for handling automatic up casting from Handle.
184 // Ex. Handle<JSArray> can be passed when MaybeHandle<Object> is expected.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000185 template <typename S>
186 V8_INLINE MaybeHandle(Handle<S> handle)
187 : location_(reinterpret_cast<T**>(handle.location_)) {
188 T* a = nullptr;
189 S* b = nullptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000190 a = b; // Fake assignment to enforce type checks.
191 USE(a);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000192 }
193
194 // Constructor for handling automatic up casting.
195 // Ex. MaybeHandle<JSArray> can be passed when Handle<Object> is expected.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000196 template <typename S>
197 V8_INLINE MaybeHandle(MaybeHandle<S> maybe_handle)
198 : location_(reinterpret_cast<T**>(maybe_handle.location_)) {
199 T* a = nullptr;
200 S* b = nullptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000201 a = b; // Fake assignment to enforce type checks.
202 USE(a);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000203 }
204
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000205 V8_INLINE void Assert() const { DCHECK_NOT_NULL(location_); }
206 V8_INLINE void Check() const { CHECK_NOT_NULL(location_); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000207
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000208 V8_INLINE Handle<T> ToHandleChecked() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000209 Check();
210 return Handle<T>(location_);
211 }
212
213 // Convert to a Handle with a type that can be upcasted to.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000214 template <typename S>
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400215 V8_INLINE bool ToHandle(Handle<S>* out) const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000216 if (location_ == nullptr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000217 *out = Handle<T>::null();
218 return false;
219 } else {
220 *out = Handle<T>(location_);
221 return true;
222 }
223 }
224
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000225 bool is_null() const { return location_ == nullptr; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000226
227 protected:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000228 T** location_ = nullptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000229
230 // MaybeHandles of different classes are allowed to access each
231 // other's location_.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000232 template <typename>
233 friend class MaybeHandle;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000234};
235
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000236
Steve Blocka7e24c12009-10-30 11:49:00 +0000237// ----------------------------------------------------------------------------
Steve Blocka7e24c12009-10-30 11:49:00 +0000238// A stack-allocated class that governs a number of local handles.
239// After a handle scope has been created, all local handles will be
240// allocated within that handle scope until either the handle scope is
241// deleted or another handle scope is created. If there is already a
242// handle scope and a new one is created, all allocations will take
243// place in the new handle scope until it is deleted. After that,
244// new handles will again be allocated in the original handle scope.
245//
246// After the handle scope of a local handle has been deleted the
247// garbage collector will no longer track the object stored in the
248// handle and may deallocate it. The behavior of accessing a handle
249// for which the handle scope has been deleted is undefined.
250class HandleScope {
251 public:
Steve Block44f0eee2011-05-26 01:26:41 +0100252 explicit inline HandleScope(Isolate* isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000253
Steve Block44f0eee2011-05-26 01:26:41 +0100254 inline ~HandleScope();
Steve Blocka7e24c12009-10-30 11:49:00 +0000255
256 // Counts the number of allocated handles.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000257 static int NumberOfHandles(Isolate* isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000258
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000259 // Create a new handle or lookup a canonical handle.
260 V8_INLINE static Object** GetHandle(Isolate* isolate, Object* value);
261
Steve Blocka7e24c12009-10-30 11:49:00 +0000262 // Creates a new handle with the given value.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000263 V8_INLINE static Object** CreateHandle(Isolate* isolate, Object* value);
Steve Blocka7e24c12009-10-30 11:49:00 +0000264
Steve Blockd0582a62009-12-15 09:54:21 +0000265 // Deallocates any extensions used by the current scope.
Steve Block44f0eee2011-05-26 01:26:41 +0100266 static void DeleteExtensions(Isolate* isolate);
Steve Blockd0582a62009-12-15 09:54:21 +0000267
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000268 static Address current_next_address(Isolate* isolate);
269 static Address current_limit_address(Isolate* isolate);
270 static Address current_level_address(Isolate* isolate);
Steve Blockd0582a62009-12-15 09:54:21 +0000271
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100272 // Closes the HandleScope (invalidating all handles
273 // created in the scope of the HandleScope) and returns
274 // a Handle backed by the parent scope holding the
275 // value of the argument handle.
276 template <typename T>
Steve Block44f0eee2011-05-26 01:26:41 +0100277 Handle<T> CloseAndEscape(Handle<T> handle_value);
278
279 Isolate* isolate() { return isolate_; }
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100280
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000281 // Limit for number of handles with --check-handle-count. This is
282 // large enough to compile natives and pass unit tests with some
283 // slack for future changes to natives.
284 static const int kCheckHandleThreshold = 30 * 1024;
285
Steve Blocka7e24c12009-10-30 11:49:00 +0000286 private:
287 // Prevent heap allocation or illegal handle scopes.
288 HandleScope(const HandleScope&);
289 void operator=(const HandleScope&);
290 void* operator new(size_t size);
291 void operator delete(void* size_t);
292
Steve Block44f0eee2011-05-26 01:26:41 +0100293 Isolate* isolate_;
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100294 Object** prev_next_;
295 Object** prev_limit_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000296
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000297 // Close the handle scope resetting limits to a previous state.
298 static inline void CloseScope(Isolate* isolate,
299 Object** prev_next,
300 Object** prev_limit);
Steve Blocka7e24c12009-10-30 11:49:00 +0000301
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000302 // Extend the handle scope making room for more handles.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000303 static Object** Extend(Isolate* isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000304
305#ifdef ENABLE_HANDLE_ZAPPING
Steve Blocka7e24c12009-10-30 11:49:00 +0000306 // Zaps the handles in the half-open interval [start, end).
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000307 static void ZapRange(Object** start, Object** end);
308#endif
Steve Blocka7e24c12009-10-30 11:49:00 +0000309
310 friend class v8::HandleScope;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000311 friend class DeferredHandles;
312 friend class DeferredHandleScope;
313 friend class HandleScopeImplementer;
314 friend class Isolate;
Steve Blocka7e24c12009-10-30 11:49:00 +0000315};
316
317
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000318// Forward declarations for CanonicalHandleScope.
319template <typename V>
320class IdentityMap;
321class RootIndexMap;
Steve Blocka7e24c12009-10-30 11:49:00 +0000322
323
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000324// A CanonicalHandleScope does not open a new HandleScope. It changes the
325// existing HandleScope so that Handles created within are canonicalized.
326// This does not apply to nested inner HandleScopes unless a nested
327// CanonicalHandleScope is introduced. Handles are only canonicalized within
328// the same CanonicalHandleScope, but not across nested ones.
329class CanonicalHandleScope final {
330 public:
331 explicit CanonicalHandleScope(Isolate* isolate);
332 ~CanonicalHandleScope();
333
334 private:
335 Object** Lookup(Object* object);
336
337 Isolate* isolate_;
338 Zone zone_;
339 RootIndexMap* root_index_map_;
340 IdentityMap<Object**>* identity_map_;
341 // Ordinary nested handle scopes within the current one are not canonical.
342 int canonical_level_;
343 // We may have nested canonical scopes. Handles are canonical within each one.
344 CanonicalHandleScope* prev_canonical_scope_;
345
346 friend class HandleScope;
347};
348
349
350class DeferredHandleScope final {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000351 public:
352 explicit DeferredHandleScope(Isolate* isolate);
353 // The DeferredHandles object returned stores the Handles created
354 // since the creation of this DeferredHandleScope. The Handles are
355 // alive as long as the DeferredHandles object is alive.
356 DeferredHandles* Detach();
357 ~DeferredHandleScope();
Steve Blocka7e24c12009-10-30 11:49:00 +0000358
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000359 private:
360 Object** prev_limit_;
361 Object** prev_next_;
362 HandleScopeImplementer* impl_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000363
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000364#ifdef DEBUG
365 bool handles_detached_;
366 int prev_level_;
367#endif
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100368
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000369 friend class HandleScopeImplementer;
370};
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000371
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000372
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000373// Seal off the current HandleScope so that new handles can only be created
374// if a new HandleScope is entered.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000375class SealHandleScope final {
Steve Blocka7e24c12009-10-30 11:49:00 +0000376 public:
377#ifndef DEBUG
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000378 explicit SealHandleScope(Isolate* isolate) {}
379 ~SealHandleScope() {}
Steve Blocka7e24c12009-10-30 11:49:00 +0000380#else
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000381 explicit inline SealHandleScope(Isolate* isolate);
382 inline ~SealHandleScope();
Steve Blocka7e24c12009-10-30 11:49:00 +0000383 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000384 Isolate* isolate_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000385 Object** prev_limit_;
386 int prev_sealed_level_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000387#endif
388};
389
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000390
391struct HandleScopeData final {
392 Object** next;
393 Object** limit;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000394 int level;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000395 int sealed_level;
396 CanonicalHandleScope* canonical_scope;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000397
398 void Initialize() {
399 next = limit = NULL;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000400 sealed_level = level = 0;
401 canonical_scope = NULL;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000402 }
403};
404
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000405} // namespace internal
406} // namespace v8
Steve Blocka7e24c12009-10-30 11:49:00 +0000407
408#endif // V8_HANDLES_H_