LCOV - code coverage report
Current view: top level - src/objects - dictionary.h (source / functions) Hit Total Coverage
Test: app.info Lines: 23 31 74.2 %
Date: 2019-02-19 Functions: 29 57 50.9 %

          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_DICTIONARY_H_
       6             : #define V8_OBJECTS_DICTIONARY_H_
       7             : 
       8             : #include "src/base/export-template.h"
       9             : #include "src/globals.h"
      10             : #include "src/objects/hash-table.h"
      11             : #include "src/objects/property-array.h"
      12             : #include "src/objects/smi.h"
      13             : 
      14             : // Has to be the last include (doesn't have include guards):
      15             : #include "src/objects/object-macros.h"
      16             : 
      17             : namespace v8 {
      18             : namespace internal {
      19             : 
      20             : template <typename T>
      21             : class Handle;
      22             : 
      23             : class Isolate;
      24             : 
      25             : template <typename Derived, typename Shape>
      26             : class Dictionary : public HashTable<Derived, Shape> {
      27             :   typedef HashTable<Derived, Shape> DerivedHashTable;
      28             : 
      29             :  public:
      30             :   typedef typename Shape::Key Key;
      31             :   // Returns the value at entry.
      32     4147308 :   Object ValueAt(int entry) {
      33     8294616 :     return this->get(DerivedHashTable::EntryToIndex(entry) + 1);
      34             :   }
      35             : 
      36             :   // Set the value for entry.
      37           0 :   void ValueAtPut(int entry, Object value) {
      38     2456894 :     this->set(DerivedHashTable::EntryToIndex(entry) + 1, value);
      39           0 :   }
      40             : 
      41             :   // Returns the property details for the property at entry.
      42   264383966 :   PropertyDetails DetailsAt(int entry) {
      43   264383929 :     return Shape::DetailsAt(Derived::cast(*this), entry);
      44             :   }
      45             : 
      46             :   // Set the details for entry.
      47    16696152 :   void DetailsAtPut(Isolate* isolate, int entry, PropertyDetails value) {
      48    16696152 :     Shape::DetailsAtPut(isolate, Derived::cast(*this), entry, value);
      49    16696152 :   }
      50             : 
      51             :   // Delete a property from the dictionary.
      52             :   V8_WARN_UNUSED_RESULT static Handle<Derived> DeleteEntry(
      53             :       Isolate* isolate, Handle<Derived> dictionary, int entry);
      54             : 
      55             :   // Attempt to shrink the dictionary after deletion of key.
      56         261 :   V8_WARN_UNUSED_RESULT static inline Handle<Derived> Shrink(
      57             :       Isolate* isolate, Handle<Derived> dictionary) {
      58       47419 :     return DerivedHashTable::Shrink(isolate, dictionary);
      59             :   }
      60             : 
      61             :   int NumberOfEnumerableProperties();
      62             : 
      63             : #ifdef OBJECT_PRINT
      64             :   // For our gdb macros, we should perhaps change these in the future.
      65             :   void Print();
      66             : 
      67             :   void Print(std::ostream& os);  // NOLINT
      68             : #endif
      69             :   // Returns the key (slow).
      70             :   Object SlowReverseLookup(Object value);
      71             : 
      72             :   // Sets the entry to (key, value) pair.
      73             :   inline void ClearEntry(Isolate* isolate, int entry);
      74             :   inline void SetEntry(Isolate* isolate, int entry, Object key, Object value,
      75             :                        PropertyDetails details);
      76             : 
      77             :   V8_WARN_UNUSED_RESULT static Handle<Derived> Add(
      78             :       Isolate* isolate, Handle<Derived> dictionary, Key key,
      79             :       Handle<Object> value, PropertyDetails details, int* entry_out = nullptr);
      80             : 
      81             :  protected:
      82             :   // Generic at put operation.
      83             :   V8_WARN_UNUSED_RESULT static Handle<Derived> AtPut(Isolate* isolate,
      84             :                                                      Handle<Derived> dictionary,
      85             :                                                      Key key,
      86             :                                                      Handle<Object> value,
      87             :                                                      PropertyDetails details);
      88             : 
      89           0 :   OBJECT_CONSTRUCTORS(Dictionary, HashTable<Derived, Shape>);
      90             : };
      91             : 
      92             : template <typename Key>
      93             : class BaseDictionaryShape : public BaseShape<Key> {
      94             :  public:
      95             :   static const bool kHasDetails = true;
      96             :   template <typename Dictionary>
      97    96874811 :   static inline PropertyDetails DetailsAt(Dictionary dict, int entry) {
      98             :     STATIC_ASSERT(Dictionary::kEntrySize == 3);
      99             :     DCHECK_GE(entry, 0);  // Not found is -1, which is not caught by get().
     100             :     return PropertyDetails(Smi::cast(dict->get(
     101   193749692 :         Dictionary::EntryToIndex(entry) + Dictionary::kEntryDetailsIndex)));
     102             :   }
     103             : 
     104             :   template <typename Dictionary>
     105     8538904 :   static inline void DetailsAtPut(Isolate* isolate, Dictionary dict, int entry,
     106             :                                   PropertyDetails value) {
     107             :     STATIC_ASSERT(Dictionary::kEntrySize == 3);
     108             :     dict->set(Dictionary::EntryToIndex(entry) + Dictionary::kEntryDetailsIndex,
     109             :               value.AsSmi());
     110     8538904 :   }
     111             : };
     112             : 
     113             : class NameDictionaryShape : public BaseDictionaryShape<Handle<Name>> {
     114             :  public:
     115             :   static inline bool IsMatch(Handle<Name> key, Object other);
     116             :   static inline uint32_t Hash(Isolate* isolate, Handle<Name> key);
     117             :   static inline uint32_t HashForObject(Isolate* isolate, Object object);
     118             :   static inline Handle<Object> AsHandle(Isolate* isolate, Handle<Name> key);
     119             :   static inline RootIndex GetMapRootIndex();
     120             :   static const int kPrefixSize = 2;
     121             :   static const int kEntrySize = 3;
     122             :   static const int kEntryValueIndex = 1;
     123             :   static const bool kNeedsHoleCheck = false;
     124             : };
     125             : 
     126             : template <typename Derived, typename Shape>
     127             : class BaseNameDictionary : public Dictionary<Derived, Shape> {
     128             :   typedef typename Shape::Key Key;
     129             : 
     130             :  public:
     131             :   static const int kNextEnumerationIndexIndex =
     132             :       HashTableBase::kPrefixStartIndex;
     133             :   static const int kObjectHashIndex = kNextEnumerationIndexIndex + 1;
     134             :   static const int kEntryValueIndex = 1;
     135             : 
     136             :   // Accessors for next enumeration index.
     137             :   void SetNextEnumerationIndex(int index) {
     138             :     DCHECK_NE(0, index);
     139             :     this->set(kNextEnumerationIndexIndex, Smi::FromInt(index));
     140             :   }
     141             : 
     142    33319847 :   int NextEnumerationIndex() {
     143    33319847 :     return Smi::ToInt(this->get(kNextEnumerationIndexIndex));
     144             :   }
     145             : 
     146             :   void SetHash(int hash) {
     147             :     DCHECK(PropertyArray::HashField::is_valid(hash));
     148             :     this->set(kObjectHashIndex, Smi::FromInt(hash));
     149             :   }
     150             : 
     151    10905073 :   int Hash() const {
     152    10905073 :     Object hash_obj = this->get(kObjectHashIndex);
     153    10905073 :     int hash = Smi::ToInt(hash_obj);
     154             :     DCHECK(PropertyArray::HashField::is_valid(hash));
     155    10905073 :     return hash;
     156             :   }
     157             : 
     158             :   // Creates a new dictionary.
     159             :   V8_WARN_UNUSED_RESULT static Handle<Derived> New(
     160             :       Isolate* isolate, int at_least_space_for,
     161             :       PretenureFlag pretenure = NOT_TENURED,
     162             :       MinimumCapacity capacity_option = USE_DEFAULT_MINIMUM_CAPACITY);
     163             : 
     164             :   // Collect the keys into the given KeyAccumulator, in ascending chronological
     165             :   // order of property creation.
     166       46758 :   static void CollectKeysTo(Handle<Derived> dictionary, KeyAccumulator* keys);
     167             : 
     168             :   // Return the key indices sorted by its enumeration index.
     169             :   static Handle<FixedArray> IterationIndices(Isolate* isolate,
     170             :                                              Handle<Derived> dictionary);
     171             : 
     172             :   // Copies enumerable keys to preallocated fixed array.
     173             :   // Does not throw for uninitialized exports in module namespace objects, so
     174             :   // this has to be checked separately.
     175             :   static void CopyEnumKeysTo(Isolate* isolate, Handle<Derived> dictionary,
     176             :                              Handle<FixedArray> storage, KeyCollectionMode mode,
     177             :                              KeyAccumulator* accumulator);
     178             : 
     179             :   // Ensure enough space for n additional elements.
     180             :   static Handle<Derived> EnsureCapacity(Isolate* isolate,
     181             :                                         Handle<Derived> dictionary, int n);
     182             : 
     183             :   V8_WARN_UNUSED_RESULT static Handle<Derived> AddNoUpdateNextEnumerationIndex(
     184             :       Isolate* isolate, Handle<Derived> dictionary, Key key,
     185             :       Handle<Object> value, PropertyDetails details, int* entry_out = nullptr);
     186             : 
     187             :   V8_WARN_UNUSED_RESULT static Handle<Derived> Add(
     188             :       Isolate* isolate, Handle<Derived> dictionary, Key key,
     189             :       Handle<Object> value, PropertyDetails details, int* entry_out = nullptr);
     190             : 
     191             :   OBJECT_CONSTRUCTORS(BaseNameDictionary, Dictionary<Derived, Shape>);
     192             : };
     193             : 
     194             : class NameDictionary
     195             :     : public BaseNameDictionary<NameDictionary, NameDictionaryShape> {
     196             :  public:
     197             :   DECL_CAST(NameDictionary)
     198             : 
     199             :   static const int kEntryDetailsIndex = 2;
     200             :   static const int kInitialCapacity = 2;
     201             : 
     202             :   inline Name NameAt(int entry);
     203             :   inline void set_hash(int hash);
     204             :   inline int hash() const;
     205             : 
     206       17240 :   OBJECT_CONSTRUCTORS(NameDictionary,
     207             :                       BaseNameDictionary<NameDictionary, NameDictionaryShape>);
     208             : };
     209             : 
     210             : class GlobalDictionaryShape : public NameDictionaryShape {
     211             :  public:
     212             :   static inline bool IsMatch(Handle<Name> key, Object other);
     213             :   static inline uint32_t HashForObject(Isolate* isolate, Object object);
     214             : 
     215             :   static const int kEntrySize = 1;  // Overrides NameDictionaryShape::kEntrySize
     216             : 
     217             :   template <typename Dictionary>
     218             :   static inline PropertyDetails DetailsAt(Dictionary dict, int entry);
     219             : 
     220             :   template <typename Dictionary>
     221             :   static inline void DetailsAtPut(Isolate* isolate, Dictionary dict, int entry,
     222             :                                   PropertyDetails value);
     223             : 
     224             :   static inline Object Unwrap(Object key);
     225             :   static inline bool IsKey(ReadOnlyRoots roots, Object k);
     226             :   static inline bool IsLive(ReadOnlyRoots roots, Object key);
     227             :   static inline RootIndex GetMapRootIndex();
     228             : };
     229             : 
     230             : class GlobalDictionary
     231             :     : public BaseNameDictionary<GlobalDictionary, GlobalDictionaryShape> {
     232             :  public:
     233             :   DECL_CAST(GlobalDictionary)
     234             : 
     235             :   inline Object ValueAt(int entry);
     236             :   inline PropertyCell CellAt(int entry);
     237             :   inline void SetEntry(Isolate* isolate, int entry, Object key, Object value,
     238             :                        PropertyDetails details);
     239             :   inline Name NameAt(int entry);
     240             :   inline void ValueAtPut(int entry, Object value);
     241             : 
     242           0 :   OBJECT_CONSTRUCTORS(
     243             :       GlobalDictionary,
     244             :       BaseNameDictionary<GlobalDictionary, GlobalDictionaryShape>);
     245             : };
     246             : 
     247             : class NumberDictionaryBaseShape : public BaseDictionaryShape<uint32_t> {
     248             :  public:
     249             :   static inline bool IsMatch(uint32_t key, Object other);
     250             :   static inline Handle<Object> AsHandle(Isolate* isolate, uint32_t key);
     251             : 
     252             :   static inline uint32_t Hash(Isolate* isolate, uint32_t key);
     253             :   static inline uint32_t HashForObject(Isolate* isolate, Object object);
     254             : };
     255             : 
     256             : class NumberDictionaryShape : public NumberDictionaryBaseShape {
     257             :  public:
     258             :   static const int kPrefixSize = 1;
     259             :   static const int kEntrySize = 3;
     260             : 
     261             :   static inline RootIndex GetMapRootIndex();
     262             : };
     263             : 
     264             : class SimpleNumberDictionaryShape : public NumberDictionaryBaseShape {
     265             :  public:
     266             :   static const bool kHasDetails = false;
     267             :   static const int kPrefixSize = 0;
     268             :   static const int kEntrySize = 2;
     269             : 
     270             :   template <typename Dictionary>
     271           0 :   static inline PropertyDetails DetailsAt(Dictionary dict, int entry) {
     272           0 :     UNREACHABLE();
     273             :   }
     274             : 
     275             :   template <typename Dictionary>
     276           0 :   static inline void DetailsAtPut(Isolate* isolate, Dictionary dict, int entry,
     277             :                                   PropertyDetails value) {
     278           0 :     UNREACHABLE();
     279             :   }
     280             : 
     281             :   static inline RootIndex GetMapRootIndex();
     282             : };
     283             : 
     284             : extern template class EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE)
     285             :     HashTable<SimpleNumberDictionary, SimpleNumberDictionaryShape>;
     286             : 
     287             : extern template class EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE)
     288             :     Dictionary<SimpleNumberDictionary, SimpleNumberDictionaryShape>;
     289             : 
     290             : // SimpleNumberDictionary is used to map number to an entry.
     291             : class SimpleNumberDictionary
     292             :     : public Dictionary<SimpleNumberDictionary, SimpleNumberDictionaryShape> {
     293             :  public:
     294             :   DECL_CAST(SimpleNumberDictionary)
     295             :   // Type specific at put (default NONE attributes is used when adding).
     296             :   V8_WARN_UNUSED_RESULT static Handle<SimpleNumberDictionary> Set(
     297             :       Isolate* isolate, Handle<SimpleNumberDictionary> dictionary, uint32_t key,
     298             :       Handle<Object> value);
     299             : 
     300             :   static const int kEntryValueIndex = 1;
     301             : 
     302             :   OBJECT_CONSTRUCTORS(
     303             :       SimpleNumberDictionary,
     304             :       Dictionary<SimpleNumberDictionary, SimpleNumberDictionaryShape>);
     305             : };
     306             : 
     307             : extern template class EXPORT_TEMPLATE_DECLARE(
     308             :     V8_EXPORT_PRIVATE) HashTable<NumberDictionary, NumberDictionaryShape>;
     309             : 
     310             : extern template class EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE)
     311             :     Dictionary<NumberDictionary, NumberDictionaryShape>;
     312             : 
     313             : // NumberDictionary is used as elements backing store and provides a bitfield
     314             : // and stores property details for every entry.
     315             : class NumberDictionary
     316             :     : public Dictionary<NumberDictionary, NumberDictionaryShape> {
     317             :  public:
     318             :   DECL_CAST(NumberDictionary)
     319             :   DECL_PRINTER(NumberDictionary)
     320             : 
     321             :   // Type specific at put (default NONE attributes is used when adding).
     322             :   V8_WARN_UNUSED_RESULT static Handle<NumberDictionary> Set(
     323             :       Isolate* isolate, Handle<NumberDictionary> dictionary, uint32_t key,
     324             :       Handle<Object> value,
     325             :       Handle<JSObject> dictionary_holder = Handle<JSObject>::null(),
     326             :       PropertyDetails details = PropertyDetails::Empty());
     327             : 
     328             :   static const int kMaxNumberKeyIndex = kPrefixStartIndex;
     329             :   void UpdateMaxNumberKey(uint32_t key, Handle<JSObject> dictionary_holder);
     330             : 
     331             :   // Returns true if the dictionary contains any elements that are non-writable,
     332             :   // non-configurable, non-enumerable, or have getters/setters.
     333             :   bool HasComplexElements();
     334             : 
     335             :   // Sorting support
     336             :   void CopyValuesTo(FixedArray elements);
     337             : 
     338             :   // If slow elements are required we will never go back to fast-case
     339             :   // for the elements kept in this dictionary.  We require slow
     340             :   // elements if an element has been added at an index larger than
     341             :   // kRequiresSlowElementsLimit or set_requires_slow_elements() has been called
     342             :   // when defining a getter or setter with a number key.
     343             :   inline bool requires_slow_elements();
     344             :   inline void set_requires_slow_elements();
     345             : 
     346             :   // Get the value of the max number key that has been added to this
     347             :   // dictionary.  max_number_key can only be called if
     348             :   // requires_slow_elements returns false.
     349             :   inline uint32_t max_number_key();
     350             : 
     351             :   static const int kEntryValueIndex = 1;
     352             :   static const int kEntryDetailsIndex = 2;
     353             : 
     354             :   // Bit masks.
     355             :   static const int kRequiresSlowElementsMask = 1;
     356             :   static const int kRequiresSlowElementsTagSize = 1;
     357             :   static const uint32_t kRequiresSlowElementsLimit = (1 << 29) - 1;
     358             : 
     359             :   // JSObjects prefer dictionary elements if the dictionary saves this much
     360             :   // memory compared to a fast elements backing store.
     361             :   static const uint32_t kPreferFastElementsSizeFactor = 3;
     362             : 
     363         112 :   OBJECT_CONSTRUCTORS(NumberDictionary,
     364             :                       Dictionary<NumberDictionary, NumberDictionaryShape>);
     365             : };
     366             : 
     367             : }  // namespace internal
     368             : }  // namespace v8
     369             : 
     370             : #include "src/objects/object-macros-undef.h"
     371             : 
     372             : #endif  // V8_OBJECTS_DICTIONARY_H_

Generated by: LCOV version 1.10