LCOV - code coverage report
Current view: top level - src/objects - hash-table.h (source / functions) Hit Total Coverage
Test: app.info Lines: 9 18 50.0 %
Date: 2019-04-19 Functions: 0 66 0.0 %

          Line data    Source code
       1             : // Copyright 2017 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_OBJECTS_HASH_TABLE_H_
       6             : #define V8_OBJECTS_HASH_TABLE_H_
       7             : 
       8             : #include "src/base/compiler-specific.h"
       9             : #include "src/base/export-template.h"
      10             : #include "src/base/macros.h"
      11             : #include "src/globals.h"
      12             : #include "src/objects/fixed-array.h"
      13             : #include "src/objects/smi.h"
      14             : #include "src/roots.h"
      15             : 
      16             : // Has to be the last include (doesn't have include guards):
      17             : #include "src/objects/object-macros.h"
      18             : 
      19             : namespace v8 {
      20             : namespace internal {
      21             : 
      22             : // HashTable is a subclass of FixedArray that implements a hash table
      23             : // that uses open addressing and quadratic probing.
      24             : //
      25             : // In order for the quadratic probing to work, elements that have not
      26             : // yet been used and elements that have been deleted are
      27             : // distinguished.  Probing continues when deleted elements are
      28             : // encountered and stops when unused elements are encountered.
      29             : //
      30             : // - Elements with key == undefined have not been used yet.
      31             : // - Elements with key == the_hole have been deleted.
      32             : //
      33             : // The hash table class is parameterized with a Shape.
      34             : // Shape must be a class with the following interface:
      35             : //   class ExampleShape {
      36             : //    public:
      37             : //     // Tells whether key matches other.
      38             : //     static bool IsMatch(Key key, Object other);
      39             : //     // Returns the hash value for key.
      40             : //     static uint32_t Hash(Isolate* isolate, Key key);
      41             : //     // Returns the hash value for object.
      42             : //     static uint32_t HashForObject(ReadOnlyRoots roots, Object object);
      43             : //     // Convert key to an object.
      44             : //     static inline Handle<Object> AsHandle(Isolate* isolate, Key key);
      45             : //     // The prefix size indicates number of elements in the beginning
      46             : //     // of the backing storage.
      47             : //     static const int kPrefixSize = ..;
      48             : //     // The Element size indicates number of elements per entry.
      49             : //     static const int kEntrySize = ..;
      50             : //     // Indicates whether IsMatch can deal with other being the_hole (a
      51             : //     // deleted entry).
      52             : //     static const bool kNeedsHoleCheck = ..;
      53             : //   };
      54             : // The prefix size indicates an amount of memory in the
      55             : // beginning of the backing storage that can be used for non-element
      56             : // information by subclasses.
      57             : 
      58             : template <typename KeyT>
      59             : class BaseShape {
      60             :  public:
      61             :   using Key = KeyT;
      62             :   static inline RootIndex GetMapRootIndex();
      63             :   static const bool kNeedsHoleCheck = true;
      64             :   static Object Unwrap(Object key) { return key; }
      65             :   static inline bool IsKey(ReadOnlyRoots roots, Object key);
      66             :   static inline bool IsLive(ReadOnlyRoots roots, Object key);
      67             : };
      68             : 
      69             : class V8_EXPORT_PRIVATE HashTableBase : public NON_EXPORTED_BASE(FixedArray) {
      70             :  public:
      71             :   // Returns the number of elements in the hash table.
      72             :   inline int NumberOfElements() const;
      73             : 
      74             :   // Returns the number of deleted elements in the hash table.
      75             :   inline int NumberOfDeletedElements() const;
      76             : 
      77             :   // Returns the capacity of the hash table.
      78             :   inline int Capacity() const;
      79             : 
      80             :   // ElementAdded should be called whenever an element is added to a
      81             :   // hash table.
      82             :   inline void ElementAdded();
      83             : 
      84             :   // ElementRemoved should be called whenever an element is removed from
      85             :   // a hash table.
      86             :   inline void ElementRemoved();
      87             :   inline void ElementsRemoved(int n);
      88             : 
      89             :   // Computes the required capacity for a table holding the given
      90             :   // number of elements. May be more than HashTable::kMaxCapacity.
      91             :   static inline int ComputeCapacity(int at_least_space_for);
      92             : 
      93             :   // Compute the probe offset (quadratic probing).
      94             :   V8_INLINE static uint32_t GetProbeOffset(uint32_t n) {
      95             :     return (n + n * n) >> 1;
      96             :   }
      97             : 
      98             :   static const int kNumberOfElementsIndex = 0;
      99             :   static const int kNumberOfDeletedElementsIndex = 1;
     100             :   static const int kCapacityIndex = 2;
     101             :   static const int kPrefixStartIndex = 3;
     102             : 
     103             :   // Constant used for denoting a absent entry.
     104             :   static const int kNotFound = -1;
     105             : 
     106             :   // Minimum capacity for newly created hash tables.
     107             :   static const int kMinCapacity = 4;
     108             : 
     109             :  protected:
     110             :   // Update the number of elements in the hash table.
     111             :   inline void SetNumberOfElements(int nof);
     112             : 
     113             :   // Update the number of deleted elements in the hash table.
     114             :   inline void SetNumberOfDeletedElements(int nod);
     115             : 
     116             :   // Returns probe entry.
     117             :   static uint32_t GetProbe(uint32_t hash, uint32_t number, uint32_t size) {
     118             :     DCHECK(base::bits::IsPowerOfTwo(size));
     119             :     return (hash + GetProbeOffset(number)) & (size - 1);
     120             :   }
     121             : 
     122             :   inline static uint32_t FirstProbe(uint32_t hash, uint32_t size) {
     123   894626599 :     return hash & (size - 1);
     124             :   }
     125             : 
     126             :   inline static uint32_t NextProbe(uint32_t last, uint32_t number,
     127             :                                    uint32_t size) {
     128   446602913 :     return (last + number) & (size - 1);
     129             :   }
     130             : 
     131             :   OBJECT_CONSTRUCTORS(HashTableBase, FixedArray);
     132             : };
     133             : 
     134             : template <typename Derived, typename Shape>
     135             : class EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) HashTable
     136             :     : public HashTableBase {
     137             :  public:
     138             :   using ShapeT = Shape;
     139             :   using Key = typename Shape::Key;
     140             : 
     141             :   // Returns a new HashTable object.
     142             :   V8_WARN_UNUSED_RESULT static Handle<Derived> New(
     143             :       Isolate* isolate, int at_least_space_for,
     144             :       AllocationType allocation = AllocationType::kYoung,
     145             :       MinimumCapacity capacity_option = USE_DEFAULT_MINIMUM_CAPACITY);
     146             : 
     147             :   // Garbage collection support.
     148             :   void IteratePrefix(ObjectVisitor* visitor);
     149             :   void IterateElements(ObjectVisitor* visitor);
     150             : 
     151             :   // Find entry for key otherwise return kNotFound.
     152             :   inline int FindEntry(ReadOnlyRoots roots, Key key, int32_t hash);
     153             :   int FindEntry(Isolate* isolate, Key key);
     154             : 
     155             :   // Rehashes the table in-place.
     156             :   void Rehash(ReadOnlyRoots roots);
     157             : 
     158             :   // Tells whether k is a real key.  The hole and undefined are not allowed
     159             :   // as keys and can be used to indicate missing or deleted elements.
     160             :   static bool IsKey(ReadOnlyRoots roots, Object k);
     161             : 
     162             :   inline bool ToKey(ReadOnlyRoots roots, int entry, Object* out_k);
     163             : 
     164             :   // Returns the key at entry.
     165           0 :   Object KeyAt(int entry) { return get(EntryToIndex(entry) + kEntryKeyIndex); }
     166             : 
     167             :   static const int kElementsStartIndex = kPrefixStartIndex + Shape::kPrefixSize;
     168             :   static const int kEntrySize = Shape::kEntrySize;
     169             :   STATIC_ASSERT(kEntrySize > 0);
     170             :   static const int kEntryKeyIndex = 0;
     171             :   static const int kElementsStartOffset =
     172             :       kHeaderSize + kElementsStartIndex * kTaggedSize;
     173             :   // Maximal capacity of HashTable. Based on maximal length of underlying
     174             :   // FixedArray. Staying below kMaxCapacity also ensures that EntryToIndex
     175             :   // cannot overflow.
     176             :   static const int kMaxCapacity =
     177             :       (FixedArray::kMaxLength - kElementsStartIndex) / kEntrySize;
     178             : 
     179             :   // Don't shrink a HashTable below this capacity.
     180             :   static const int kMinShrinkCapacity = 16;
     181             : 
     182             :   static const int kMaxRegularCapacity = kMaxRegularHeapObjectSize / 32;
     183             : 
     184             :   // Returns the index for an entry (of the key)
     185           0 :   static constexpr inline int EntryToIndex(int entry) {
     186  2864903405 :     return (entry * kEntrySize) + kElementsStartIndex;
     187             :   }
     188             : 
     189             :   // Returns the index for an entry (of the key)
     190           0 :   static constexpr inline int IndexToEntry(int index) {
     191           2 :     return (index - kElementsStartIndex) / kEntrySize;
     192             :   }
     193             : 
     194             :   // Returns the index for a slot address in the object.
     195           0 :   static constexpr inline int SlotToIndex(Address object, Address slot) {
     196           2 :     return static_cast<int>((slot - object - kHeaderSize) / kTaggedSize);
     197             :   }
     198             : 
     199             :   // Ensure enough space for n additional elements.
     200             :   V8_WARN_UNUSED_RESULT static Handle<Derived> EnsureCapacity(
     201             :       Isolate* isolate, Handle<Derived> table, int n,
     202             :       AllocationType allocation = AllocationType::kYoung);
     203             : 
     204             :   // Returns true if this table has sufficient capacity for adding n elements.
     205             :   bool HasSufficientCapacityToAdd(int number_of_additional_elements);
     206             : 
     207             :  protected:
     208             :   friend class ObjectHashTable;
     209             : 
     210             :   V8_WARN_UNUSED_RESULT static Handle<Derived> NewInternal(
     211             :       Isolate* isolate, int capacity, AllocationType allocation);
     212             : 
     213             :   // Find the entry at which to insert element with the given key that
     214             :   // has the given hash value.
     215             :   uint32_t FindInsertionEntry(uint32_t hash);
     216             : 
     217             :   // Attempt to shrink hash table after removal of key.
     218             :   V8_WARN_UNUSED_RESULT static Handle<Derived> Shrink(
     219             :       Isolate* isolate, Handle<Derived> table, int additionalCapacity = 0);
     220             : 
     221             :   inline void set_key(int index, Object value);
     222             :   inline void set_key(int index, Object value, WriteBarrierMode mode);
     223             : 
     224             :  private:
     225             :   // Ensure that kMaxRegularCapacity yields a non-large object dictionary.
     226             :   STATIC_ASSERT(EntryToIndex(kMaxRegularCapacity) < kMaxRegularLength);
     227             :   STATIC_ASSERT(v8::base::bits::IsPowerOfTwo(kMaxRegularCapacity));
     228             :   static const int kMaxRegularEntry = kMaxRegularCapacity / kEntrySize;
     229             :   static const int kMaxRegularIndex = EntryToIndex(kMaxRegularEntry);
     230             :   STATIC_ASSERT(OffsetOfElementAt(kMaxRegularIndex) <
     231             :                 kMaxRegularHeapObjectSize);
     232             : 
     233             :   // Sets the capacity of the hash table.
     234           0 :   void SetCapacity(int capacity) {
     235             :     // To scale a computed hash code to fit within the hash table, we
     236             :     // use bit-wise AND with a mask, so the capacity must be positive
     237             :     // and non-zero.
     238             :     DCHECK_GT(capacity, 0);
     239             :     DCHECK_LE(capacity, kMaxCapacity);
     240             :     set(kCapacityIndex, Smi::FromInt(capacity));
     241           0 :   }
     242             : 
     243             :   // Returns _expected_ if one of entries given by the first _probe_ probes is
     244             :   // equal to  _expected_. Otherwise, returns the entry given by the probe
     245             :   // number _probe_.
     246             :   uint32_t EntryForProbe(ReadOnlyRoots roots, Object k, int probe,
     247             :                          uint32_t expected);
     248             : 
     249             :   void Swap(uint32_t entry1, uint32_t entry2, WriteBarrierMode mode);
     250             : 
     251             :   // Rehashes this hash-table into the new table.
     252             :   void Rehash(ReadOnlyRoots roots, Derived new_table);
     253             : 
     254           0 :   OBJECT_CONSTRUCTORS(HashTable, HashTableBase);
     255             : };
     256             : 
     257             : // HashTableKey is an abstract superclass for virtual key behavior.
     258             : class HashTableKey {
     259             :  public:
     260    60554152 :   explicit HashTableKey(uint32_t hash) : hash_(hash) {}
     261             : 
     262             :   // Returns whether the other object matches this key.
     263             :   virtual bool IsMatch(Object other) = 0;
     264             :   // Returns the hash value for this key.
     265             :   // Required.
     266    60554191 :   virtual ~HashTableKey() = default;
     267             : 
     268             :   uint32_t Hash() const { return hash_; }
     269             : 
     270             :  protected:
     271             :   void set_hash(uint32_t hash) {
     272             :     DCHECK_EQ(0, hash_);
     273    13075525 :     hash_ = hash;
     274             :   }
     275             : 
     276             :  private:
     277             :   uint32_t hash_ = 0;
     278             : };
     279             : 
     280             : class ObjectHashTableShape : public BaseShape<Handle<Object>> {
     281             :  public:
     282             :   static inline bool IsMatch(Handle<Object> key, Object other);
     283             :   static inline uint32_t Hash(Isolate* isolate, Handle<Object> key);
     284             :   static inline uint32_t HashForObject(ReadOnlyRoots roots, Object object);
     285             :   static inline Handle<Object> AsHandle(Handle<Object> key);
     286             :   static const int kPrefixSize = 0;
     287             :   static const int kEntryValueIndex = 1;
     288             :   static const int kEntrySize = 2;
     289             :   static const bool kNeedsHoleCheck = false;
     290             : };
     291             : 
     292             : template <typename Derived, typename Shape>
     293             : class EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) ObjectHashTableBase
     294             :     : public HashTable<Derived, Shape> {
     295             :  public:
     296             :   // Looks up the value associated with the given key. The hole value is
     297             :   // returned in case the key is not present.
     298             :   Object Lookup(Handle<Object> key);
     299             :   Object Lookup(Handle<Object> key, int32_t hash);
     300             :   Object Lookup(ReadOnlyRoots roots, Handle<Object> key, int32_t hash);
     301             : 
     302             :   // Returns the value at entry.
     303             :   Object ValueAt(int entry);
     304             : 
     305             :   // Overwrite all keys and values with the hole value.
     306             :   static void FillEntriesWithHoles(Handle<Derived>);
     307             : 
     308             :   // Adds (or overwrites) the value associated with the given key.
     309             :   static Handle<Derived> Put(Handle<Derived> table, Handle<Object> key,
     310             :                              Handle<Object> value);
     311             :   static Handle<Derived> Put(Isolate* isolate, Handle<Derived> table,
     312             :                              Handle<Object> key, Handle<Object> value,
     313             :                              int32_t hash);
     314             : 
     315             :   // Returns an ObjectHashTable (possibly |table|) where |key| has been removed.
     316             :   static Handle<Derived> Remove(Isolate* isolate, Handle<Derived> table,
     317             :                                 Handle<Object> key, bool* was_present);
     318             :   static Handle<Derived> Remove(Isolate* isolate, Handle<Derived> table,
     319             :                                 Handle<Object> key, bool* was_present,
     320             :                                 int32_t hash);
     321             : 
     322             :   // Returns the index to the value of an entry.
     323           0 :   static inline int EntryToValueIndex(int entry) {
     324             :     return HashTable<Derived, Shape>::EntryToIndex(entry) +
     325      131460 :            Shape::kEntryValueIndex;
     326             :   }
     327             : 
     328             :  protected:
     329             :   void AddEntry(int entry, Object key, Object value);
     330             :   void RemoveEntry(int entry);
     331             : 
     332           0 :   OBJECT_CONSTRUCTORS(ObjectHashTableBase, HashTable<Derived, Shape>);
     333             : };
     334             : 
     335             : class ObjectHashTable;
     336             : 
     337             : extern template class EXPORT_TEMPLATE_DECLARE(
     338             :     V8_EXPORT_PRIVATE) HashTable<ObjectHashTable, ObjectHashTableShape>;
     339             : extern template class EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE)
     340             :     ObjectHashTableBase<ObjectHashTable, ObjectHashTableShape>;
     341             : 
     342             : // ObjectHashTable maps keys that are arbitrary objects to object values by
     343             : // using the identity hash of the key for hashing purposes.
     344             : class V8_EXPORT_PRIVATE ObjectHashTable
     345             :     : public ObjectHashTableBase<ObjectHashTable, ObjectHashTableShape> {
     346             :  public:
     347             :   DECL_CAST(ObjectHashTable)
     348             :   DECL_PRINTER(ObjectHashTable)
     349             : 
     350             :   OBJECT_CONSTRUCTORS(
     351             :       ObjectHashTable,
     352             :       ObjectHashTableBase<ObjectHashTable, ObjectHashTableShape>);
     353             : };
     354             : 
     355             : class EphemeronHashTableShape : public ObjectHashTableShape {
     356             :  public:
     357             :   static inline RootIndex GetMapRootIndex();
     358             : };
     359             : 
     360             : class EphemeronHashTable;
     361             : 
     362             : extern template class EXPORT_TEMPLATE_DECLARE(
     363             :     V8_EXPORT_PRIVATE) HashTable<EphemeronHashTable, EphemeronHashTableShape>;
     364             : extern template class EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE)
     365             :     ObjectHashTableBase<EphemeronHashTable, EphemeronHashTableShape>;
     366             : 
     367             : // EphemeronHashTable is similar to ObjectHashTable but gets special treatment
     368             : // by the GC. The GC treats its entries as ephemerons: both key and value are
     369             : // weak references, however if the key is strongly reachable its corresponding
     370             : // value is also kept alive.
     371             : class V8_EXPORT_PRIVATE EphemeronHashTable
     372             :     : public ObjectHashTableBase<EphemeronHashTable, EphemeronHashTableShape> {
     373             :  public:
     374             :   DECL_CAST(EphemeronHashTable)
     375             :   DECL_PRINTER(EphemeronHashTable)
     376             :   class BodyDescriptor;
     377             : 
     378             :  protected:
     379             :   friend class MarkCompactCollector;
     380             :   friend class ScavengerCollector;
     381             :   friend class HashTable<EphemeronHashTable, EphemeronHashTableShape>;
     382             :   friend class ObjectHashTableBase<EphemeronHashTable, EphemeronHashTableShape>;
     383             :   inline void set_key(int index, Object value);
     384             :   inline void set_key(int index, Object value, WriteBarrierMode mode);
     385             : 
     386             :   OBJECT_CONSTRUCTORS(
     387             :       EphemeronHashTable,
     388             :       ObjectHashTableBase<EphemeronHashTable, EphemeronHashTableShape>);
     389             : };
     390             : 
     391             : class ObjectHashSetShape : public ObjectHashTableShape {
     392             :  public:
     393             :   static const int kPrefixSize = 0;
     394             :   static const int kEntrySize = 1;
     395             : };
     396             : 
     397             : class ObjectHashSet;
     398             : extern template class EXPORT_TEMPLATE_DECLARE(
     399             :     V8_EXPORT_PRIVATE) HashTable<ObjectHashSet, ObjectHashSetShape>;
     400             : 
     401             : class V8_EXPORT_PRIVATE ObjectHashSet
     402             :     : public HashTable<ObjectHashSet, ObjectHashSetShape> {
     403             :  public:
     404             :   static Handle<ObjectHashSet> Add(Isolate* isolate, Handle<ObjectHashSet> set,
     405             :                                    Handle<Object> key);
     406             : 
     407             :   inline bool Has(Isolate* isolate, Handle<Object> key, int32_t hash);
     408             :   inline bool Has(Isolate* isolate, Handle<Object> key);
     409             : 
     410             :   DECL_CAST(ObjectHashSet)
     411             : 
     412             :   OBJECT_CONSTRUCTORS(ObjectHashSet,
     413             :                       HashTable<ObjectHashSet, ObjectHashSetShape>);
     414             : };
     415             : 
     416             : }  // namespace internal
     417             : }  // namespace v8
     418             : 
     419             : #include "src/objects/object-macros-undef.h"
     420             : 
     421             : #endif  // V8_OBJECTS_HASH_TABLE_H_

Generated by: LCOV version 1.10