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

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: Created 5 years, 7 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 | « no previous file | 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
13 // A Handle can be converted into a MaybeHandle. Converting a MaybeHandle 18 // 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 19 // into a Handle requires checking that it does not point to NULL. This
15 // ensures NULL checks before use. 20 // ensures NULL checks before use.
16 // Do not use MaybeHandle as argument type. 21 // Do not use MaybeHandle as argument type.
17
18 template<typename T> 22 template<typename T>
19 class MaybeHandle { 23 class MaybeHandle {
20 public: 24 public:
21 INLINE(MaybeHandle()) : location_(NULL) { } 25 V8_INLINE MaybeHandle() : location_(nullptr) {}
22 26
23 // Constructor for handling automatic up casting from Handle. 27 // Constructor for handling automatic up casting from Handle.
24 // Ex. Handle<JSArray> can be passed when MaybeHandle<Object> is expected. 28 // Ex. Handle<JSArray> can be passed when MaybeHandle<Object> is expected.
25 template <class S> MaybeHandle(Handle<S> handle) { 29 template <class S> MaybeHandle(Handle<S> handle) {
26 #ifdef DEBUG 30 #ifdef DEBUG
27 T* a = NULL; 31 T* a = nullptr;
28 S* b = NULL; 32 S* b = nullptr;
29 a = b; // Fake assignment to enforce type checks. 33 a = b; // Fake assignment to enforce type checks.
30 USE(a); 34 USE(a);
31 #endif 35 #endif
32 this->location_ = reinterpret_cast<T**>(handle.location()); 36 this->location_ = reinterpret_cast<T**>(handle.location());
33 } 37 }
34 38
35 // Constructor for handling automatic up casting. 39 // Constructor for handling automatic up casting.
36 // Ex. MaybeHandle<JSArray> can be passed when Handle<Object> is expected. 40 // Ex. MaybeHandle<JSArray> can be passed when Handle<Object> is expected.
37 template <class S> MaybeHandle(MaybeHandle<S> maybe_handle) { 41 template <class S> MaybeHandle(MaybeHandle<S> maybe_handle) {
38 #ifdef DEBUG 42 #ifdef DEBUG
39 T* a = NULL; 43 T* a = NULL;
40 S* b = NULL; 44 S* b = NULL;
41 a = b; // Fake assignment to enforce type checks. 45 a = b; // Fake assignment to enforce type checks.
42 USE(a); 46 USE(a);
43 #endif 47 #endif
44 location_ = reinterpret_cast<T**>(maybe_handle.location_); 48 location_ = reinterpret_cast<T**>(maybe_handle.location_);
45 } 49 }
46 50
47 INLINE(void Assert() const) { DCHECK(location_ != NULL); } 51 V8_INLINE void Assert() const { DCHECK_NOT_NULL(location_); }
48 INLINE(void Check() const) { CHECK(location_ != NULL); } 52 V8_INLINE void Check() const { CHECK_NOT_NULL(location_); }
49 53
50 INLINE(Handle<T> ToHandleChecked()) const { 54 V8_INLINE Handle<T> ToHandleChecked() const {
51 Check(); 55 Check();
52 return Handle<T>(location_); 56 return Handle<T>(location_);
53 } 57 }
54 58
55 // Convert to a Handle with a type that can be upcasted to. 59 // Convert to a Handle with a type that can be upcasted to.
56 template <class S> 60 template <class S>
57 V8_INLINE bool ToHandle(Handle<S>* out) const { 61 V8_INLINE bool ToHandle(Handle<S>* out) const {
58 if (location_ == NULL) { 62 if (location_ == NULL) {
59 *out = Handle<T>::null(); 63 *out = Handle<T>::null();
60 return false; 64 return false;
61 } else { 65 } else {
62 *out = Handle<T>(location_); 66 *out = Handle<T>(location_);
63 return true; 67 return true;
64 } 68 }
65 } 69 }
66 70
67 bool is_null() const { return location_ == NULL; } 71 bool is_null() const { return location_ == NULL; }
68 72
69 protected: 73 protected:
70 T** location_; 74 T** location_;
71 75
72 // MaybeHandles of different classes are allowed to access each 76 // MaybeHandles of different classes are allowed to access each
73 // other's location_. 77 // other's location_.
74 template<class S> friend class MaybeHandle; 78 template<class S> friend class MaybeHandle;
75 }; 79 };
76 80
81
82 // Base class for Handles. Don't use this directly.
83 class HandleBase {
84 public:
85 V8_INLINE explicit HandleBase(Object** location = nullptr)
86 : location_(location) {}
87 V8_INLINE explicit HandleBase(HandleBase const& other)
88 : location_(other.location_) {}
89 explicit HandleBase(HeapObject* object);
90 explicit HandleBase(Object* object, Isolate* isolate);
91 V8_INLINE ~HandleBase() {}
92
93 // Check if this handle refers to the exact same object as the other handle.
94 V8_INLINE bool is_identical_to(HandleBase const& other) const {
95 // Dereferencing deferred handles to check object equality is safe.
96 SLOW_DCHECK(location_ == nullptr ||
97 IsDereferenceAllowed(NO_DEFERRED_CHECK));
98 SLOW_DCHECK(other.location_ == nullptr ||
99 other.IsDereferenceAllowed(NO_DEFERRED_CHECK));
100 if (location_ == other.location_) return true;
101 if (location_ == nullptr || other.location_ == nullptr) return false;
102 return *location_ == *other.location_;
103 }
104
105 // Check if this handle is a NULL handle.
106 V8_INLINE bool is_null() const { return location_ == nullptr; }
107
108 protected:
109 // Provides the C++ deference operator.
110 V8_INLINE Object* operator*() const {
111 SLOW_DCHECK(IsDereferenceAllowed(INCLUDE_DEFERRED_CHECK));
112 return *location_;
113 }
114
115 // Returns the address to where the raw pointer is stored.
116 V8_INLINE Object** location() const {
117 SLOW_DCHECK(location_ == nullptr ||
118 IsDereferenceAllowed(INCLUDE_DEFERRED_CHECK));
119 return location_;
120 }
121
122 private:
123 enum DereferenceCheckMode { INCLUDE_DEFERRED_CHECK, NO_DEFERRED_CHECK };
124 #ifdef DEBUG
125 bool IsDereferenceAllowed(DereferenceCheckMode mode) const;
126 #else
127 V8_INLINE bool IsDereferenceAllowed(DereferenceCheckMode) const {
128 return true;
129 }
130 #endif // DEBUG
131
132 Object** location_;
133 };
134
135
77 // ---------------------------------------------------------------------------- 136 // ----------------------------------------------------------------------------
78 // A Handle provides a reference to an object that survives relocation by 137 // A Handle provides a reference to an object that survives relocation by
79 // the garbage collector. 138 // the garbage collector.
80 // Handles are only valid within a HandleScope. 139 // Handles are only valid within a HandleScope.
81 // When a handle is created for an object a cell is allocated in the heap. 140 // When a handle is created for an object a cell is allocated in the heap.
82 141 template <typename T>
83 template<typename T> 142 class Handle final : public HandleBase {
84 class Handle {
85 public: 143 public:
86 INLINE(explicit Handle(T** location)) { location_ = location; } 144 V8_INLINE explicit Handle(T** location)
87 INLINE(explicit Handle(T* obj)); 145 : HandleBase(reinterpret_cast<Object**>(location)) {}
88 INLINE(Handle(T* obj, Isolate* isolate)); 146 V8_INLINE explicit Handle(T* object) : HandleBase(object) {}
147 V8_INLINE Handle(T* object, Isolate* isolate) : HandleBase(object, isolate) {}
89 148
90 // TODO(yangguo): Values that contain empty handles should be declared as 149 // TODO(yangguo): Values that contain empty handles should be declared as
91 // MaybeHandle to force validation before being used as handles. 150 // MaybeHandle to force validation before being used as handles.
92 INLINE(Handle()) : location_(NULL) { } 151 V8_INLINE Handle() {}
93 152
94 // Constructor for handling automatic up casting. 153 // Constructor for handling automatic up casting.
95 // Ex. Handle<JSFunction> can be passed when Handle<Object> is expected. 154 // Ex. Handle<JSFunction> can be passed when Handle<Object> is expected.
96 template <class S> Handle(Handle<S> handle) { 155 template <class S>
97 #ifdef DEBUG 156 V8_INLINE Handle(Handle<S> const& other)
98 T* a = NULL; 157 : HandleBase(other) {
99 S* b = NULL; 158 T* a = nullptr;
159 S* b = nullptr;
100 a = b; // Fake assignment to enforce type checks. 160 a = b; // Fake assignment to enforce type checks.
101 USE(a); 161 USE(a);
102 #endif
103 location_ = reinterpret_cast<T**>(handle.location_);
104 } 162 }
105 163
106 INLINE(T* operator->() const) { return operator*(); } 164 V8_INLINE T* operator->() const { return operator*(); }
107
108 // Check if this handle refers to the exact same object as the other handle.
109 INLINE(bool is_identical_to(const Handle<T> other) const);
110 165
111 // Provides the C++ dereference operator. 166 // Provides the C++ dereference operator.
112 INLINE(T* operator*() const); 167 V8_INLINE T* operator*() const {
168 return reinterpret_cast<T*>(HandleBase::operator*());
169 }
113 170
114 // Returns the address to where the raw pointer is stored. 171 // Returns the address to where the raw pointer is stored.
115 INLINE(T** location() const); 172 V8_INLINE T** location() const {
173 return reinterpret_cast<T**>(HandleBase::location());
174 }
116 175
117 template <class S> static Handle<T> cast(Handle<S> that) { 176 template <class S>
118 T::cast(*reinterpret_cast<T**>(that.location_)); 177 V8_INLINE static Handle<T> cast(Handle<S> const& other) {
119 return Handle<T>(reinterpret_cast<T**>(that.location_)); 178 T::cast(*reinterpret_cast<T**>(other.location()));
179 return Handle<T>(reinterpret_cast<T**>(other.location()));
120 } 180 }
121 181
122 // TODO(yangguo): Values that contain empty handles should be declared as 182 // TODO(yangguo): Values that contain empty handles should be declared as
123 // MaybeHandle to force validation before being used as handles. 183 // MaybeHandle to force validation before being used as handles.
124 static Handle<T> null() { return Handle<T>(); } 184 static Handle<T> null() { return Handle<T>(); }
125 bool is_null() const { return location_ == NULL; }
126 185
127 // Closes the given scope, but lets this handle escape. See 186 // Closes the given scope, but lets this handle escape. See
128 // implementation in api.h. 187 // implementation in api.h.
129 inline Handle<T> EscapeFrom(v8::EscapableHandleScope* scope); 188 inline Handle<T> EscapeFrom(v8::EscapableHandleScope* scope);
130 189
131 #ifdef DEBUG
132 enum DereferenceCheckMode { INCLUDE_DEFERRED_CHECK, NO_DEFERRED_CHECK };
133
134 bool IsDereferenceAllowed(DereferenceCheckMode mode) const;
135 #endif // DEBUG
136
137 private: 190 private:
138 T** location_;
139
140 // Handles of different classes are allowed to access each other's location_. 191 // Handles of different classes are allowed to access each other's location_.
141 template<class S> friend class Handle; 192 template<class S> friend class Handle;
142 }; 193 };
143 194
144 195
145 // Convenience wrapper. 196 // Convenience wrapper.
146 template<class T> 197 template<class T>
147 inline Handle<T> handle(T* t, Isolate* isolate) { 198 inline Handle<T> handle(T* t, Isolate* isolate) {
148 return Handle<T>(t, isolate); 199 return Handle<T>(t, isolate);
149 } 200 }
150 201
151 202
152 // Convenience wrapper. 203 // Convenience wrapper.
153 template<class T> 204 template<class T>
154 inline Handle<T> handle(T* t) { 205 inline Handle<T> handle(T* t) {
155 return Handle<T>(t, t->GetIsolate()); 206 return Handle<T>(t, t->GetIsolate());
156 } 207 }
157 208
158 209
159 // Key comparison function for Map handles. 210 // Key comparison function for Map handles.
160 inline bool operator<(const Handle<Map>& lhs, const Handle<Map>& rhs) { 211 inline bool operator<(const Handle<Map>& lhs, const Handle<Map>& rhs) {
161 // This is safe because maps don't move. 212 // This is safe because maps don't move.
162 return *lhs < *rhs; 213 return *lhs < *rhs;
163 } 214 }
164 215
165 216
166 class DeferredHandles;
167 class HandleScopeImplementer;
168
169
170 // A stack-allocated class that governs a number of local handles. 217 // A stack-allocated class that governs a number of local handles.
171 // After a handle scope has been created, all local handles will be 218 // After a handle scope has been created, all local handles will be
172 // allocated within that handle scope until either the handle scope is 219 // allocated within that handle scope until either the handle scope is
173 // deleted or another handle scope is created. If there is already a 220 // 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 221 // 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, 222 // place in the new handle scope until it is deleted. After that,
176 // new handles will again be allocated in the original handle scope. 223 // new handles will again be allocated in the original handle scope.
177 // 224 //
178 // After the handle scope of a local handle has been deleted the 225 // After the handle scope of a local handle has been deleted the
179 // garbage collector will no longer track the object stored in the 226 // garbage collector will no longer track the object stored in the
180 // handle and may deallocate it. The behavior of accessing a handle 227 // handle and may deallocate it. The behavior of accessing a handle
181 // for which the handle scope has been deleted is undefined. 228 // for which the handle scope has been deleted is undefined.
182 class HandleScope { 229 class HandleScope final {
183 public: 230 public:
184 explicit inline HandleScope(Isolate* isolate); 231 explicit HandleScope(Isolate* isolate);
185 232 ~HandleScope();
186 inline ~HandleScope();
187 233
188 // Counts the number of allocated handles. 234 // Counts the number of allocated handles.
189 static int NumberOfHandles(Isolate* isolate); 235 static int NumberOfHandles(Isolate* isolate);
190 236
191 // Creates a new handle with the given value. 237 // Creates a new handle with the given value.
238 static Object** CreateHandle(Isolate* isolate, Object* value);
192 template <typename T> 239 template <typename T>
193 static inline T** CreateHandle(Isolate* isolate, T* value); 240 static T** CreateHandle(Isolate* isolate, T* value) {
241 return reinterpret_cast<T**>(
242 CreateHandle(isolate, static_cast<Object*>(value)));
243 }
194 244
195 // Deallocates any extensions used by the current scope. 245 // Deallocates any extensions used by the current scope.
196 static void DeleteExtensions(Isolate* isolate); 246 static void DeleteExtensions(Isolate* isolate);
197 247
198 static Address current_next_address(Isolate* isolate); 248 static Address current_next_address(Isolate* isolate);
199 static Address current_limit_address(Isolate* isolate); 249 static Address current_limit_address(Isolate* isolate);
200 static Address current_level_address(Isolate* isolate); 250 static Address current_level_address(Isolate* isolate);
201 251
202 // Closes the HandleScope (invalidating all handles 252 // Closes the HandleScope (invalidating all handles
203 // created in the scope of the HandleScope) and returns 253 // created in the scope of the HandleScope) and returns
204 // a Handle backed by the parent scope holding the 254 // a Handle backed by the parent scope holding the
205 // value of the argument handle. 255 // value of the argument handle.
256 Handle<Object> CloseAndEscape(Handle<Object> handle);
206 template <typename T> 257 template <typename T>
207 Handle<T> CloseAndEscape(Handle<T> handle_value); 258 Handle<T> CloseAndEscape(Handle<T> handle) {
259 return Handle<T>::cast(CloseAndEscape(Handle<Object>::cast(handle)));
260 }
208 261
209 Isolate* isolate() { return isolate_; } 262 Isolate* isolate() const { return isolate_; }
210 263
211 private: 264 private:
265 friend class v8::HandleScope;
266 friend class v8::internal::DeferredHandles;
267 friend class v8::internal::HandleScopeImplementer;
268 friend class v8::internal::Isolate;
269
212 // Prevent heap allocation or illegal handle scopes. 270 // Prevent heap allocation or illegal handle scopes.
213 HandleScope(const HandleScope&); 271 void* operator new(size_t size) = delete;
214 void operator=(const HandleScope&); 272 void operator delete(void* size_t) = delete;
215 void* operator new(size_t size);
216 void operator delete(void* size_t);
217
218 Isolate* isolate_;
219 Object** prev_next_;
220 Object** prev_limit_;
221 273
222 // Close the handle scope resetting limits to a previous state. 274 // Close the handle scope resetting limits to a previous state.
223 static inline void CloseScope(Isolate* isolate, 275 static void CloseScope(Isolate* isolate, Object** prev_next,
224 Object** prev_next, 276 Object** prev_limit);
225 Object** prev_limit);
226 277
227 // Extend the handle scope making room for more handles. 278 // Extend the handle scope making room for more handles.
228 static internal::Object** Extend(Isolate* isolate); 279 static Object** Extend(Isolate* isolate);
229 280
230 #ifdef ENABLE_HANDLE_ZAPPING 281 #ifdef ENABLE_HANDLE_ZAPPING
231 // Zaps the handles in the half-open interval [start, end). 282 // Zaps the handles in the half-open interval [start, end).
232 static void ZapRange(Object** start, Object** end); 283 static void ZapRange(Object** start, Object** end);
233 #endif 284 #endif
234 285
235 friend class v8::HandleScope; 286 Isolate* const isolate_;
236 friend class v8::internal::DeferredHandles; 287 Object** prev_next_;
237 friend class v8::internal::HandleScopeImplementer; 288 Object** prev_limit_;
238 friend class v8::internal::Isolate; 289
290 DISALLOW_COPY_AND_ASSIGN(HandleScope);
239 }; 291 };
240 292
241 293
242 class DeferredHandles;
243
244
245 class DeferredHandleScope { 294 class DeferredHandleScope {
246 public: 295 public:
247 explicit DeferredHandleScope(Isolate* isolate); 296 explicit DeferredHandleScope(Isolate* isolate);
248 // The DeferredHandles object returned stores the Handles created 297 // The DeferredHandles object returned stores the Handles created
249 // since the creation of this DeferredHandleScope. The Handles are 298 // since the creation of this DeferredHandleScope. The Handles are
250 // alive as long as the DeferredHandles object is alive. 299 // alive as long as the DeferredHandles object is alive.
251 DeferredHandles* Detach(); 300 DeferredHandles* Detach();
252 ~DeferredHandleScope(); 301 ~DeferredHandleScope();
253 302
254 private: 303 private:
255 Object** prev_limit_; 304 Object** prev_limit_;
256 Object** prev_next_; 305 Object** prev_next_;
257 HandleScopeImplementer* impl_; 306 HandleScopeImplementer* impl_;
258 307
259 #ifdef DEBUG 308 #ifdef DEBUG
260 bool handles_detached_; 309 bool handles_detached_;
261 int prev_level_; 310 int prev_level_;
262 #endif 311 #endif
263 312
264 friend class HandleScopeImplementer; 313 friend class HandleScopeImplementer;
265 }; 314 };
266 315
267 316
268 // Seal off the current HandleScope so that new handles can only be created 317 // Seal off the current HandleScope so that new handles can only be created
269 // if a new HandleScope is entered. 318 // if a new HandleScope is entered.
270 class SealHandleScope BASE_EMBEDDED { 319 class SealHandleScope final {
Yang 2015/05/05 11:01:31 Why are we getting rid of BASE_EMBEDDED here?
Benedikt Meurer 2015/05/05 12:11:15 Because it's crap and doesn't work as intended, as
271 public: 320 public:
272 #ifndef DEBUG 321 #ifndef DEBUG
273 explicit SealHandleScope(Isolate* isolate) {} 322 explicit SealHandleScope(Isolate* isolate) {}
274 ~SealHandleScope() {} 323 ~SealHandleScope() {}
275 #else 324 #else
276 explicit inline SealHandleScope(Isolate* isolate); 325 explicit SealHandleScope(Isolate* isolate);
277 inline ~SealHandleScope(); 326 ~SealHandleScope();
327
278 private: 328 private:
279 Isolate* isolate_; 329 Isolate* const isolate_;
280 Object** limit_; 330 Object** limit_;
281 int level_; 331 int level_;
282 #endif 332 #endif // DEBUG
333
334 private:
335 DISALLOW_COPY_AND_ASSIGN(SealHandleScope);
283 }; 336 };
284 337
338
285 struct HandleScopeData { 339 struct HandleScopeData {
286 internal::Object** next; 340 internal::Object** next;
287 internal::Object** limit; 341 internal::Object** limit;
288 int level; 342 int level;
289 343
290 void Initialize() { 344 void Initialize() {
291 next = limit = NULL; 345 next = limit = nullptr;
292 level = 0; 346 level = 0;
293 } 347 }
294 }; 348 };
295 349
296 } } // namespace v8::internal 350 } // namespace internal
351 } // namespace v8
297 352
298 #endif // V8_HANDLES_H_ 353 #endif // V8_HANDLES_H_
OLDNEW
« no previous file with comments | « no previous file | src/handles.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698