LCOV - code coverage report
Current view: top level - src/objects - dictionary.h (source / functions) Hit Total Coverage
Test: app.info Lines: 16 23 69.6 %
Date: 2019-03-21 Functions: 18 48 37.5 %

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

Generated by: LCOV version 1.10