Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(324)

Side by Side Diff: src/handles.h

Issue 1128533002: [handles] Sanitize Handle and friends. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Lower kTargetRecursionDepth. Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/api.cc ('k') | src/handles.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef V8_HANDLES_H_ 5 #ifndef V8_HANDLES_H_
6 #define V8_HANDLES_H_ 6 #define V8_HANDLES_H_
7 7
8 #include "src/objects.h" 8 #include "src/objects.h"
9 9
10 namespace v8 { 10 namespace v8 {
11 namespace internal { 11 namespace internal {
12 12
13 // Forward declarations.
14 class DeferredHandles;
15 class HandleScopeImplementer;
16
17
18 // ----------------------------------------------------------------------------
19 // Base class for Handle instantiations. Don't use directly.
20 class HandleBase {
21 public:
22 V8_INLINE explicit HandleBase(Object** location) : location_(location) {}
23 V8_INLINE explicit HandleBase(Object* object, Isolate* isolate);
24
25 // Check if this handle refers to the exact same object as the other handle.
26 V8_INLINE bool is_identical_to(const HandleBase that) const {
27 // Dereferencing deferred handles to check object equality is safe.
28 SLOW_DCHECK((this->location_ == NULL ||
29 this->IsDereferenceAllowed(NO_DEFERRED_CHECK)) &&
30 (that.location_ == NULL ||
31 that.IsDereferenceAllowed(NO_DEFERRED_CHECK)));
32 if (this->location_ == that.location_) return true;
33 if (this->location_ == NULL || that.location_ == NULL) return false;
34 return *this->location_ == *that.location_;
35 }
36
37 V8_INLINE bool is_null() const { return location_ == nullptr; }
38
39 protected:
40 // Provides the C++ dereference operator.
41 V8_INLINE Object* operator*() const {
42 SLOW_DCHECK(IsDereferenceAllowed(INCLUDE_DEFERRED_CHECK));
43 return *location_;
44 }
45
46 // Returns the address to where the raw pointer is stored.
47 V8_INLINE Object** location() const {
48 SLOW_DCHECK(location_ == NULL ||
49 IsDereferenceAllowed(INCLUDE_DEFERRED_CHECK));
50 return location_;
51 }
52
53 enum DereferenceCheckMode { INCLUDE_DEFERRED_CHECK, NO_DEFERRED_CHECK };
54 #ifdef DEBUG
55 bool IsDereferenceAllowed(DereferenceCheckMode mode) const;
56 #else
57 V8_INLINE
58 bool IsDereferenceAllowed(DereferenceCheckMode mode) const { return true; }
59 #endif // DEBUG
60
61 Object** location_;
62 };
63
64
65 // ----------------------------------------------------------------------------
66 // A Handle provides a reference to an object that survives relocation by
67 // the garbage collector.
68 // Handles are only valid within a HandleScope.
69 // When a handle is created for an object a cell is allocated in the heap.
70 template <typename T>
71 class Handle final : public HandleBase {
72 public:
73 V8_INLINE explicit Handle(T** location = nullptr)
74 : HandleBase(reinterpret_cast<Object**>(location)) {
75 Object* a = nullptr;
76 T* b = nullptr;
77 a = b; // Fake assignment to enforce type checks.
78 USE(a);
79 }
80 V8_INLINE explicit Handle(T* object) : Handle(object, object->GetIsolate()) {}
81 V8_INLINE Handle(T* object, Isolate* isolate) : HandleBase(object, isolate) {}
82
83 // Constructor for handling automatic up casting.
84 // Ex. Handle<JSFunction> can be passed when Handle<Object> is expected.
85 template <typename S>
86 V8_INLINE Handle(Handle<S> handle)
87 : HandleBase(handle) {
88 T* a = nullptr;
89 S* b = nullptr;
90 a = b; // Fake assignment to enforce type checks.
91 USE(a);
92 }
93
94 V8_INLINE T* operator->() const { return operator*(); }
95
96 // Provides the C++ dereference operator.
97 V8_INLINE T* operator*() const {
98 return reinterpret_cast<T*>(HandleBase::operator*());
99 }
100
101 // Returns the address to where the raw pointer is stored.
102 V8_INLINE T** location() const {
103 return reinterpret_cast<T**>(HandleBase::location());
104 }
105
106 template <typename S>
107 static const Handle<T> cast(Handle<S> that) {
108 T::cast(*reinterpret_cast<T**>(that.location_));
109 return Handle<T>(reinterpret_cast<T**>(that.location_));
110 }
111
112 // TODO(yangguo): Values that contain empty handles should be declared as
113 // MaybeHandle to force validation before being used as handles.
114 static const Handle<T> null() { return Handle<T>(); }
115
116 private:
117 // Handles of different classes are allowed to access each other's location_.
118 template <typename>
119 friend class Handle;
120 // MaybeHandle is allowed to access location_.
121 template <typename>
122 friend class MaybeHandle;
123 };
124
125 template <typename T>
126 V8_INLINE Handle<T> handle(T* object, Isolate* isolate) {
127 return Handle<T>(object, isolate);
128 }
129
130 template <typename T>
131 V8_INLINE Handle<T> handle(T* object) {
132 return Handle<T>(object);
133 }
134
135
136 // ----------------------------------------------------------------------------
13 // A Handle can be converted into a MaybeHandle. Converting a MaybeHandle 137 // 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 138 // into a Handle requires checking that it does not point to NULL. This
15 // ensures NULL checks before use. 139 // ensures NULL checks before use.
16 // Do not use MaybeHandle as argument type. 140 // Do not use MaybeHandle as argument type.
17 141 template <typename T>
18 template<typename T> 142 class MaybeHandle final {
19 class MaybeHandle {
20 public: 143 public:
21 INLINE(MaybeHandle()) : location_(NULL) { } 144 V8_INLINE MaybeHandle() {}
145 V8_INLINE ~MaybeHandle() {}
22 146
23 // Constructor for handling automatic up casting from Handle. 147 // Constructor for handling automatic up casting from Handle.
24 // Ex. Handle<JSArray> can be passed when MaybeHandle<Object> is expected. 148 // Ex. Handle<JSArray> can be passed when MaybeHandle<Object> is expected.
25 template <class S> MaybeHandle(Handle<S> handle) { 149 template <typename S>
26 #ifdef DEBUG 150 V8_INLINE MaybeHandle(Handle<S> handle)
27 T* a = NULL; 151 : location_(reinterpret_cast<T**>(handle.location_)) {
28 S* b = NULL; 152 T* a = nullptr;
29 a = b; // Fake assignment to enforce type checks. 153 S* b = nullptr;
30 USE(a); 154 a = b; // Fake assignment to enforce type checks.
31 #endif 155 USE(a);
32 this->location_ = reinterpret_cast<T**>(handle.location());
33 } 156 }
34 157
35 // Constructor for handling automatic up casting. 158 // Constructor for handling automatic up casting.
36 // Ex. MaybeHandle<JSArray> can be passed when Handle<Object> is expected. 159 // Ex. MaybeHandle<JSArray> can be passed when Handle<Object> is expected.
37 template <class S> MaybeHandle(MaybeHandle<S> maybe_handle) { 160 template <typename S>
38 #ifdef DEBUG 161 V8_INLINE MaybeHandle(MaybeHandle<S> maybe_handle)
39 T* a = NULL; 162 : location_(reinterpret_cast<T**>(maybe_handle.location_)) {
40 S* b = NULL; 163 T* a = nullptr;
41 a = b; // Fake assignment to enforce type checks. 164 S* b = nullptr;
42 USE(a); 165 a = b; // Fake assignment to enforce type checks.
43 #endif 166 USE(a);
44 location_ = reinterpret_cast<T**>(maybe_handle.location_); 167 }
45 } 168
46 169 V8_INLINE void Assert() const { DCHECK_NOT_NULL(location_); }
47 INLINE(void Assert() const) { DCHECK(location_ != NULL); } 170 V8_INLINE void Check() const { CHECK_NOT_NULL(location_); }
48 INLINE(void Check() const) { CHECK(location_ != NULL); } 171
49 172 V8_INLINE Handle<T> ToHandleChecked() const {
50 INLINE(Handle<T> ToHandleChecked()) const {
51 Check(); 173 Check();
52 return Handle<T>(location_); 174 return Handle<T>(location_);
53 } 175 }
54 176
55 // Convert to a Handle with a type that can be upcasted to. 177 // Convert to a Handle with a type that can be upcasted to.
56 template <class S> 178 template <typename S>
57 V8_INLINE bool ToHandle(Handle<S>* out) const { 179 V8_INLINE bool ToHandle(Handle<S>* out) const {
58 if (location_ == NULL) { 180 if (location_ == nullptr) {
59 *out = Handle<T>::null(); 181 *out = Handle<T>::null();
60 return false; 182 return false;
61 } else { 183 } else {
62 *out = Handle<T>(location_); 184 *out = Handle<T>(location_);
63 return true; 185 return true;
64 } 186 }
65 } 187 }
66 188
67 bool is_null() const { return location_ == NULL; } 189 bool is_null() const { return location_ == nullptr; }
68 190
69 template <typename S> 191 template <typename S>
70 bool operator==(MaybeHandle<S> that) const { 192 V8_INLINE bool operator==(MaybeHandle<S> that) const {
71 return this->location_ == that.location_; 193 return this->location_ == that.location_;
72 } 194 }
73 template <typename S> 195 template <typename S>
74 bool operator!=(MaybeHandle<S> that) const { 196 V8_INLINE bool operator!=(MaybeHandle<S> that) const {
75 return !(*this == that); 197 return this->location_ != that.location_;
76 } 198 }
77
78 199
79 protected: 200 protected:
80 T** location_; 201 T** location_ = nullptr;
81 202
82 // MaybeHandles of different classes are allowed to access each 203 // MaybeHandles of different classes are allowed to access each
83 // other's location_. 204 // other's location_.
84 template<class S> friend class MaybeHandle; 205 template <typename>
206 friend class MaybeHandle;
207 // Utility functions are allowed to access location_.
85 template <typename S> 208 template <typename S>
86 friend size_t hash_value(MaybeHandle<S>); 209 friend size_t hash_value(MaybeHandle<S>);
87 }; 210 };
88 211
89 template <typename S> 212 template <typename T>
90 inline size_t hash_value(MaybeHandle<S> maybe_handle) { 213 V8_INLINE size_t hash_value(MaybeHandle<T> maybe_handle) {
91 return bit_cast<size_t>(maybe_handle.location_); 214 uintptr_t v = bit_cast<uintptr_t>(maybe_handle.location_);
215 DCHECK_EQ(0u, v & ((1u << kPointerSizeLog2) - 1));
216 return v >> kPointerSizeLog2;
92 } 217 }
93 218
94 219
95 // ----------------------------------------------------------------------------
96 // A Handle provides a reference to an object that survives relocation by
97 // the garbage collector.
98 // Handles are only valid within a HandleScope.
99 // When a handle is created for an object a cell is allocated in the heap.
100
101 template<typename T>
102 class Handle {
103 public:
104 INLINE(explicit Handle(T** location)) { location_ = location; }
105 INLINE(explicit Handle(T* obj));
106 INLINE(Handle(T* obj, Isolate* isolate));
107
108 // TODO(yangguo): Values that contain empty handles should be declared as
109 // MaybeHandle to force validation before being used as handles.
110 INLINE(Handle()) : location_(NULL) { }
111
112 // Constructor for handling automatic up casting.
113 // Ex. Handle<JSFunction> can be passed when Handle<Object> is expected.
114 template <class S> Handle(Handle<S> handle) {
115 #ifdef DEBUG
116 T* a = NULL;
117 S* b = NULL;
118 a = b; // Fake assignment to enforce type checks.
119 USE(a);
120 #endif
121 location_ = reinterpret_cast<T**>(handle.location_);
122 }
123
124 INLINE(T* operator->() const) { return operator*(); }
125
126 // Check if this handle refers to the exact same object as the other handle.
127 INLINE(bool is_identical_to(const Handle<T> other) const);
128
129 // Provides the C++ dereference operator.
130 INLINE(T* operator*() const);
131
132 // Returns the address to where the raw pointer is stored.
133 INLINE(T** location() const);
134
135 template <class S> static Handle<T> cast(Handle<S> that) {
136 T::cast(*reinterpret_cast<T**>(that.location_));
137 return Handle<T>(reinterpret_cast<T**>(that.location_));
138 }
139
140 // TODO(yangguo): Values that contain empty handles should be declared as
141 // MaybeHandle to force validation before being used as handles.
142 static Handle<T> null() { return Handle<T>(); }
143 bool is_null() const { return location_ == NULL; }
144
145 // Closes the given scope, but lets this handle escape. See
146 // implementation in api.h.
147 inline Handle<T> EscapeFrom(v8::EscapableHandleScope* scope);
148
149 #ifdef DEBUG
150 enum DereferenceCheckMode { INCLUDE_DEFERRED_CHECK, NO_DEFERRED_CHECK };
151
152 bool IsDereferenceAllowed(DereferenceCheckMode mode) const;
153 #endif // DEBUG
154
155 private:
156 T** location_;
157
158 // Handles of different classes are allowed to access each other's location_.
159 template<class S> friend class Handle;
160 };
161
162
163 // Convenience wrapper.
164 template<class T>
165 inline Handle<T> handle(T* t, Isolate* isolate) {
166 return Handle<T>(t, isolate);
167 }
168
169
170 // Convenience wrapper.
171 template<class T>
172 inline Handle<T> handle(T* t) {
173 return Handle<T>(t, t->GetIsolate());
174 }
175
176
177 class DeferredHandles;
178 class HandleScopeImplementer;
179
180
181 // A stack-allocated class that governs a number of local handles. 220 // A stack-allocated class that governs a number of local handles.
182 // After a handle scope has been created, all local handles will be 221 // After a handle scope has been created, all local handles will be
183 // allocated within that handle scope until either the handle scope is 222 // allocated within that handle scope until either the handle scope is
184 // deleted or another handle scope is created. If there is already a 223 // deleted or another handle scope is created. If there is already a
185 // handle scope and a new one is created, all allocations will take 224 // handle scope and a new one is created, all allocations will take
186 // place in the new handle scope until it is deleted. After that, 225 // place in the new handle scope until it is deleted. After that,
187 // new handles will again be allocated in the original handle scope. 226 // new handles will again be allocated in the original handle scope.
188 // 227 //
189 // After the handle scope of a local handle has been deleted the 228 // After the handle scope of a local handle has been deleted the
190 // garbage collector will no longer track the object stored in the 229 // garbage collector will no longer track the object stored in the
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
234 Isolate* isolate_; 273 Isolate* isolate_;
235 Object** prev_next_; 274 Object** prev_next_;
236 Object** prev_limit_; 275 Object** prev_limit_;
237 276
238 // Close the handle scope resetting limits to a previous state. 277 // Close the handle scope resetting limits to a previous state.
239 static inline void CloseScope(Isolate* isolate, 278 static inline void CloseScope(Isolate* isolate,
240 Object** prev_next, 279 Object** prev_next,
241 Object** prev_limit); 280 Object** prev_limit);
242 281
243 // Extend the handle scope making room for more handles. 282 // Extend the handle scope making room for more handles.
244 static internal::Object** Extend(Isolate* isolate); 283 static Object** Extend(Isolate* isolate);
245 284
246 #ifdef ENABLE_HANDLE_ZAPPING 285 #ifdef ENABLE_HANDLE_ZAPPING
247 // Zaps the handles in the half-open interval [start, end). 286 // Zaps the handles in the half-open interval [start, end).
248 static void ZapRange(Object** start, Object** end); 287 static void ZapRange(Object** start, Object** end);
249 #endif 288 #endif
250 289
251 friend class v8::HandleScope; 290 friend class v8::HandleScope;
252 friend class v8::internal::DeferredHandles; 291 friend class DeferredHandles;
253 friend class v8::internal::HandleScopeImplementer; 292 friend class HandleScopeImplementer;
254 friend class v8::internal::Isolate; 293 friend class Isolate;
255 }; 294 };
256 295
257 296
258 class DeferredHandles; 297 class DeferredHandleScope final {
259
260
261 class DeferredHandleScope {
262 public: 298 public:
263 explicit DeferredHandleScope(Isolate* isolate); 299 explicit DeferredHandleScope(Isolate* isolate);
264 // The DeferredHandles object returned stores the Handles created 300 // The DeferredHandles object returned stores the Handles created
265 // since the creation of this DeferredHandleScope. The Handles are 301 // since the creation of this DeferredHandleScope. The Handles are
266 // alive as long as the DeferredHandles object is alive. 302 // alive as long as the DeferredHandles object is alive.
267 DeferredHandles* Detach(); 303 DeferredHandles* Detach();
268 ~DeferredHandleScope(); 304 ~DeferredHandleScope();
269 305
270 private: 306 private:
271 Object** prev_limit_; 307 Object** prev_limit_;
272 Object** prev_next_; 308 Object** prev_next_;
273 HandleScopeImplementer* impl_; 309 HandleScopeImplementer* impl_;
274 310
275 #ifdef DEBUG 311 #ifdef DEBUG
276 bool handles_detached_; 312 bool handles_detached_;
277 int prev_level_; 313 int prev_level_;
278 #endif 314 #endif
279 315
280 friend class HandleScopeImplementer; 316 friend class HandleScopeImplementer;
281 }; 317 };
282 318
283 319
284 // Seal off the current HandleScope so that new handles can only be created 320 // Seal off the current HandleScope so that new handles can only be created
285 // if a new HandleScope is entered. 321 // if a new HandleScope is entered.
286 class SealHandleScope BASE_EMBEDDED { 322 class SealHandleScope final {
287 public: 323 public:
288 #ifndef DEBUG 324 #ifndef DEBUG
289 explicit SealHandleScope(Isolate* isolate) {} 325 explicit SealHandleScope(Isolate* isolate) {}
290 ~SealHandleScope() {} 326 ~SealHandleScope() {}
291 #else 327 #else
292 explicit inline SealHandleScope(Isolate* isolate); 328 explicit inline SealHandleScope(Isolate* isolate);
293 inline ~SealHandleScope(); 329 inline ~SealHandleScope();
294 private: 330 private:
295 Isolate* isolate_; 331 Isolate* isolate_;
296 Object** limit_; 332 Object** limit_;
297 int level_; 333 int level_;
298 #endif 334 #endif
299 }; 335 };
300 336
301 struct HandleScopeData { 337
302 internal::Object** next; 338 struct HandleScopeData final {
303 internal::Object** limit; 339 Object** next;
340 Object** limit;
304 int level; 341 int level;
305 342
306 void Initialize() { 343 void Initialize() {
307 next = limit = NULL; 344 next = limit = NULL;
308 level = 0; 345 level = 0;
309 } 346 }
310 }; 347 };
311 348
312 } } // namespace v8::internal 349 } // namespace internal
350 } // namespace v8
313 351
314 #endif // V8_HANDLES_H_ 352 #endif // V8_HANDLES_H_
OLDNEW
« no previous file with comments | « src/api.cc ('k') | src/handles.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698