LCOV - code coverage report
Current view: top level - src - handles.h (source / functions) Hit Total Coverage
Test: app.info Lines: 15 15 100.0 %
Date: 2019-04-17 Functions: 22 33 66.7 %

          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             : template <typename T>
      25             : class MaybeHandle;
      26             : class Object;
      27             : class OrderedHashMap;
      28             : class OrderedHashSet;
      29             : class OrderedNameDictionary;
      30             : class SmallOrderedHashMap;
      31             : class SmallOrderedHashSet;
      32             : class SmallOrderedNameDictionary;
      33             : class WasmExportedFunctionData;
      34             : 
      35             : // ----------------------------------------------------------------------------
      36             : // Base class for Handle instantiations.  Don't use directly.
      37             : class HandleBase {
      38             :  public:
      39   944283885 :   V8_INLINE explicit HandleBase(Address* location) : location_(location) {}
      40             :   V8_INLINE explicit HandleBase(Address object, Isolate* isolate);
      41             : 
      42             :   // Check if this handle refers to the exact same object as the other handle.
      43             :   V8_INLINE bool is_identical_to(const HandleBase that) const {
      44             :     // Dereferencing deferred handles to check object equality is safe.
      45             :     SLOW_DCHECK((this->location_ == nullptr ||
      46             :                  this->IsDereferenceAllowed(NO_DEFERRED_CHECK)) &&
      47             :                 (that.location_ == nullptr ||
      48             :                  that.IsDereferenceAllowed(NO_DEFERRED_CHECK)));
      49    35922902 :     if (this->location_ == that.location_) return true;
      50    23332953 :     if (this->location_ == nullptr || that.location_ == nullptr) return false;
      51    23292419 :     return *this->location_ == *that.location_;
      52             :   }
      53             : 
      54   490521868 :   V8_INLINE bool is_null() const { return location_ == nullptr; }
      55             : 
      56             :   // Returns the raw address where this handle is stored. This should only be
      57             :   // used for hashing handles; do not ever try to dereference it.
      58             :   V8_INLINE Address address() const { return bit_cast<Address>(location_); }
      59             : 
      60             :  protected:
      61             :   // Provides the C++ dereference operator.
      62             :   V8_INLINE Address operator*() const {
      63             :     SLOW_DCHECK(IsDereferenceAllowed(INCLUDE_DEFERRED_CHECK));
      64 23578972615 :     return *location_;
      65             :   }
      66             : 
      67             :   // Returns the address to where the raw pointer is stored.
      68             :   V8_INLINE Address* location() const {
      69             :     SLOW_DCHECK(location_ == nullptr ||
      70             :                 IsDereferenceAllowed(INCLUDE_DEFERRED_CHECK));
      71    49601623 :     return location_;
      72             :   }
      73             : 
      74             :   enum DereferenceCheckMode { INCLUDE_DEFERRED_CHECK, NO_DEFERRED_CHECK };
      75             : #ifdef DEBUG
      76             :   bool V8_EXPORT_PRIVATE IsDereferenceAllowed(DereferenceCheckMode mode) const;
      77             : #else
      78             :   V8_INLINE
      79             :   bool V8_EXPORT_PRIVATE IsDereferenceAllowed(DereferenceCheckMode mode) const {
      80             :     return true;
      81             :   }
      82             : #endif  // DEBUG
      83             : 
      84             :   // This uses type Address* as opposed to a pointer type to a typed
      85             :   // wrapper class, because it doesn't point to instances of such a
      86             :   // wrapper class. Design overview: https://goo.gl/Ph4CGz
      87             :   Address* location_;
      88             : };
      89             : 
      90             : 
      91             : // ----------------------------------------------------------------------------
      92             : // A Handle provides a reference to an object that survives relocation by
      93             : // the garbage collector.
      94             : //
      95             : // Handles are only valid within a HandleScope. When a handle is created
      96             : // for an object a cell is allocated in the current HandleScope.
      97             : //
      98             : // Also note that Handles do not provide default equality comparison or hashing
      99             : // operators on purpose. Such operators would be misleading, because intended
     100             : // semantics is ambiguous between Handle location and object identity. Instead
     101             : // use either {is_identical_to} or {location} explicitly.
     102             : template <typename T>
     103             : class Handle final : public HandleBase {
     104             :  public:
     105             :   V8_INLINE explicit Handle(Address* location = nullptr)
     106             :       : HandleBase(location) {
     107             :     // Type check:
     108             :     static_assert(std::is_convertible<T*, Object*>::value,
     109             :                   "static type violation");
     110             :     // TODO(jkummerow): Runtime type check here as a SLOW_DCHECK?
     111             :   }
     112             : 
     113             :   V8_INLINE Handle(T object, Isolate* isolate);
     114             : 
     115             :   // Allocate a new handle for the object, do not canonicalize.
     116             :   V8_INLINE static Handle<T> New(T object, Isolate* isolate);
     117             : 
     118             :   // Constructor for handling automatic up casting.
     119             :   // Ex. Handle<JSFunction> can be passed when Handle<Object> is expected.
     120             :   template <typename S, typename = typename std::enable_if<
     121             :                             std::is_convertible<S*, T*>::value>::type>
     122   645262530 :   V8_INLINE Handle(Handle<S> handle) : HandleBase(handle) {}
     123             : 
     124             :   V8_INLINE T operator->() const {
     125             :     return operator*();
     126             :   }
     127             : 
     128             :   // Provides the C++ dereference operator.
     129             :   V8_INLINE T operator*() const {
     130             :     // unchecked_cast because we rather trust Handle<T> to contain a T than
     131             :     // include all the respective -inl.h headers for SLOW_DCHECKs.
     132     2684571 :     return T::unchecked_cast(Object(HandleBase::operator*()));
     133             :   }
     134             : 
     135             :   // Returns the address to where the raw pointer is stored.
     136             :   V8_INLINE Address* location() const { return HandleBase::location(); }
     137             : 
     138             :   template <typename S>
     139             :   inline static const Handle<T> cast(Handle<S> that);
     140             : 
     141             :   // TODO(yangguo): Values that contain empty handles should be declared as
     142             :   // MaybeHandle to force validation before being used as handles.
     143    10792605 :   static const Handle<T> null() { return Handle<T>(); }
     144             : 
     145             :   // Location equality.
     146     3844327 :   bool equals(Handle<T> other) const { return address() == other.address(); }
     147             : 
     148             :   // Provide function object for location equality comparison.
     149             :   struct equal_to {
     150             :     V8_INLINE bool operator()(Handle<T> lhs, Handle<T> rhs) const {
     151     3844327 :       return lhs.equals(rhs);
     152             :     }
     153             :   };
     154             : 
     155             :   // Provide function object for location hashing.
     156             :   struct hash {
     157             :     V8_INLINE size_t operator()(Handle<T> const& handle) const {
     158             :       return base::hash<Address>()(handle.address());
     159             :     }
     160             :   };
     161             : 
     162             :  private:
     163             :   // Handles of different classes are allowed to access each other's location_.
     164             :   template <typename>
     165             :   friend class Handle;
     166             :   // MaybeHandle is allowed to access location_.
     167             :   template <typename>
     168             :   friend class MaybeHandle;
     169             : };
     170             : 
     171             : template <typename T>
     172             : inline std::ostream& operator<<(std::ostream& os, Handle<T> handle);
     173             : 
     174             : // ----------------------------------------------------------------------------
     175             : // A stack-allocated class that governs a number of local handles.
     176             : // After a handle scope has been created, all local handles will be
     177             : // allocated within that handle scope until either the handle scope is
     178             : // deleted or another handle scope is created.  If there is already a
     179             : // handle scope and a new one is created, all allocations will take
     180             : // place in the new handle scope until it is deleted.  After that,
     181             : // new handles will again be allocated in the original handle scope.
     182             : //
     183             : // After the handle scope of a local handle has been deleted the
     184             : // garbage collector will no longer track the object stored in the
     185             : // handle and may deallocate it.  The behavior of accessing a handle
     186             : // for which the handle scope has been deleted is undefined.
     187             : class HandleScope {
     188             :  public:
     189             :   explicit inline HandleScope(Isolate* isolate);
     190             : 
     191             :   inline ~HandleScope();
     192             : 
     193             :   // Counts the number of allocated handles.
     194             :   V8_EXPORT_PRIVATE static int NumberOfHandles(Isolate* isolate);
     195             : 
     196             :   // Create a new handle or lookup a canonical handle.
     197             :   V8_INLINE static Address* GetHandle(Isolate* isolate, Address value);
     198             : 
     199             :   // Creates a new handle with the given value.
     200             :   V8_INLINE static Address* CreateHandle(Isolate* isolate, Address value);
     201             : 
     202             :   // Deallocates any extensions used by the current scope.
     203             :   V8_EXPORT_PRIVATE static void DeleteExtensions(Isolate* isolate);
     204             : 
     205             :   static Address current_next_address(Isolate* isolate);
     206             :   static Address current_limit_address(Isolate* isolate);
     207             :   static Address current_level_address(Isolate* isolate);
     208             : 
     209             :   // Closes the HandleScope (invalidating all handles
     210             :   // created in the scope of the HandleScope) and returns
     211             :   // a Handle backed by the parent scope holding the
     212             :   // value of the argument handle.
     213             :   template <typename T>
     214             :   Handle<T> CloseAndEscape(Handle<T> handle_value);
     215             : 
     216             :   Isolate* isolate() { return isolate_; }
     217             : 
     218             :   // Limit for number of handles with --check-handle-count. This is
     219             :   // large enough to compile natives and pass unit tests with some
     220             :   // slack for future changes to natives.
     221             :   static const int kCheckHandleThreshold = 30 * 1024;
     222             : 
     223             :  private:
     224             :   // Prevent heap allocation or illegal handle scopes.
     225             :   void* operator new(size_t size);
     226             :   void operator delete(void* size_t);
     227             : 
     228             :   Isolate* isolate_;
     229             :   Address* prev_next_;
     230             :   Address* prev_limit_;
     231             : 
     232             :   // Close the handle scope resetting limits to a previous state.
     233             :   static inline void CloseScope(Isolate* isolate, Address* prev_next,
     234             :                                 Address* prev_limit);
     235             : 
     236             :   // Extend the handle scope making room for more handles.
     237             :   V8_EXPORT_PRIVATE static Address* Extend(Isolate* isolate);
     238             : 
     239             : #ifdef ENABLE_HANDLE_ZAPPING
     240             :   // Zaps the handles in the half-open interval [start, end).
     241             :   V8_EXPORT_PRIVATE static void ZapRange(Address* start, Address* end);
     242             : #endif
     243             : 
     244             :   friend class v8::HandleScope;
     245             :   friend class DeferredHandles;
     246             :   friend class DeferredHandleScope;
     247             :   friend class HandleScopeImplementer;
     248             :   friend class Isolate;
     249             : 
     250             :   DISALLOW_COPY_AND_ASSIGN(HandleScope);
     251             : };
     252             : 
     253             : 
     254             : // Forward declarations for CanonicalHandleScope.
     255             : template <typename V, class AllocationPolicy>
     256             : class IdentityMap;
     257             : class RootIndexMap;
     258             : 
     259             : 
     260             : // A CanonicalHandleScope does not open a new HandleScope. It changes the
     261             : // existing HandleScope so that Handles created within are canonicalized.
     262             : // This does not apply to nested inner HandleScopes unless a nested
     263             : // CanonicalHandleScope is introduced. Handles are only canonicalized within
     264             : // the same CanonicalHandleScope, but not across nested ones.
     265             : class V8_EXPORT_PRIVATE CanonicalHandleScope final {
     266             :  public:
     267             :   explicit CanonicalHandleScope(Isolate* isolate);
     268             :   ~CanonicalHandleScope();
     269             : 
     270             :  private:
     271             :   Address* Lookup(Address object);
     272             : 
     273             :   Isolate* isolate_;
     274             :   Zone zone_;
     275             :   RootIndexMap* root_index_map_;
     276             :   IdentityMap<Address*, ZoneAllocationPolicy>* identity_map_;
     277             :   // Ordinary nested handle scopes within the current one are not canonical.
     278             :   int canonical_level_;
     279             :   // We may have nested canonical scopes. Handles are canonical within each one.
     280             :   CanonicalHandleScope* prev_canonical_scope_;
     281             : 
     282             :   friend class HandleScope;
     283             : };
     284             : 
     285             : // A DeferredHandleScope is a HandleScope in which handles are not destroyed
     286             : // when the DeferredHandleScope is left. Instead the DeferredHandleScope has to
     287             : // be detached with {Detach}, and the result of {Detach} has to be destroyed
     288             : // explicitly. A DeferredHandleScope should only be used with the following
     289             : // design pattern:
     290             : // 1) Open a HandleScope (not a DeferredHandleScope).
     291             : //    HandleScope scope(isolate_);
     292             : // 2) Create handles.
     293             : //    Handle<Object> h1 = handle(object1, isolate);
     294             : //    Handle<Object> h2 = handle(object2, isolate);
     295             : // 3) Open a DeferredHandleScope.
     296             : //    DeferredHandleScope deferred_scope(isolate);
     297             : // 4) Reopen handles which should be in the DeferredHandleScope, e.g only h1.
     298             : //    h1 = handle(*h1, isolate);
     299             : // 5) Detach the DeferredHandleScope.
     300             : //    DeferredHandles* deferred_handles = deferred_scope.Detach();
     301             : // 6) Destroy the deferred handles.
     302             : //    delete deferred_handles;
     303             : //
     304             : // Note: A DeferredHandleScope must not be opened within a DeferredHandleScope.
     305             : class V8_EXPORT_PRIVATE DeferredHandleScope final {
     306             :  public:
     307             :   explicit DeferredHandleScope(Isolate* isolate);
     308             :   // The DeferredHandles object returned stores the Handles created
     309             :   // since the creation of this DeferredHandleScope.  The Handles are
     310             :   // alive as long as the DeferredHandles object is alive.
     311             :   DeferredHandles* Detach();
     312             :   ~DeferredHandleScope();
     313             : 
     314             :  private:
     315             :   Address* prev_limit_;
     316             :   Address* prev_next_;
     317             :   HandleScopeImplementer* impl_;
     318             : 
     319             : #ifdef DEBUG
     320             :   bool handles_detached_ = false;
     321             :   int prev_level_;
     322             : #endif
     323             : 
     324             :   friend class HandleScopeImplementer;
     325             : };
     326             : 
     327             : 
     328             : // Seal off the current HandleScope so that new handles can only be created
     329             : // if a new HandleScope is entered.
     330             : class SealHandleScope final {
     331             :  public:
     332             : #ifndef DEBUG
     333             :   explicit SealHandleScope(Isolate* isolate) {}
     334             :   ~SealHandleScope() = default;
     335             : #else
     336             :   explicit inline SealHandleScope(Isolate* isolate);
     337             :   inline ~SealHandleScope();
     338             :  private:
     339             :   Isolate* isolate_;
     340             :   Address* prev_limit_;
     341             :   int prev_sealed_level_;
     342             : #endif
     343             : };
     344             : 
     345             : 
     346             : struct HandleScopeData final {
     347             :   Address* next;
     348             :   Address* limit;
     349             :   int level;
     350             :   int sealed_level;
     351             :   CanonicalHandleScope* canonical_scope;
     352             : 
     353             :   void Initialize() {
     354       94878 :     next = limit = nullptr;
     355       94878 :     sealed_level = level = 0;
     356       94878 :     canonical_scope = nullptr;
     357             :   }
     358             : };
     359             : 
     360             : }  // namespace internal
     361             : }  // namespace v8
     362             : 
     363             : #endif  // V8_HANDLES_H_

Generated by: LCOV version 1.10