Home | History | Annotate | Download | only in src
      1 // Copyright 2012 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 #ifndef V8_TRANSITIONS_H_
     29 #define V8_TRANSITIONS_H_
     30 
     31 #include "elements-kind.h"
     32 #include "heap.h"
     33 #include "isolate.h"
     34 #include "objects.h"
     35 #include "v8checks.h"
     36 
     37 namespace v8 {
     38 namespace internal {
     39 
     40 
     41 // TransitionArrays are fixed arrays used to hold map transitions for property,
     42 // constant, and element changes. They can either be simple transition arrays
     43 // that store a single property transition, or a full transition array that has
     44 // prototype transitions and multiple property transitons. The details related
     45 // to property transitions are accessed in the descriptor array of the target
     46 // map. In the case of a simple transition, the key is also read from the
     47 // descriptor array of the target map.
     48 //
     49 // The simple format of the these objects is:
     50 // [0] Undefined or back pointer map
     51 // [1] Single transition
     52 //
     53 // The full format is:
     54 // [0] Undefined or back pointer map
     55 // [1] Smi(0) or fixed array of prototype transitions
     56 // [2] First transition
     57 // [length() - kTransitionSize] Last transition
     58 class TransitionArray: public FixedArray {
     59  public:
     60   // Accessors for fetching instance transition at transition number.
     61   inline Name* GetKey(int transition_number);
     62   inline void SetKey(int transition_number, Name* value);
     63   inline Object** GetKeySlot(int transition_number);
     64   int GetSortedKeyIndex(int transition_number) { return transition_number; }
     65 
     66   Name* GetSortedKey(int transition_number) {
     67     return GetKey(transition_number);
     68   }
     69 
     70   inline Map* GetTarget(int transition_number);
     71   inline void SetTarget(int transition_number, Map* target);
     72 
     73   inline PropertyDetails GetTargetDetails(int transition_number);
     74 
     75   inline bool HasElementsTransition();
     76 
     77   inline Object* back_pointer_storage();
     78   inline void set_back_pointer_storage(
     79       Object* back_pointer,
     80       WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
     81 
     82   inline FixedArray* GetPrototypeTransitions();
     83   inline void SetPrototypeTransitions(
     84       FixedArray* prototype_transitions,
     85       WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
     86   inline Object** GetPrototypeTransitionsSlot();
     87   inline bool HasPrototypeTransitions();
     88   inline HeapObject* UncheckedPrototypeTransitions();
     89 
     90   // Returns the number of transitions in the array.
     91   int number_of_transitions() {
     92     if (IsSimpleTransition()) return 1;
     93     int len = length();
     94     return len <= kFirstIndex ? 0 : (len - kFirstIndex) / kTransitionSize;
     95   }
     96 
     97   inline int number_of_entries() { return number_of_transitions(); }
     98 
     99   // Allocate a new transition array with a single entry.
    100   static MUST_USE_RESULT MaybeObject* NewWith(
    101       SimpleTransitionFlag flag,
    102       Name* key,
    103       Map* target,
    104       Object* back_pointer);
    105 
    106   MUST_USE_RESULT MaybeObject* ExtendToFullTransitionArray();
    107 
    108   // Copy the transition array, inserting a new transition.
    109   // TODO(verwaest): This should not cause an existing transition to be
    110   // overwritten.
    111   MUST_USE_RESULT MaybeObject* CopyInsert(Name* name, Map* target);
    112 
    113   // Copy a single transition from the origin array.
    114   inline void NoIncrementalWriteBarrierCopyFrom(TransitionArray* origin,
    115                                                 int origin_transition,
    116                                                 int target_transition);
    117 
    118   // Search a transition for a given property name.
    119   inline int Search(Name* name);
    120 
    121   // Allocates a TransitionArray.
    122   MUST_USE_RESULT static MaybeObject* Allocate(int number_of_transitions);
    123 
    124   bool IsSimpleTransition() {
    125     return length() == kSimpleTransitionSize &&
    126         get(kSimpleTransitionTarget)->IsHeapObject() &&
    127         // The IntrusivePrototypeTransitionIterator may have set the map of the
    128         // prototype transitions array to a smi. In that case, there are
    129         // prototype transitions, hence this transition array is a full
    130         // transition array.
    131         HeapObject::cast(get(kSimpleTransitionTarget))->map()->IsMap() &&
    132         get(kSimpleTransitionTarget)->IsMap();
    133   }
    134 
    135   bool IsFullTransitionArray() {
    136     return length() > kFirstIndex ||
    137         (length() == kFirstIndex && !IsSimpleTransition());
    138   }
    139 
    140   // Casting.
    141   static inline TransitionArray* cast(Object* obj);
    142 
    143   // Constant for denoting key was not found.
    144   static const int kNotFound = -1;
    145 
    146   static const int kBackPointerStorageIndex = 0;
    147 
    148   // Layout for full transition arrays.
    149   static const int kPrototypeTransitionsIndex = 1;
    150   static const int kFirstIndex = 2;
    151 
    152   // Layout for simple transition arrays.
    153   static const int kSimpleTransitionTarget = 1;
    154   static const int kSimpleTransitionSize = 2;
    155   static const int kSimpleTransitionIndex = 0;
    156   STATIC_ASSERT(kSimpleTransitionIndex != kNotFound);
    157 
    158   static const int kBackPointerStorageOffset = FixedArray::kHeaderSize;
    159 
    160   // Layout for the full transition array header.
    161   static const int kPrototypeTransitionsOffset = kBackPointerStorageOffset +
    162                                                  kPointerSize;
    163 
    164   // Layout of map transition entries in full transition arrays.
    165   static const int kTransitionKey = 0;
    166   static const int kTransitionTarget = 1;
    167   static const int kTransitionSize = 2;
    168 
    169 #ifdef OBJECT_PRINT
    170   // Print all the transitions.
    171   inline void PrintTransitions() {
    172     PrintTransitions(stdout);
    173   }
    174   void PrintTransitions(FILE* out);
    175 #endif
    176 
    177 #ifdef DEBUG
    178   bool IsSortedNoDuplicates(int valid_entries = -1);
    179   bool IsConsistentWithBackPointers(Map* current_map);
    180   bool IsEqualTo(TransitionArray* other);
    181 #endif
    182 
    183   // The maximum number of transitions we want in a transition array (should
    184   // fit in a page).
    185   static const int kMaxNumberOfTransitions = 1024 + 512;
    186 
    187  private:
    188   // Conversion from transition number to array indices.
    189   static int ToKeyIndex(int transition_number) {
    190     return kFirstIndex +
    191            (transition_number * kTransitionSize) +
    192            kTransitionKey;
    193   }
    194 
    195   static int ToTargetIndex(int transition_number) {
    196     return kFirstIndex +
    197            (transition_number * kTransitionSize) +
    198            kTransitionTarget;
    199   }
    200 
    201   inline void NoIncrementalWriteBarrierSet(int transition_number,
    202                                            Name* key,
    203                                            Map* target);
    204 
    205   DISALLOW_IMPLICIT_CONSTRUCTORS(TransitionArray);
    206 };
    207 
    208 
    209 } }  // namespace v8::internal
    210 
    211 #endif  // V8_TRANSITIONS_H_
    212