Home | History | Annotate | Download | only in src
      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
      3 // found in the LICENSE file.
      4 
      5 #ifndef V8_HANDLES_H_
      6 #define V8_HANDLES_H_
      7 
      8 #include "src/objects.h"
      9 
     10 namespace v8 {
     11 namespace internal {
     12 
     13 // 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 
     18 template<typename T>
     19 class 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.
     56   template <class S> INLINE(bool ToHandle(Handle<S>* out)) {
     57     if (location_ == NULL) {
     58       *out = Handle<T>::null();
     59       return false;
     60     } else {
     61       *out = Handle<T>(location_);
     62       return true;
     63     }
     64   }
     65 
     66   bool is_null() const { return location_ == NULL; }
     67 
     68  protected:
     69   T** location_;
     70 
     71   // MaybeHandles of different classes are allowed to access each
     72   // other's location_.
     73   template<class S> friend class MaybeHandle;
     74 };
     75 
     76 // ----------------------------------------------------------------------------
     77 // A Handle provides a reference to an object that survives relocation by
     78 // the garbage collector.
     79 // Handles are only valid within a HandleScope.
     80 // When a handle is created for an object a cell is allocated in the heap.
     81 
     82 template<typename T>
     83 class Handle {
     84  public:
     85   INLINE(explicit Handle(T** location)) { location_ = location; }
     86   INLINE(explicit Handle(T* obj));
     87   INLINE(Handle(T* obj, Isolate* isolate));
     88 
     89   // TODO(yangguo): Values that contain empty handles should be declared as
     90   // MaybeHandle to force validation before being used as handles.
     91   INLINE(Handle()) : location_(NULL) { }
     92 
     93   // Constructor for handling automatic up casting.
     94   // Ex. Handle<JSFunction> can be passed when Handle<Object> is expected.
     95   template <class S> Handle(Handle<S> handle) {
     96 #ifdef DEBUG
     97     T* a = NULL;
     98     S* b = NULL;
     99     a = b;  // Fake assignment to enforce type checks.
    100     USE(a);
    101 #endif
    102     location_ = reinterpret_cast<T**>(handle.location_);
    103   }
    104 
    105   INLINE(T* operator->() const) { return operator*(); }
    106 
    107   // Check if this handle refers to the exact same object as the other handle.
    108   INLINE(bool is_identical_to(const Handle<T> other) const);
    109 
    110   // Provides the C++ dereference operator.
    111   INLINE(T* operator*() const);
    112 
    113   // Returns the address to where the raw pointer is stored.
    114   INLINE(T** location() const);
    115 
    116   template <class S> static Handle<T> cast(Handle<S> that) {
    117     T::cast(*reinterpret_cast<T**>(that.location_));
    118     return Handle<T>(reinterpret_cast<T**>(that.location_));
    119   }
    120 
    121   // TODO(yangguo): Values that contain empty handles should be declared as
    122   // MaybeHandle to force validation before being used as handles.
    123   static Handle<T> null() { return Handle<T>(); }
    124   bool is_null() const { return location_ == NULL; }
    125 
    126   // Closes the given scope, but lets this handle escape. See
    127   // implementation in api.h.
    128   inline Handle<T> EscapeFrom(v8::EscapableHandleScope* scope);
    129 
    130 #ifdef DEBUG
    131   enum DereferenceCheckMode { INCLUDE_DEFERRED_CHECK, NO_DEFERRED_CHECK };
    132 
    133   bool IsDereferenceAllowed(DereferenceCheckMode mode) const;
    134 #endif  // DEBUG
    135 
    136  private:
    137   T** location_;
    138 
    139   // Handles of different classes are allowed to access each other's location_.
    140   template<class S> friend class Handle;
    141 };
    142 
    143 
    144 // Convenience wrapper.
    145 template<class T>
    146 inline Handle<T> handle(T* t, Isolate* isolate) {
    147   return Handle<T>(t, isolate);
    148 }
    149 
    150 
    151 // Convenience wrapper.
    152 template<class T>
    153 inline Handle<T> handle(T* t) {
    154   return Handle<T>(t, t->GetIsolate());
    155 }
    156 
    157 
    158 // Key comparison function for Map handles.
    159 inline bool operator<(const Handle<Map>& lhs, const Handle<Map>& rhs) {
    160   // This is safe because maps don't move.
    161   return *lhs < *rhs;
    162 }
    163 
    164 
    165 class DeferredHandles;
    166 class HandleScopeImplementer;
    167 
    168 
    169 // A stack-allocated class that governs a number of local handles.
    170 // After a handle scope has been created, all local handles will be
    171 // allocated within that handle scope until either the handle scope is
    172 // deleted or another handle scope is created.  If there is already a
    173 // handle scope and a new one is created, all allocations will take
    174 // place in the new handle scope until it is deleted.  After that,
    175 // new handles will again be allocated in the original handle scope.
    176 //
    177 // After the handle scope of a local handle has been deleted the
    178 // garbage collector will no longer track the object stored in the
    179 // handle and may deallocate it.  The behavior of accessing a handle
    180 // for which the handle scope has been deleted is undefined.
    181 class HandleScope {
    182  public:
    183   explicit inline HandleScope(Isolate* isolate);
    184 
    185   inline ~HandleScope();
    186 
    187   // Counts the number of allocated handles.
    188   static int NumberOfHandles(Isolate* isolate);
    189 
    190   // Creates a new handle with the given value.
    191   template <typename T>
    192   static inline T** CreateHandle(Isolate* isolate, T* value);
    193 
    194   // Deallocates any extensions used by the current scope.
    195   static void DeleteExtensions(Isolate* isolate);
    196 
    197   static Address current_next_address(Isolate* isolate);
    198   static Address current_limit_address(Isolate* isolate);
    199   static Address current_level_address(Isolate* isolate);
    200 
    201   // Closes the HandleScope (invalidating all handles
    202   // created in the scope of the HandleScope) and returns
    203   // a Handle backed by the parent scope holding the
    204   // value of the argument handle.
    205   template <typename T>
    206   Handle<T> CloseAndEscape(Handle<T> handle_value);
    207 
    208   Isolate* isolate() { return isolate_; }
    209 
    210  private:
    211   // Prevent heap allocation or illegal handle scopes.
    212   HandleScope(const HandleScope&);
    213   void operator=(const HandleScope&);
    214   void* operator new(size_t size);
    215   void operator delete(void* size_t);
    216 
    217   Isolate* isolate_;
    218   Object** prev_next_;
    219   Object** prev_limit_;
    220 
    221   // Close the handle scope resetting limits to a previous state.
    222   static inline void CloseScope(Isolate* isolate,
    223                                 Object** prev_next,
    224                                 Object** prev_limit);
    225 
    226   // Extend the handle scope making room for more handles.
    227   static internal::Object** Extend(Isolate* isolate);
    228 
    229 #ifdef ENABLE_HANDLE_ZAPPING
    230   // Zaps the handles in the half-open interval [start, end).
    231   static void ZapRange(Object** start, Object** end);
    232 #endif
    233 
    234   friend class v8::HandleScope;
    235   friend class v8::internal::DeferredHandles;
    236   friend class v8::internal::HandleScopeImplementer;
    237   friend class v8::internal::Isolate;
    238 };
    239 
    240 
    241 class DeferredHandles;
    242 
    243 
    244 class DeferredHandleScope {
    245  public:
    246   explicit DeferredHandleScope(Isolate* isolate);
    247   // The DeferredHandles object returned stores the Handles created
    248   // since the creation of this DeferredHandleScope.  The Handles are
    249   // alive as long as the DeferredHandles object is alive.
    250   DeferredHandles* Detach();
    251   ~DeferredHandleScope();
    252 
    253  private:
    254   Object** prev_limit_;
    255   Object** prev_next_;
    256   HandleScopeImplementer* impl_;
    257 
    258 #ifdef DEBUG
    259   bool handles_detached_;
    260   int prev_level_;
    261 #endif
    262 
    263   friend class HandleScopeImplementer;
    264 };
    265 
    266 
    267 // Seal off the current HandleScope so that new handles can only be created
    268 // if a new HandleScope is entered.
    269 class SealHandleScope BASE_EMBEDDED {
    270  public:
    271 #ifndef DEBUG
    272   explicit SealHandleScope(Isolate* isolate) {}
    273   ~SealHandleScope() {}
    274 #else
    275   explicit inline SealHandleScope(Isolate* isolate);
    276   inline ~SealHandleScope();
    277  private:
    278   Isolate* isolate_;
    279   Object** limit_;
    280   int level_;
    281 #endif
    282 };
    283 
    284 struct HandleScopeData {
    285   internal::Object** next;
    286   internal::Object** limit;
    287   int level;
    288 
    289   void Initialize() {
    290     next = limit = NULL;
    291     level = 0;
    292   }
    293 };
    294 
    295 } }  // namespace v8::internal
    296 
    297 #endif  // V8_HANDLES_H_
    298