LCOV - code coverage report
Current view: top level - src - handles.h (source / functions) Hit Total Coverage
Test: app.info Lines: 27 27 100.0 %
Date: 2017-04-26 Functions: 60 68 88.2 %

          Line data    Source code
       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 <type_traits>
       9             : 
      10             : #include "include/v8.h"
      11             : #include "src/base/functional.h"
      12             : #include "src/base/macros.h"
      13             : #include "src/checks.h"
      14             : #include "src/globals.h"
      15             : #include "src/zone/zone.h"
      16             : 
      17             : namespace v8 {
      18             : namespace internal {
      19             : 
      20             : // Forward declarations.
      21             : class DeferredHandles;
      22             : class HandleScopeImplementer;
      23             : class Isolate;
      24             : class Object;
      25             : 
      26             : 
      27             : // ----------------------------------------------------------------------------
      28             : // Base class for Handle instantiations.  Don't use directly.
      29             : class HandleBase {
      30             :  public:
      31  1385190364 :   V8_INLINE explicit HandleBase(Object** location) : location_(location) {}
      32             :   V8_INLINE explicit HandleBase(Object* object, Isolate* isolate);
      33             : 
      34             :   // Check if this handle refers to the exact same object as the other handle.
      35             :   V8_INLINE bool is_identical_to(const HandleBase that) const {
      36             :     // Dereferencing deferred handles to check object equality is safe.
      37             :     SLOW_DCHECK((this->location_ == nullptr ||
      38             :                  this->IsDereferenceAllowed(NO_DEFERRED_CHECK)) &&
      39             :                 (that.location_ == nullptr ||
      40             :                  that.IsDereferenceAllowed(NO_DEFERRED_CHECK)));
      41   916666181 :     if (this->location_ == that.location_) return true;
      42   868325458 :     if (this->location_ == NULL || that.location_ == NULL) return false;
      43   867981728 :     return *this->location_ == *that.location_;
      44             :   }
      45             : 
      46   811868584 :   V8_INLINE bool is_null() const { return location_ == nullptr; }
      47             : 
      48             :   // Returns the raw address where this handle is stored. This should only be
      49             :   // used for hashing handles; do not ever try to dereference it.
      50    27599562 :   V8_INLINE Address address() const { return bit_cast<Address>(location_); }
      51             : 
      52             :  protected:
      53             :   // Provides the C++ dereference operator.
      54             :   V8_INLINE Object* operator*() const {
      55             :     SLOW_DCHECK(IsDereferenceAllowed(INCLUDE_DEFERRED_CHECK));
      56 28548732385 :     return *location_;
      57             :   }
      58             : 
      59             :   // Returns the address to where the raw pointer is stored.
      60             :   V8_INLINE Object** location() const {
      61             :     SLOW_DCHECK(location_ == nullptr ||
      62             :                 IsDereferenceAllowed(INCLUDE_DEFERRED_CHECK));
      63   112599568 :     return location_;
      64             :   }
      65             : 
      66             :   enum DereferenceCheckMode { INCLUDE_DEFERRED_CHECK, NO_DEFERRED_CHECK };
      67             : #ifdef DEBUG
      68             :   bool V8_EXPORT_PRIVATE IsDereferenceAllowed(DereferenceCheckMode mode) const;
      69             : #else
      70             :   V8_INLINE
      71             :   bool V8_EXPORT_PRIVATE IsDereferenceAllowed(DereferenceCheckMode mode) const {
      72             :     return true;
      73             :   }
      74             : #endif  // DEBUG
      75             : 
      76             :   Object** location_;
      77             : };
      78             : 
      79             : 
      80             : // ----------------------------------------------------------------------------
      81             : // A Handle provides a reference to an object that survives relocation by
      82             : // the garbage collector.
      83             : //
      84             : // Handles are only valid within a HandleScope. When a handle is created
      85             : // for an object a cell is allocated in the current HandleScope.
      86             : //
      87             : // Also note that Handles do not provide default equality comparison or hashing
      88             : // operators on purpose. Such operators would be misleading, because intended
      89             : // semantics is ambiguous between Handle location and object identity. Instead
      90             : // use either {is_identical_to} or {location} explicitly.
      91             : template <typename T>
      92             : class Handle final : public HandleBase {
      93             :  public:
      94             :   V8_INLINE explicit Handle(T** location = nullptr)
      95             :       : HandleBase(reinterpret_cast<Object**>(location)) {
      96             :     // Type check:
      97             :     static_assert(std::is_base_of<Object, T>::value, "static type violation");
      98             :   }
      99             : 
     100   833460629 :   V8_INLINE explicit Handle(T* object) : Handle(object, object->GetIsolate()) {}
     101             :   V8_INLINE Handle(T* object, Isolate* isolate);
     102             : 
     103             :   // Allocate a new handle for the object, do not canonicalize.
     104             :   V8_INLINE static Handle<T> New(T* object, Isolate* isolate);
     105             : 
     106             :   // Constructor for handling automatic up casting.
     107             :   // Ex. Handle<JSFunction> can be passed when Handle<Object> is expected.
     108             :   template <typename S>
     109   892641731 :   V8_INLINE Handle(Handle<S> handle) : HandleBase(handle) {
     110             :     // Type check:
     111             :     static_assert(std::is_base_of<T, S>::value, "static type violation");
     112             :   }
     113             : 
     114             :   V8_INLINE T* operator->() const { return operator*(); }
     115             : 
     116             :   // Provides the C++ dereference operator.
     117             :   V8_INLINE T* operator*() const {
     118             :     return reinterpret_cast<T*>(HandleBase::operator*());
     119             :   }
     120             : 
     121             :   // Returns the address to where the raw pointer is stored.
     122             :   V8_INLINE T** location() const {
     123             :     return reinterpret_cast<T**>(HandleBase::location());
     124             :   }
     125             : 
     126             :   template <typename S>
     127    30066017 :   static const Handle<T> cast(Handle<S> that) {
     128      211805 :     T::cast(*reinterpret_cast<T**>(that.location_));
     129    30066017 :     return Handle<T>(reinterpret_cast<T**>(that.location_));
     130             :   }
     131             : 
     132             :   // TODO(yangguo): Values that contain empty handles should be declared as
     133             :   // MaybeHandle to force validation before being used as handles.
     134    31105196 :   static const Handle<T> null() { return Handle<T>(); }
     135             : 
     136             :   // Provide function object for location equality comparison.
     137             :   struct equal_to : public std::binary_function<Handle<T>, Handle<T>, bool> {
     138             :     V8_INLINE bool operator()(Handle<T> lhs, Handle<T> rhs) const {
     139      846104 :       return lhs.address() == rhs.address();
     140             :     }
     141             :   };
     142             : 
     143             :   // Provide function object for location hashing.
     144             :   struct hash : public std::unary_function<Handle<T>, size_t> {
     145             :     V8_INLINE size_t operator()(Handle<T> const& handle) const {
     146             :       return base::hash<void*>()(handle.address());
     147             :     }
     148             :   };
     149             : 
     150             :  private:
     151             :   // Handles of different classes are allowed to access each other's location_.
     152             :   template <typename>
     153             :   friend class Handle;
     154             :   // MaybeHandle is allowed to access location_.
     155             :   template <typename>
     156             :   friend class MaybeHandle;
     157             : };
     158             : 
     159             : template <typename T>
     160             : inline std::ostream& operator<<(std::ostream& os, Handle<T> handle);
     161             : 
     162             : template <typename T>
     163             : V8_INLINE Handle<T> handle(T* object, Isolate* isolate) {
     164             :   return Handle<T>(object, isolate);
     165             : }
     166             : 
     167             : template <typename T>
     168             : V8_INLINE Handle<T> handle(T* object) {
     169             :   return Handle<T>(object);
     170             : }
     171             : 
     172             : 
     173             : // ----------------------------------------------------------------------------
     174             : // A Handle can be converted into a MaybeHandle. Converting a MaybeHandle
     175             : // into a Handle requires checking that it does not point to NULL.  This
     176             : // ensures NULL checks before use.
     177             : //
     178             : // Also note that Handles do not provide default equality comparison or hashing
     179             : // operators on purpose. Such operators would be misleading, because intended
     180             : // semantics is ambiguous between Handle location and object identity.
     181             : template <typename T>
     182             : class MaybeHandle final {
     183             :  public:
     184    67365720 :   V8_INLINE MaybeHandle() {}
     185             :   V8_INLINE ~MaybeHandle() {}
     186             : 
     187             :   // Constructor for handling automatic up casting from Handle.
     188             :   // Ex. Handle<JSArray> can be passed when MaybeHandle<Object> is expected.
     189             :   template <typename S>
     190             :   V8_INLINE MaybeHandle(Handle<S> handle)
     191  1146227281 :       : location_(reinterpret_cast<T**>(handle.location_)) {
     192             :     // Type check:
     193             :     static_assert(std::is_base_of<T, S>::value, "static type violation");
     194             :   }
     195             : 
     196             :   // Constructor for handling automatic up casting.
     197             :   // Ex. MaybeHandle<JSArray> can be passed when Handle<Object> is expected.
     198             :   template <typename S>
     199             :   V8_INLINE MaybeHandle(MaybeHandle<S> maybe_handle)
     200    12475937 :       : location_(reinterpret_cast<T**>(maybe_handle.location_)) {
     201             :     // Type check:
     202             :     static_assert(std::is_base_of<T, S>::value, "static type violation");
     203             :   }
     204             : 
     205             :   template <typename S>
     206             :   V8_INLINE MaybeHandle(S* object, Isolate* isolate)
     207             :       : MaybeHandle(handle(object, isolate)) {}
     208             : 
     209             :   V8_INLINE void Assert() const { DCHECK_NOT_NULL(location_); }
     210   284492818 :   V8_INLINE void Check() const { CHECK_NOT_NULL(location_); }
     211             : 
     212             :   V8_INLINE Handle<T> ToHandleChecked() const {
     213             :     Check();
     214             :     return Handle<T>(location_);
     215             :   }
     216             : 
     217             :   // Convert to a Handle with a type that can be upcasted to.
     218             :   template <typename S>
     219             :   V8_INLINE bool ToHandle(Handle<S>* out) const {
     220   864121389 :     if (location_ == nullptr) {
     221    29655524 :       *out = Handle<T>::null();
     222             :       return false;
     223             :     } else {
     224    51976625 :       *out = Handle<T>(location_);
     225             :       return true;
     226             :     }
     227             :   }
     228             : 
     229             :   // Returns the raw address where this handle is stored. This should only be
     230             :   // used for hashing handles; do not ever try to dereference it.
     231       17534 :   V8_INLINE Address address() const { return bit_cast<Address>(location_); }
     232             : 
     233    38488657 :   bool is_null() const { return location_ == nullptr; }
     234             : 
     235             :  protected:
     236             :   T** location_ = nullptr;
     237             : 
     238             :   // MaybeHandles of different classes are allowed to access each
     239             :   // other's location_.
     240             :   template <typename>
     241             :   friend class MaybeHandle;
     242             : };
     243             : 
     244             : 
     245             : // ----------------------------------------------------------------------------
     246             : // A stack-allocated class that governs a number of local handles.
     247             : // After a handle scope has been created, all local handles will be
     248             : // allocated within that handle scope until either the handle scope is
     249             : // deleted or another handle scope is created.  If there is already a
     250             : // handle scope and a new one is created, all allocations will take
     251             : // place in the new handle scope until it is deleted.  After that,
     252             : // new handles will again be allocated in the original handle scope.
     253             : //
     254             : // After the handle scope of a local handle has been deleted the
     255             : // garbage collector will no longer track the object stored in the
     256             : // handle and may deallocate it.  The behavior of accessing a handle
     257             : // for which the handle scope has been deleted is undefined.
     258             : class HandleScope {
     259             :  public:
     260             :   explicit inline HandleScope(Isolate* isolate);
     261             : 
     262             :   inline ~HandleScope();
     263             : 
     264             :   // Counts the number of allocated handles.
     265             :   V8_EXPORT_PRIVATE static int NumberOfHandles(Isolate* isolate);
     266             : 
     267             :   // Create a new handle or lookup a canonical handle.
     268             :   V8_INLINE static Object** GetHandle(Isolate* isolate, Object* value);
     269             : 
     270             :   // Creates a new handle with the given value.
     271             :   V8_INLINE static Object** CreateHandle(Isolate* isolate, Object* value);
     272             : 
     273             :   // Deallocates any extensions used by the current scope.
     274             :   V8_EXPORT_PRIVATE static void DeleteExtensions(Isolate* isolate);
     275             : 
     276             :   static Address current_next_address(Isolate* isolate);
     277             :   static Address current_limit_address(Isolate* isolate);
     278             :   static Address current_level_address(Isolate* isolate);
     279             : 
     280             :   // Closes the HandleScope (invalidating all handles
     281             :   // created in the scope of the HandleScope) and returns
     282             :   // a Handle backed by the parent scope holding the
     283             :   // value of the argument handle.
     284             :   template <typename T>
     285             :   Handle<T> CloseAndEscape(Handle<T> handle_value);
     286             : 
     287             :   Isolate* isolate() { return isolate_; }
     288             : 
     289             :   // Limit for number of handles with --check-handle-count. This is
     290             :   // large enough to compile natives and pass unit tests with some
     291             :   // slack for future changes to natives.
     292             :   static const int kCheckHandleThreshold = 30 * 1024;
     293             : 
     294             :  private:
     295             :   // Prevent heap allocation or illegal handle scopes.
     296             :   void* operator new(size_t size);
     297             :   void operator delete(void* size_t);
     298             : 
     299             :   Isolate* isolate_;
     300             :   Object** prev_next_;
     301             :   Object** prev_limit_;
     302             : 
     303             :   // Close the handle scope resetting limits to a previous state.
     304             :   static inline void CloseScope(Isolate* isolate,
     305             :                                 Object** prev_next,
     306             :                                 Object** prev_limit);
     307             : 
     308             :   // Extend the handle scope making room for more handles.
     309             :   V8_EXPORT_PRIVATE static Object** Extend(Isolate* isolate);
     310             : 
     311             : #ifdef ENABLE_HANDLE_ZAPPING
     312             :   // Zaps the handles in the half-open interval [start, end).
     313             :   V8_EXPORT_PRIVATE static void ZapRange(Object** start, Object** end);
     314             : #endif
     315             : 
     316             :   friend class v8::HandleScope;
     317             :   friend class DeferredHandles;
     318             :   friend class DeferredHandleScope;
     319             :   friend class HandleScopeImplementer;
     320             :   friend class Isolate;
     321             : 
     322             :   DISALLOW_COPY_AND_ASSIGN(HandleScope);
     323             : };
     324             : 
     325             : 
     326             : // Forward declarations for CanonicalHandleScope.
     327             : template <typename V, class AllocationPolicy>
     328             : class IdentityMap;
     329             : class RootIndexMap;
     330             : 
     331             : 
     332             : // A CanonicalHandleScope does not open a new HandleScope. It changes the
     333             : // existing HandleScope so that Handles created within are canonicalized.
     334             : // This does not apply to nested inner HandleScopes unless a nested
     335             : // CanonicalHandleScope is introduced. Handles are only canonicalized within
     336             : // the same CanonicalHandleScope, but not across nested ones.
     337             : class V8_EXPORT_PRIVATE CanonicalHandleScope final {
     338             :  public:
     339             :   explicit CanonicalHandleScope(Isolate* isolate);
     340             :   ~CanonicalHandleScope();
     341             : 
     342             :  private:
     343             :   Object** Lookup(Object* object);
     344             : 
     345             :   Isolate* isolate_;
     346             :   Zone zone_;
     347             :   RootIndexMap* root_index_map_;
     348             :   IdentityMap<Object**, ZoneAllocationPolicy>* identity_map_;
     349             :   // Ordinary nested handle scopes within the current one are not canonical.
     350             :   int canonical_level_;
     351             :   // We may have nested canonical scopes. Handles are canonical within each one.
     352             :   CanonicalHandleScope* prev_canonical_scope_;
     353             : 
     354             :   friend class HandleScope;
     355             : };
     356             : 
     357             : // A DeferredHandleScope is a HandleScope in which handles are not destroyed
     358             : // when the DeferredHandleScope is left. Instead the DeferredHandleScope has to
     359             : // be detached with {Detach}, and the result of {Detach} has to be destroyed
     360             : // explicitly. A DeferredHandleScope should only be used with the following
     361             : // design pattern:
     362             : // 1) Open a HandleScope (not a DeferredHandleScope).
     363             : //    HandleScope scope(isolate_);
     364             : // 2) Create handles.
     365             : //    Handle<Object> h1 = handle(object1, isolate);
     366             : //    Handle<Object> h2 = handle(object2, isolate);
     367             : // 3) Open a DeferredHandleScope.
     368             : //    DeferredHandleScope deferred_scope(isolate);
     369             : // 4) Reopen handles which should be in the DeferredHandleScope, e.g only h1.
     370             : //    h1 = handle(*h1, isolate);
     371             : // 5) Detach the DeferredHandleScope.
     372             : //    DeferredHandles* deferred_handles = deferred_scope.Detach();
     373             : // 6) Destroy the deferred handles.
     374             : //    delete deferred_handles;
     375             : //
     376             : // Note: A DeferredHandleScope must not be opened within a DeferredHandleScope.
     377             : class V8_EXPORT_PRIVATE DeferredHandleScope final {
     378             :  public:
     379             :   explicit DeferredHandleScope(Isolate* isolate);
     380             :   // The DeferredHandles object returned stores the Handles created
     381             :   // since the creation of this DeferredHandleScope.  The Handles are
     382             :   // alive as long as the DeferredHandles object is alive.
     383             :   DeferredHandles* Detach();
     384             :   ~DeferredHandleScope();
     385             : 
     386             :  private:
     387             :   Object** prev_limit_;
     388             :   Object** prev_next_;
     389             :   HandleScopeImplementer* impl_;
     390             : 
     391             : #ifdef DEBUG
     392             :   bool handles_detached_ = false;
     393             :   int prev_level_;
     394             : #endif
     395             : 
     396             :   friend class HandleScopeImplementer;
     397             : };
     398             : 
     399             : 
     400             : // Seal off the current HandleScope so that new handles can only be created
     401             : // if a new HandleScope is entered.
     402             : class SealHandleScope final {
     403             :  public:
     404             : #ifndef DEBUG
     405             :   explicit SealHandleScope(Isolate* isolate) {}
     406             :   ~SealHandleScope() {}
     407             : #else
     408             :   explicit inline SealHandleScope(Isolate* isolate);
     409             :   inline ~SealHandleScope();
     410             :  private:
     411             :   Isolate* isolate_;
     412             :   Object** prev_limit_;
     413             :   int prev_sealed_level_;
     414             : #endif
     415             : };
     416             : 
     417             : 
     418             : struct HandleScopeData final {
     419             :   Object** next;
     420             :   Object** limit;
     421             :   int level;
     422             :   int sealed_level;
     423             :   CanonicalHandleScope* canonical_scope;
     424             : 
     425             :   void Initialize() {
     426       83356 :     next = limit = NULL;
     427       83356 :     sealed_level = level = 0;
     428       83356 :     canonical_scope = NULL;
     429             :   }
     430             : };
     431             : 
     432             : }  // namespace internal
     433             : }  // namespace v8
     434             : 
     435             : #endif  // V8_HANDLES_H_

Generated by: LCOV version 1.10