LCOV - code coverage report
Current view: top level - src - transitions.h (source / functions) Hit Total Coverage
Test: app.info Lines: 14 14 100.0 %
Date: 2019-01-20 Functions: 2 2 100.0 %

          Line data    Source code
       1             : // Copyright 2012 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_TRANSITIONS_H_
       6             : #define V8_TRANSITIONS_H_
       7             : 
       8             : #include "src/checks.h"
       9             : #include "src/elements-kind.h"
      10             : #include "src/objects.h"
      11             : #include "src/objects/descriptor-array.h"
      12             : #include "src/objects/map.h"
      13             : #include "src/objects/maybe-object.h"
      14             : #include "src/objects/name.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             : // TransitionsAccessor is a helper class to encapsulate access to the various
      23             : // ways a Map can store transitions to other maps in its respective field at
      24             : // Map::kTransitionsOrPrototypeInfo.
      25             : // It caches state information internally, which becomes stale when a Map's
      26             : // transitions storage changes or when a GC cycle clears dead transitions;
      27             : // so while a TransitionsAccessor instance can be used for several read-only
      28             : // operations in a row (provided no GC happens between them), it must be
      29             : // discarded and recreated after "Insert" and "UpdateHandler" operations.
      30             : //
      31             : // Internal details: a Map's field either holds an in-place weak reference to a
      32             : // transition target, or a StoreIC handler for a transitioning store (which in
      33             : // turn points to its target map), or a TransitionArray for several target maps
      34             : // and/or handlers as well as prototype and ElementsKind transitions.  Property
      35             : // details (and in case of inline target storage, the key) are retrieved from
      36             : // the target map's descriptor array.  Stored transitions are weak in the GC
      37             : // sense: both single transitions stored inline and TransitionArray fields are
      38             : // cleared when the map they refer to is not otherwise reachable.
      39             : class TransitionsAccessor {
      40             :  public:
      41             :   TransitionsAccessor(Isolate* isolate, Map map, DisallowHeapAllocation* no_gc)
      42    87412178 :       : isolate_(isolate), map_(map) {
      43    43706089 :     Initialize();
      44             :     USE(no_gc);
      45             :   }
      46    56115371 :   TransitionsAccessor(Isolate* isolate, Handle<Map> map)
      47   112230744 :       : isolate_(isolate), map_handle_(map), map_(*map) {
      48    56115373 :     Initialize();
      49    56115385 :   }
      50             : 
      51             :   // Insert a new transition into |map|'s transition array, extending it
      52             :   // as necessary.
      53             :   // Requires the constructor that takes a Handle<Map> to have been used.
      54             :   // This TransitionsAccessor instance is unusable after this operation.
      55             :   void Insert(Handle<Name> name, Handle<Map> target, SimpleTransitionFlag flag);
      56             : 
      57             :   Map SearchTransition(Name name, PropertyKind kind,
      58             :                        PropertyAttributes attributes);
      59             : 
      60             :   Map SearchSpecial(Symbol name);
      61             :   // Returns true for non-property transitions like elements kind, or
      62             :   // or frozen/sealed transitions.
      63             :   static bool IsSpecialTransition(ReadOnlyRoots roots, Name name);
      64             : 
      65             :   enum RequestedLocation { kAnyLocation, kFieldOnly };
      66             :   MaybeHandle<Map> FindTransitionToDataProperty(
      67             :       Handle<Name> name, RequestedLocation requested_location = kAnyLocation);
      68             : 
      69             :   MaybeHandle<Map> FindTransitionToField(Handle<Name> name) {
      70    11530568 :     return FindTransitionToDataProperty(name, kFieldOnly);
      71             :   }
      72             : 
      73             :   Handle<String> ExpectedTransitionKey();
      74             :   Handle<Map> ExpectedTransitionTarget();
      75             : 
      76             :   int NumberOfTransitions();
      77             :   // The size of transition arrays are limited so they do not end up in large
      78             :   // object space. Otherwise ClearNonLiveReferences would leak memory while
      79             :   // applying in-place right trimming.
      80             :   static const int kMaxNumberOfTransitions = 1024 + 512;
      81             :   bool CanHaveMoreTransitions();
      82             :   inline Name GetKey(int transition_number);
      83             :   inline Map GetTarget(int transition_number);
      84             :   static inline PropertyDetails GetTargetDetails(Name name, Map target);
      85             : 
      86             :   static bool IsMatchingMap(Map target, Name name, PropertyKind kind,
      87             :                             PropertyAttributes attributes);
      88             : 
      89             :   // ===== ITERATION =====
      90             :   typedef void (*TraverseCallback)(Map map, void* data);
      91             : 
      92             :   // Traverse the transition tree in postorder.
      93             :   void TraverseTransitionTree(TraverseCallback callback, void* data) {
      94             :     // Make sure that we do not allocate in the callback.
      95             :     DisallowHeapAllocation no_allocation;
      96      263507 :     TraverseTransitionTreeInternal(callback, data, &no_allocation);
      97             :   }
      98             : 
      99             :   // ===== PROTOTYPE TRANSITIONS =====
     100             :   // When you set the prototype of an object using the __proto__ accessor you
     101             :   // need a new map for the object (the prototype is stored in the map).  In
     102             :   // order not to multiply maps unnecessarily we store these as transitions in
     103             :   // the original map.  That way we can transition to the same map if the same
     104             :   // prototype is set, rather than creating a new map every time.  The
     105             :   // transitions are in the form of a map where the keys are prototype objects
     106             :   // and the values are the maps they transition to.
     107             :   void PutPrototypeTransition(Handle<Object> prototype, Handle<Map> target_map);
     108             :   Handle<Map> GetPrototypeTransition(Handle<Object> prototype);
     109             : 
     110             :   // During the first-time Map::Update and Map::TryUpdate, the migration target
     111             :   // map could be cached in the raw_transitions slot of the old map that is
     112             :   // deprecated from the map transition tree. The next time old map is updated,
     113             :   // we will check this cache slot as a shortcut to get the migration target
     114             :   // map.
     115             :   void SetMigrationTarget(Map migration_target);
     116             :   Map GetMigrationTarget();
     117             : 
     118             : #if DEBUG || OBJECT_PRINT
     119             :   void PrintTransitions(std::ostream& os);
     120             :   static void PrintOneTransition(std::ostream& os, Name key, Map target);
     121             :   void PrintTransitionTree();
     122             :   void PrintTransitionTree(std::ostream& os, int level,
     123             :                            DisallowHeapAllocation* no_gc);
     124             : #endif
     125             : #if DEBUG
     126             :   void CheckNewTransitionsAreConsistent(TransitionArray old_transitions,
     127             :                                         Object transitions);
     128             :   bool IsConsistentWithBackPointers();
     129             :   bool IsSortedNoDuplicates();
     130             : #endif
     131             : 
     132             :  protected:
     133             :   // Allow tests to use inheritance to access internals.
     134             :   enum Encoding {
     135             :     kPrototypeInfo,
     136             :     kUninitialized,
     137             :     kMigrationTarget,
     138             :     kWeakRef,
     139             :     kFullTransitionArray,
     140             :   };
     141             : 
     142      825437 :   void Reload() {
     143             :     DCHECK(!map_handle_.is_null());
     144      825437 :     map_ = *map_handle_;
     145      825437 :     Initialize();
     146      825438 :   }
     147             : 
     148             :   inline Encoding encoding() {
     149             :     DCHECK(!needs_reload_);
     150             :     return encoding_;
     151             :   }
     152             : 
     153             :  private:
     154             :   friend class MarkCompactCollector;  // For HasSimpleTransitionTo.
     155             :   friend class TransitionArray;
     156             : 
     157             :   static inline PropertyDetails GetSimpleTargetDetails(Map transition);
     158             : 
     159             :   static inline Name GetSimpleTransitionKey(Map transition);
     160             : 
     161             :   static inline Map GetTargetFromRaw(MaybeObject raw);
     162             : 
     163             :   void MarkNeedsReload() {
     164             : #if DEBUG
     165             :     needs_reload_ = true;
     166             : #endif
     167             :   }
     168             : 
     169             :   void Initialize();
     170             : 
     171             :   inline Map GetSimpleTransition();
     172             :   bool HasSimpleTransitionTo(Map map);
     173             : 
     174             :   void ReplaceTransitions(MaybeObject new_transitions);
     175             : 
     176             :   inline Map GetTargetMapFromWeakRef();
     177             : 
     178             :   void EnsureHasFullTransitionArray();
     179             :   void SetPrototypeTransitions(Handle<WeakFixedArray> proto_transitions);
     180             :   WeakFixedArray GetPrototypeTransitions();
     181             : 
     182             :   void TraverseTransitionTreeInternal(TraverseCallback callback, void* data,
     183             :                                       DisallowHeapAllocation* no_gc);
     184             : 
     185             :   inline TransitionArray transitions();
     186             : 
     187             :   Isolate* isolate_;
     188             :   Handle<Map> map_handle_;
     189             :   Map map_;
     190             :   MaybeObject raw_transitions_;
     191             :   Encoding encoding_;
     192             : #if DEBUG
     193             :   bool needs_reload_;
     194             : #endif
     195             : 
     196             :   DISALLOW_IMPLICIT_CONSTRUCTORS(TransitionsAccessor);
     197             : };
     198             : 
     199             : // TransitionArrays are fixed arrays used to hold map transitions for property,
     200             : // constant, and element changes.
     201             : // The TransitionArray class exposes a very low-level interface. Most clients
     202             : // should use TransitionsAccessors.
     203             : // TransitionArrays have the following format:
     204             : // [0] Link to next TransitionArray (for weak handling support) (strong ref)
     205             : // [1] Smi(0) or WeakFixedArray of prototype transitions (strong ref)
     206             : // [2] Number of transitions (can be zero after trimming)
     207             : // [3] First transition key (strong ref)
     208             : // [4] First transition target (weak ref)
     209             : // ...
     210             : // [3 + number of transitions * kTransitionSize]: start of slack
     211             : class TransitionArray : public WeakFixedArray {
     212             :  public:
     213             :   DECL_CAST(TransitionArray)
     214             : 
     215             :   inline WeakFixedArray GetPrototypeTransitions();
     216             :   inline bool HasPrototypeTransitions();
     217             : 
     218             :   // Accessors for fetching instance transition at transition number.
     219             :   inline void SetKey(int transition_number, Name value);
     220             :   inline Name GetKey(int transition_number);
     221             :   inline HeapObjectSlot GetKeySlot(int transition_number);
     222             : 
     223             :   inline Map GetTarget(int transition_number);
     224             :   inline void SetRawTarget(int transition_number, MaybeObject target);
     225             :   inline MaybeObject GetRawTarget(int transition_number);
     226             :   inline HeapObjectSlot GetTargetSlot(int transition_number);
     227             :   inline bool GetTargetIfExists(int transition_number, Isolate* isolate,
     228             :                                 Map* target);
     229             : 
     230             :   // Required for templatized Search interface.
     231             :   static constexpr int kNotFound = -1;
     232             : 
     233             :   inline Name GetSortedKey(int transition_number);
     234             :   int GetSortedKeyIndex(int transition_number) { return transition_number; }
     235             :   inline int number_of_entries() const;
     236             : #ifdef DEBUG
     237             :   bool IsSortedNoDuplicates(int valid_entries = -1);
     238             : #endif
     239             : 
     240             :   void Sort();
     241             : 
     242             :   void PrintInternal(std::ostream& os);
     243             : 
     244             :   DECL_PRINTER(TransitionArray)
     245             :   DECL_VERIFIER(TransitionArray)
     246             : 
     247             :   // Layout for full transition arrays.
     248             :   static const int kPrototypeTransitionsIndex = 0;
     249             :   static const int kTransitionLengthIndex = 1;
     250             :   static const int kFirstIndex = 2;
     251             : 
     252             :   // Layout of map transition entries in full transition arrays.
     253             :   static const int kEntryKeyIndex = 0;
     254             :   static const int kEntryTargetIndex = 1;
     255             :   static const int kEntrySize = 2;
     256             : 
     257             :   // Conversion from transition number to array indices.
     258             :   static int ToKeyIndex(int transition_number) {
     259   100725202 :     return kFirstIndex + (transition_number * kEntrySize) + kEntryKeyIndex;
     260             :   }
     261             : 
     262             :   static int ToTargetIndex(int transition_number) {
     263    45977563 :     return kFirstIndex + (transition_number * kEntrySize) + kEntryTargetIndex;
     264             :   }
     265             : 
     266             :   inline int SearchNameForTesting(Name name,
     267             :                                   int* out_insertion_index = nullptr);
     268             : 
     269             :  private:
     270             :   friend class Factory;
     271             :   friend class MarkCompactCollector;
     272             :   friend class TransitionsAccessor;
     273             : 
     274             :   inline void SetNumberOfTransitions(int number_of_transitions);
     275             : 
     276             :   inline int Capacity();
     277             : 
     278             :   // ===== PROTOTYPE TRANSITIONS =====
     279             :   // Cache format:
     280             :   //    0: finger - index of the first free cell in the cache
     281             :   //    1 + i: target map
     282             :   static const int kProtoTransitionHeaderSize = 1;
     283             :   static const int kMaxCachedPrototypeTransitions = 256;
     284             : 
     285             :   inline void SetPrototypeTransitions(WeakFixedArray prototype_transitions);
     286             : 
     287             :   static inline int NumberOfPrototypeTransitions(
     288             :       WeakFixedArray proto_transitions);
     289             :   static void SetNumberOfPrototypeTransitions(WeakFixedArray proto_transitions,
     290             :                                               int value);
     291             : 
     292             :   static const int kProtoTransitionNumberOfEntriesOffset = 0;
     293             :   STATIC_ASSERT(kProtoTransitionHeaderSize == 1);
     294             : 
     295             :   // Returns the fixed array length required to hold number_of_transitions
     296             :   // transitions.
     297             :   static int LengthFor(int number_of_transitions) {
     298             :     return ToKeyIndex(number_of_transitions);
     299             :   }
     300             : 
     301             :   // Search a  transition for a given kind, property name and attributes.
     302             :   int Search(PropertyKind kind, Name name, PropertyAttributes attributes,
     303             :              int* out_insertion_index = nullptr);
     304             : 
     305             :   Map SearchAndGetTarget(PropertyKind kind, Name name,
     306             :                          PropertyAttributes attributes);
     307             : 
     308             :   // Search a non-property transition (like elements kind, observe or frozen
     309             :   // transitions).
     310             :   inline int SearchSpecial(Symbol symbol, int* out_insertion_index = nullptr);
     311             :   // Search a first transition for a given property name.
     312             :   inline int SearchName(Name name, int* out_insertion_index = nullptr);
     313             :   int SearchDetails(int transition, PropertyKind kind,
     314             :                     PropertyAttributes attributes, int* out_insertion_index);
     315             :   Map SearchDetailsAndGetTarget(int transition, PropertyKind kind,
     316             :                                 PropertyAttributes attributes);
     317             : 
     318             :   inline int number_of_transitions() const;
     319             : 
     320             :   static bool CompactPrototypeTransitionArray(Isolate* isolate,
     321             :                                               WeakFixedArray array);
     322             : 
     323             :   static Handle<WeakFixedArray> GrowPrototypeTransitionArray(
     324             :       Handle<WeakFixedArray> array, int new_capacity, Isolate* isolate);
     325             : 
     326             :   // Compares two tuples <key, kind, attributes>, returns -1 if
     327             :   // tuple1 is "less" than tuple2, 0 if tuple1 equal to tuple2 and 1 otherwise.
     328             :   static inline int CompareKeys(Name key1, uint32_t hash1, PropertyKind kind1,
     329             :                                 PropertyAttributes attributes1, Name key2,
     330             :                                 uint32_t hash2, PropertyKind kind2,
     331             :                                 PropertyAttributes attributes2);
     332             : 
     333             :   // Compares keys, returns -1 if key1 is "less" than key2,
     334             :   // 0 if key1 equal to key2 and 1 otherwise.
     335             :   static inline int CompareNames(Name key1, uint32_t hash1, Name key2,
     336             :                                  uint32_t hash2);
     337             : 
     338             :   // Compares two details, returns -1 if details1 is "less" than details2,
     339             :   // 0 if details1 equal to details2 and 1 otherwise.
     340             :   static inline int CompareDetails(PropertyKind kind1,
     341             :                                    PropertyAttributes attributes1,
     342             :                                    PropertyKind kind2,
     343             :                                    PropertyAttributes attributes2);
     344             : 
     345             :   inline void Set(int transition_number, Name key, MaybeObject target);
     346             : 
     347             :   void Zap(Isolate* isolate);
     348             : 
     349             :   OBJECT_CONSTRUCTORS(TransitionArray, WeakFixedArray);
     350             : };
     351             : 
     352             : }  // namespace internal
     353             : }  // namespace v8
     354             : 
     355             : #include "src/objects/object-macros-undef.h"
     356             : 
     357             : #endif  // V8_TRANSITIONS_H_

Generated by: LCOV version 1.10