blob: eb57f0e26089383c9d7fe9f57a8cba5f41a111e2 [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 Murdochb8a8cc12014-11-26 15:28:44 +00008#include "src/objects.h"
Steve Blocka7e24c12009-10-30 11:49:00 +00009
10namespace v8 {
11namespace internal {
12
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013// A Handle can be converted into a MaybeHandle. Converting a MaybeHandle
14// into a Handle requires checking that it does not point to NULL. This
15// ensures NULL checks before use.
16// Do not use MaybeHandle as argument type.
17
18template<typename T>
19class MaybeHandle {
20 public:
21 INLINE(MaybeHandle()) : location_(NULL) { }
22
23 // Constructor for handling automatic up casting from Handle.
24 // Ex. Handle<JSArray> can be passed when MaybeHandle<Object> is expected.
25 template <class S> MaybeHandle(Handle<S> handle) {
26#ifdef DEBUG
27 T* a = NULL;
28 S* b = NULL;
29 a = b; // Fake assignment to enforce type checks.
30 USE(a);
31#endif
32 this->location_ = reinterpret_cast<T**>(handle.location());
33 }
34
35 // Constructor for handling automatic up casting.
36 // Ex. MaybeHandle<JSArray> can be passed when Handle<Object> is expected.
37 template <class S> MaybeHandle(MaybeHandle<S> maybe_handle) {
38#ifdef DEBUG
39 T* a = NULL;
40 S* b = NULL;
41 a = b; // Fake assignment to enforce type checks.
42 USE(a);
43#endif
44 location_ = reinterpret_cast<T**>(maybe_handle.location_);
45 }
46
47 INLINE(void Assert() const) { DCHECK(location_ != NULL); }
48 INLINE(void Check() const) { CHECK(location_ != NULL); }
49
50 INLINE(Handle<T> ToHandleChecked()) const {
51 Check();
52 return Handle<T>(location_);
53 }
54
55 // Convert to a Handle with a type that can be upcasted to.
Emily Bernierd0a1eb72015-03-24 16:35:39 -040056 template <class S>
57 V8_INLINE bool ToHandle(Handle<S>* out) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000058 if (location_ == NULL) {
59 *out = Handle<T>::null();
60 return false;
61 } else {
62 *out = Handle<T>(location_);
63 return true;
64 }
65 }
66
67 bool is_null() const { return location_ == NULL; }
68
69 protected:
70 T** location_;
71
72 // MaybeHandles of different classes are allowed to access each
73 // other's location_.
74 template<class S> friend class MaybeHandle;
75};
76
Steve Blocka7e24c12009-10-30 11:49:00 +000077// ----------------------------------------------------------------------------
78// A Handle provides a reference to an object that survives relocation by
79// the garbage collector.
80// Handles are only valid within a HandleScope.
81// When a handle is created for an object a cell is allocated in the heap.
82
Ben Murdoche0cee9b2011-05-25 10:26:03 +010083template<typename T>
Steve Blocka7e24c12009-10-30 11:49:00 +000084class Handle {
85 public:
Steve Block6ded16b2010-05-10 14:33:55 +010086 INLINE(explicit Handle(T** location)) { location_ = location; }
Steve Blocka7e24c12009-10-30 11:49:00 +000087 INLINE(explicit Handle(T* obj));
Steve Block44f0eee2011-05-26 01:26:41 +010088 INLINE(Handle(T* obj, Isolate* isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +000089
Ben Murdochb8a8cc12014-11-26 15:28:44 +000090 // TODO(yangguo): Values that contain empty handles should be declared as
91 // MaybeHandle to force validation before being used as handles.
92 INLINE(Handle()) : location_(NULL) { }
Steve Blocka7e24c12009-10-30 11:49:00 +000093
94 // Constructor for handling automatic up casting.
95 // Ex. Handle<JSFunction> can be passed when Handle<Object> is expected.
96 template <class S> Handle(Handle<S> handle) {
97#ifdef DEBUG
98 T* a = NULL;
99 S* b = NULL;
100 a = b; // Fake assignment to enforce type checks.
101 USE(a);
102#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000103 location_ = reinterpret_cast<T**>(handle.location_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000104 }
105
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000106 INLINE(T* operator->() const) { return operator*(); }
Steve Blocka7e24c12009-10-30 11:49:00 +0000107
108 // Check if this handle refers to the exact same object as the other handle.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000109 INLINE(bool is_identical_to(const Handle<T> other) const);
Steve Blocka7e24c12009-10-30 11:49:00 +0000110
111 // Provides the C++ dereference operator.
112 INLINE(T* operator*() const);
113
114 // Returns the address to where the raw pointer is stored.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000115 INLINE(T** location() const);
Steve Blocka7e24c12009-10-30 11:49:00 +0000116
117 template <class S> static Handle<T> cast(Handle<S> that) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000118 T::cast(*reinterpret_cast<T**>(that.location_));
119 return Handle<T>(reinterpret_cast<T**>(that.location_));
Steve Blocka7e24c12009-10-30 11:49:00 +0000120 }
121
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000122 // TODO(yangguo): Values that contain empty handles should be declared as
123 // MaybeHandle to force validation before being used as handles.
Steve Blocka7e24c12009-10-30 11:49:00 +0000124 static Handle<T> null() { return Handle<T>(); }
Steve Block44f0eee2011-05-26 01:26:41 +0100125 bool is_null() const { return location_ == NULL; }
Steve Blocka7e24c12009-10-30 11:49:00 +0000126
127 // Closes the given scope, but lets this handle escape. See
128 // implementation in api.h.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000129 inline Handle<T> EscapeFrom(v8::EscapableHandleScope* scope);
130
131#ifdef DEBUG
132 enum DereferenceCheckMode { INCLUDE_DEFERRED_CHECK, NO_DEFERRED_CHECK };
133
134 bool IsDereferenceAllowed(DereferenceCheckMode mode) const;
135#endif // DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +0000136
137 private:
138 T** location_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000139
140 // Handles of different classes are allowed to access each other's location_.
141 template<class S> friend class Handle;
Steve Blocka7e24c12009-10-30 11:49:00 +0000142};
143
144
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000145// Convenience wrapper.
146template<class T>
147inline Handle<T> handle(T* t, Isolate* isolate) {
148 return Handle<T>(t, isolate);
149}
150
151
152// Convenience wrapper.
153template<class T>
154inline Handle<T> handle(T* t) {
155 return Handle<T>(t, t->GetIsolate());
156}
157
158
159// Key comparison function for Map handles.
160inline bool operator<(const Handle<Map>& lhs, const Handle<Map>& rhs) {
161 // This is safe because maps don't move.
162 return *lhs < *rhs;
163}
164
165
166class DeferredHandles;
167class HandleScopeImplementer;
168
169
Steve Blocka7e24c12009-10-30 11:49:00 +0000170// A stack-allocated class that governs a number of local handles.
171// After a handle scope has been created, all local handles will be
172// allocated within that handle scope until either the handle scope is
173// deleted or another handle scope is created. If there is already a
174// handle scope and a new one is created, all allocations will take
175// place in the new handle scope until it is deleted. After that,
176// new handles will again be allocated in the original handle scope.
177//
178// After the handle scope of a local handle has been deleted the
179// garbage collector will no longer track the object stored in the
180// handle and may deallocate it. The behavior of accessing a handle
181// for which the handle scope has been deleted is undefined.
182class HandleScope {
183 public:
Steve Block44f0eee2011-05-26 01:26:41 +0100184 explicit inline HandleScope(Isolate* isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000185
Steve Block44f0eee2011-05-26 01:26:41 +0100186 inline ~HandleScope();
Steve Blocka7e24c12009-10-30 11:49:00 +0000187
188 // Counts the number of allocated handles.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000189 static int NumberOfHandles(Isolate* isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000190
191 // Creates a new handle with the given value.
192 template <typename T>
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000193 static inline T** CreateHandle(Isolate* isolate, T* value);
Steve Blocka7e24c12009-10-30 11:49:00 +0000194
Steve Blockd0582a62009-12-15 09:54:21 +0000195 // Deallocates any extensions used by the current scope.
Steve Block44f0eee2011-05-26 01:26:41 +0100196 static void DeleteExtensions(Isolate* isolate);
Steve Blockd0582a62009-12-15 09:54:21 +0000197
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000198 static Address current_next_address(Isolate* isolate);
199 static Address current_limit_address(Isolate* isolate);
200 static Address current_level_address(Isolate* isolate);
Steve Blockd0582a62009-12-15 09:54:21 +0000201
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100202 // Closes the HandleScope (invalidating all handles
203 // created in the scope of the HandleScope) and returns
204 // a Handle backed by the parent scope holding the
205 // value of the argument handle.
206 template <typename T>
Steve Block44f0eee2011-05-26 01:26:41 +0100207 Handle<T> CloseAndEscape(Handle<T> handle_value);
208
209 Isolate* isolate() { return isolate_; }
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100210
Steve Blocka7e24c12009-10-30 11:49:00 +0000211 private:
212 // Prevent heap allocation or illegal handle scopes.
213 HandleScope(const HandleScope&);
214 void operator=(const HandleScope&);
215 void* operator new(size_t size);
216 void operator delete(void* size_t);
217
Steve Block44f0eee2011-05-26 01:26:41 +0100218 Isolate* isolate_;
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100219 Object** prev_next_;
220 Object** prev_limit_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000221
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000222 // Close the handle scope resetting limits to a previous state.
223 static inline void CloseScope(Isolate* isolate,
224 Object** prev_next,
225 Object** prev_limit);
Steve Blocka7e24c12009-10-30 11:49:00 +0000226
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000227 // Extend the handle scope making room for more handles.
228 static internal::Object** Extend(Isolate* isolate);
229
230#ifdef ENABLE_HANDLE_ZAPPING
Steve Blocka7e24c12009-10-30 11:49:00 +0000231 // Zaps the handles in the half-open interval [start, end).
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000232 static void ZapRange(Object** start, Object** end);
233#endif
Steve Blocka7e24c12009-10-30 11:49:00 +0000234
235 friend class v8::HandleScope;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000236 friend class v8::internal::DeferredHandles;
237 friend class v8::internal::HandleScopeImplementer;
238 friend class v8::internal::Isolate;
Steve Blocka7e24c12009-10-30 11:49:00 +0000239};
240
241
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000242class DeferredHandles;
Steve Blocka7e24c12009-10-30 11:49:00 +0000243
244
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000245class DeferredHandleScope {
246 public:
247 explicit DeferredHandleScope(Isolate* isolate);
248 // The DeferredHandles object returned stores the Handles created
249 // since the creation of this DeferredHandleScope. The Handles are
250 // alive as long as the DeferredHandles object is alive.
251 DeferredHandles* Detach();
252 ~DeferredHandleScope();
Steve Blocka7e24c12009-10-30 11:49:00 +0000253
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000254 private:
255 Object** prev_limit_;
256 Object** prev_next_;
257 HandleScopeImplementer* impl_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000258
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000259#ifdef DEBUG
260 bool handles_detached_;
261 int prev_level_;
262#endif
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100263
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000264 friend class HandleScopeImplementer;
265};
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000266
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000267
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000268// Seal off the current HandleScope so that new handles can only be created
269// if a new HandleScope is entered.
270class SealHandleScope BASE_EMBEDDED {
Steve Blocka7e24c12009-10-30 11:49:00 +0000271 public:
272#ifndef DEBUG
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000273 explicit SealHandleScope(Isolate* isolate) {}
274 ~SealHandleScope() {}
Steve Blocka7e24c12009-10-30 11:49:00 +0000275#else
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000276 explicit inline SealHandleScope(Isolate* isolate);
277 inline ~SealHandleScope();
Steve Blocka7e24c12009-10-30 11:49:00 +0000278 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000279 Isolate* isolate_;
280 Object** limit_;
John Reck59135872010-11-02 12:39:01 -0700281 int level_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000282#endif
283};
284
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000285struct HandleScopeData {
286 internal::Object** next;
287 internal::Object** limit;
288 int level;
289
290 void Initialize() {
291 next = limit = NULL;
292 level = 0;
293 }
294};
295
Steve Blocka7e24c12009-10-30 11:49:00 +0000296} } // namespace v8::internal
297
298#endif // V8_HANDLES_H_