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

Unified 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | src/handles.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/handles.h
diff --git a/src/handles.h b/src/handles.h
index eb57f0e26089383c9d7fe9f57a8cba5f41a111e2..b97badaea9cbcadeb13114fb43da099a1d8a9dab 100644
--- a/src/handles.h
+++ b/src/handles.h
@@ -10,22 +10,26 @@
namespace v8 {
namespace internal {
+// Forward declarations.
+class DeferredHandles;
+class HandleScopeImplementer;
+
+
// A Handle can be converted into a MaybeHandle. Converting a MaybeHandle
// into a Handle requires checking that it does not point to NULL. This
// ensures NULL checks before use.
// Do not use MaybeHandle as argument type.
-
template<typename T>
class MaybeHandle {
public:
- INLINE(MaybeHandle()) : location_(NULL) { }
+ V8_INLINE MaybeHandle() : location_(nullptr) {}
// Constructor for handling automatic up casting from Handle.
// Ex. Handle<JSArray> can be passed when MaybeHandle<Object> is expected.
template <class S> MaybeHandle(Handle<S> handle) {
#ifdef DEBUG
- T* a = NULL;
- S* b = NULL;
+ T* a = nullptr;
+ S* b = nullptr;
a = b; // Fake assignment to enforce type checks.
USE(a);
#endif
@@ -44,10 +48,10 @@ class MaybeHandle {
location_ = reinterpret_cast<T**>(maybe_handle.location_);
}
- INLINE(void Assert() const) { DCHECK(location_ != NULL); }
- INLINE(void Check() const) { CHECK(location_ != NULL); }
+ V8_INLINE void Assert() const { DCHECK_NOT_NULL(location_); }
+ V8_INLINE void Check() const { CHECK_NOT_NULL(location_); }
- INLINE(Handle<T> ToHandleChecked()) const {
+ V8_INLINE Handle<T> ToHandleChecked() const {
Check();
return Handle<T>(location_);
}
@@ -74,69 +78,116 @@ class MaybeHandle {
template<class S> friend class MaybeHandle;
};
+
+// Base class for Handles. Don't use this directly.
+class HandleBase {
+ public:
+ V8_INLINE explicit HandleBase(Object** location = nullptr)
+ : location_(location) {}
+ V8_INLINE explicit HandleBase(HandleBase const& other)
+ : location_(other.location_) {}
+ explicit HandleBase(HeapObject* object);
+ explicit HandleBase(Object* object, Isolate* isolate);
+ V8_INLINE ~HandleBase() {}
+
+ // Check if this handle refers to the exact same object as the other handle.
+ V8_INLINE bool is_identical_to(HandleBase const& other) const {
+ // Dereferencing deferred handles to check object equality is safe.
+ SLOW_DCHECK(location_ == nullptr ||
+ IsDereferenceAllowed(NO_DEFERRED_CHECK));
+ SLOW_DCHECK(other.location_ == nullptr ||
+ other.IsDereferenceAllowed(NO_DEFERRED_CHECK));
+ if (location_ == other.location_) return true;
+ if (location_ == nullptr || other.location_ == nullptr) return false;
+ return *location_ == *other.location_;
+ }
+
+ // Check if this handle is a NULL handle.
+ V8_INLINE bool is_null() const { return location_ == nullptr; }
+
+ protected:
+ // Provides the C++ deference operator.
+ V8_INLINE Object* operator*() const {
+ SLOW_DCHECK(IsDereferenceAllowed(INCLUDE_DEFERRED_CHECK));
+ return *location_;
+ }
+
+ // Returns the address to where the raw pointer is stored.
+ V8_INLINE Object** location() const {
+ SLOW_DCHECK(location_ == nullptr ||
+ IsDereferenceAllowed(INCLUDE_DEFERRED_CHECK));
+ return location_;
+ }
+
+ private:
+ enum DereferenceCheckMode { INCLUDE_DEFERRED_CHECK, NO_DEFERRED_CHECK };
+#ifdef DEBUG
+ bool IsDereferenceAllowed(DereferenceCheckMode mode) const;
+#else
+ V8_INLINE bool IsDereferenceAllowed(DereferenceCheckMode) const {
+ return true;
+ }
+#endif // DEBUG
+
+ Object** location_;
+};
+
+
// ----------------------------------------------------------------------------
// A Handle provides a reference to an object that survives relocation by
// the garbage collector.
// Handles are only valid within a HandleScope.
// When a handle is created for an object a cell is allocated in the heap.
-
-template<typename T>
-class Handle {
+template <typename T>
+class Handle final : public HandleBase {
public:
- INLINE(explicit Handle(T** location)) { location_ = location; }
- INLINE(explicit Handle(T* obj));
- INLINE(Handle(T* obj, Isolate* isolate));
+ V8_INLINE explicit Handle(T** location)
+ : HandleBase(reinterpret_cast<Object**>(location)) {}
+ V8_INLINE explicit Handle(T* object) : HandleBase(object) {}
+ V8_INLINE Handle(T* object, Isolate* isolate) : HandleBase(object, isolate) {}
// TODO(yangguo): Values that contain empty handles should be declared as
// MaybeHandle to force validation before being used as handles.
- INLINE(Handle()) : location_(NULL) { }
+ V8_INLINE Handle() {}
// Constructor for handling automatic up casting.
// Ex. Handle<JSFunction> can be passed when Handle<Object> is expected.
- template <class S> Handle(Handle<S> handle) {
-#ifdef DEBUG
- T* a = NULL;
- S* b = NULL;
+ template <class S>
+ V8_INLINE Handle(Handle<S> const& other)
+ : HandleBase(other) {
+ T* a = nullptr;
+ S* b = nullptr;
a = b; // Fake assignment to enforce type checks.
USE(a);
-#endif
- location_ = reinterpret_cast<T**>(handle.location_);
}
- INLINE(T* operator->() const) { return operator*(); }
-
- // Check if this handle refers to the exact same object as the other handle.
- INLINE(bool is_identical_to(const Handle<T> other) const);
+ V8_INLINE T* operator->() const { return operator*(); }
// Provides the C++ dereference operator.
- INLINE(T* operator*() const);
+ V8_INLINE T* operator*() const {
+ return reinterpret_cast<T*>(HandleBase::operator*());
+ }
// Returns the address to where the raw pointer is stored.
- INLINE(T** location() const);
+ V8_INLINE T** location() const {
+ return reinterpret_cast<T**>(HandleBase::location());
+ }
- template <class S> static Handle<T> cast(Handle<S> that) {
- T::cast(*reinterpret_cast<T**>(that.location_));
- return Handle<T>(reinterpret_cast<T**>(that.location_));
+ template <class S>
+ V8_INLINE static Handle<T> cast(Handle<S> const& other) {
+ T::cast(*reinterpret_cast<T**>(other.location()));
+ return Handle<T>(reinterpret_cast<T**>(other.location()));
}
// TODO(yangguo): Values that contain empty handles should be declared as
// MaybeHandle to force validation before being used as handles.
static Handle<T> null() { return Handle<T>(); }
- bool is_null() const { return location_ == NULL; }
// Closes the given scope, but lets this handle escape. See
// implementation in api.h.
inline Handle<T> EscapeFrom(v8::EscapableHandleScope* scope);
-#ifdef DEBUG
- enum DereferenceCheckMode { INCLUDE_DEFERRED_CHECK, NO_DEFERRED_CHECK };
-
- bool IsDereferenceAllowed(DereferenceCheckMode mode) const;
-#endif // DEBUG
-
private:
- T** location_;
-
// Handles of different classes are allowed to access each other's location_.
template<class S> friend class Handle;
};
@@ -163,10 +214,6 @@ inline bool operator<(const Handle<Map>& lhs, const Handle<Map>& rhs) {
}
-class DeferredHandles;
-class HandleScopeImplementer;
-
-
// A stack-allocated class that governs a number of local handles.
// After a handle scope has been created, all local handles will be
// allocated within that handle scope until either the handle scope is
@@ -179,18 +226,21 @@ class HandleScopeImplementer;
// garbage collector will no longer track the object stored in the
// handle and may deallocate it. The behavior of accessing a handle
// for which the handle scope has been deleted is undefined.
-class HandleScope {
+class HandleScope final {
public:
- explicit inline HandleScope(Isolate* isolate);
-
- inline ~HandleScope();
+ explicit HandleScope(Isolate* isolate);
+ ~HandleScope();
// Counts the number of allocated handles.
static int NumberOfHandles(Isolate* isolate);
// Creates a new handle with the given value.
+ static Object** CreateHandle(Isolate* isolate, Object* value);
template <typename T>
- static inline T** CreateHandle(Isolate* isolate, T* value);
+ static T** CreateHandle(Isolate* isolate, T* value) {
+ return reinterpret_cast<T**>(
+ CreateHandle(isolate, static_cast<Object*>(value)));
+ }
// Deallocates any extensions used by the current scope.
static void DeleteExtensions(Isolate* isolate);
@@ -203,43 +253,42 @@ class HandleScope {
// created in the scope of the HandleScope) and returns
// a Handle backed by the parent scope holding the
// value of the argument handle.
+ Handle<Object> CloseAndEscape(Handle<Object> handle);
template <typename T>
- Handle<T> CloseAndEscape(Handle<T> handle_value);
+ Handle<T> CloseAndEscape(Handle<T> handle) {
+ return Handle<T>::cast(CloseAndEscape(Handle<Object>::cast(handle)));
+ }
- Isolate* isolate() { return isolate_; }
+ Isolate* isolate() const { return isolate_; }
private:
- // Prevent heap allocation or illegal handle scopes.
- HandleScope(const HandleScope&);
- void operator=(const HandleScope&);
- void* operator new(size_t size);
- void operator delete(void* size_t);
+ friend class v8::HandleScope;
+ friend class v8::internal::DeferredHandles;
+ friend class v8::internal::HandleScopeImplementer;
+ friend class v8::internal::Isolate;
- Isolate* isolate_;
- Object** prev_next_;
- Object** prev_limit_;
+ // Prevent heap allocation or illegal handle scopes.
+ void* operator new(size_t size) = delete;
+ void operator delete(void* size_t) = delete;
// Close the handle scope resetting limits to a previous state.
- static inline void CloseScope(Isolate* isolate,
- Object** prev_next,
- Object** prev_limit);
+ static void CloseScope(Isolate* isolate, Object** prev_next,
+ Object** prev_limit);
// Extend the handle scope making room for more handles.
- static internal::Object** Extend(Isolate* isolate);
+ static Object** Extend(Isolate* isolate);
#ifdef ENABLE_HANDLE_ZAPPING
// Zaps the handles in the half-open interval [start, end).
static void ZapRange(Object** start, Object** end);
#endif
- friend class v8::HandleScope;
- friend class v8::internal::DeferredHandles;
- friend class v8::internal::HandleScopeImplementer;
- friend class v8::internal::Isolate;
-};
-
+ Isolate* const isolate_;
+ Object** prev_next_;
+ Object** prev_limit_;
-class DeferredHandles;
+ DISALLOW_COPY_AND_ASSIGN(HandleScope);
+};
class DeferredHandleScope {
@@ -267,32 +316,38 @@ class DeferredHandleScope {
// Seal off the current HandleScope so that new handles can only be created
// if a new HandleScope is entered.
-class SealHandleScope BASE_EMBEDDED {
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
+class SealHandleScope final {
public:
#ifndef DEBUG
explicit SealHandleScope(Isolate* isolate) {}
~SealHandleScope() {}
#else
- explicit inline SealHandleScope(Isolate* isolate);
- inline ~SealHandleScope();
+ explicit SealHandleScope(Isolate* isolate);
+ ~SealHandleScope();
+
private:
- Isolate* isolate_;
+ Isolate* const isolate_;
Object** limit_;
int level_;
-#endif
+#endif // DEBUG
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(SealHandleScope);
};
+
struct HandleScopeData {
internal::Object** next;
internal::Object** limit;
int level;
void Initialize() {
- next = limit = NULL;
+ next = limit = nullptr;
level = 0;
}
};
-} } // namespace v8::internal
+} // namespace internal
+} // namespace v8
#endif // V8_HANDLES_H_
« 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