Home | History | Annotate | Download | only in src
      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_INL_H_
      6 #define V8_TRANSITIONS_INL_H_
      7 
      8 #include "src/transitions.h"
      9 
     10 namespace v8 {
     11 namespace internal {
     12 
     13 
     14 TransitionArray* TransitionArray::cast(Object* object) {
     15   DCHECK(object->IsTransitionArray());
     16   return reinterpret_cast<TransitionArray*>(object);
     17 }
     18 
     19 
     20 Object* TransitionArray::next_link() { return get(kNextLinkIndex); }
     21 
     22 
     23 void TransitionArray::set_next_link(Object* next, WriteBarrierMode mode) {
     24   return set(kNextLinkIndex, next, mode);
     25 }
     26 
     27 
     28 bool TransitionArray::HasPrototypeTransitions() {
     29   return get(kPrototypeTransitionsIndex) != Smi::kZero;
     30 }
     31 
     32 
     33 FixedArray* TransitionArray::GetPrototypeTransitions() {
     34   DCHECK(HasPrototypeTransitions());  // Callers must check first.
     35   Object* prototype_transitions = get(kPrototypeTransitionsIndex);
     36   return FixedArray::cast(prototype_transitions);
     37 }
     38 
     39 
     40 void TransitionArray::SetPrototypeTransitions(FixedArray* transitions) {
     41   DCHECK(transitions->IsFixedArray());
     42   set(kPrototypeTransitionsIndex, transitions);
     43 }
     44 
     45 
     46 Object** TransitionArray::GetPrototypeTransitionsSlot() {
     47   return RawFieldOfElementAt(kPrototypeTransitionsIndex);
     48 }
     49 
     50 
     51 Object** TransitionArray::GetKeySlot(int transition_number) {
     52   DCHECK(transition_number < number_of_transitions());
     53   return RawFieldOfElementAt(ToKeyIndex(transition_number));
     54 }
     55 
     56 
     57 Name* TransitionArray::GetKey(int transition_number) {
     58   DCHECK(transition_number < number_of_transitions());
     59   return Name::cast(get(ToKeyIndex(transition_number)));
     60 }
     61 
     62 
     63 Name* TransitionArray::GetKey(Object* raw_transitions, int transition_number) {
     64   if (IsSimpleTransition(raw_transitions)) {
     65     DCHECK(transition_number == 0);
     66     return GetSimpleTransitionKey(GetSimpleTransition(raw_transitions));
     67   }
     68   DCHECK(IsFullTransitionArray(raw_transitions));
     69   return TransitionArray::cast(raw_transitions)->GetKey(transition_number);
     70 }
     71 
     72 
     73 void TransitionArray::SetKey(int transition_number, Name* key) {
     74   DCHECK(transition_number < number_of_transitions());
     75   set(ToKeyIndex(transition_number), key);
     76 }
     77 
     78 
     79 Map* TransitionArray::GetTarget(int transition_number) {
     80   DCHECK(transition_number < number_of_transitions());
     81   return Map::cast(get(ToTargetIndex(transition_number)));
     82 }
     83 
     84 
     85 Map* TransitionArray::GetTarget(Object* raw_transitions,
     86                                 int transition_number) {
     87   if (IsSimpleTransition(raw_transitions)) {
     88     DCHECK(transition_number == 0);
     89     return GetSimpleTransition(raw_transitions);
     90   }
     91   DCHECK(IsFullTransitionArray(raw_transitions));
     92   return TransitionArray::cast(raw_transitions)->GetTarget(transition_number);
     93 }
     94 
     95 
     96 void TransitionArray::SetTarget(int transition_number, Map* value) {
     97   DCHECK(transition_number < number_of_transitions());
     98   set(ToTargetIndex(transition_number), value);
     99 }
    100 
    101 
    102 int TransitionArray::SearchName(Name* name, int* out_insertion_index) {
    103   DCHECK(name->IsUniqueName());
    104   return internal::Search<ALL_ENTRIES>(this, name, number_of_entries(),
    105                                        out_insertion_index);
    106 }
    107 
    108 
    109 #ifdef DEBUG
    110 bool TransitionArray::IsSpecialTransition(Name* name) {
    111   if (!name->IsSymbol()) return false;
    112   Heap* heap = name->GetHeap();
    113   return name == heap->nonextensible_symbol() ||
    114          name == heap->sealed_symbol() || name == heap->frozen_symbol() ||
    115          name == heap->elements_transition_symbol() ||
    116          name == heap->strict_function_transition_symbol();
    117 }
    118 #endif
    119 
    120 
    121 int TransitionArray::CompareKeys(Name* key1, uint32_t hash1, PropertyKind kind1,
    122                                  PropertyAttributes attributes1, Name* key2,
    123                                  uint32_t hash2, PropertyKind kind2,
    124                                  PropertyAttributes attributes2) {
    125   int cmp = CompareNames(key1, hash1, key2, hash2);
    126   if (cmp != 0) return cmp;
    127 
    128   return CompareDetails(kind1, attributes1, kind2, attributes2);
    129 }
    130 
    131 
    132 int TransitionArray::CompareNames(Name* key1, uint32_t hash1, Name* key2,
    133                                   uint32_t hash2) {
    134   if (key1 != key2) {
    135     // In case of hash collisions key1 is always "less" than key2.
    136     return hash1 <= hash2 ? -1 : 1;
    137   }
    138 
    139   return 0;
    140 }
    141 
    142 
    143 int TransitionArray::CompareDetails(PropertyKind kind1,
    144                                     PropertyAttributes attributes1,
    145                                     PropertyKind kind2,
    146                                     PropertyAttributes attributes2) {
    147   if (kind1 != kind2) {
    148     return static_cast<int>(kind1) < static_cast<int>(kind2) ? -1 : 1;
    149   }
    150 
    151   if (attributes1 != attributes2) {
    152     return static_cast<int>(attributes1) < static_cast<int>(attributes2) ? -1
    153                                                                          : 1;
    154   }
    155 
    156   return 0;
    157 }
    158 
    159 
    160 PropertyDetails TransitionArray::GetTargetDetails(Name* name, Map* target) {
    161   DCHECK(!IsSpecialTransition(name));
    162   int descriptor = target->LastAdded();
    163   DescriptorArray* descriptors = target->instance_descriptors();
    164   // Transitions are allowed only for the last added property.
    165   DCHECK(descriptors->GetKey(descriptor)->Equals(name));
    166   return descriptors->GetDetails(descriptor);
    167 }
    168 
    169 
    170 void TransitionArray::Set(int transition_number, Name* key, Map* target) {
    171   set(ToKeyIndex(transition_number), key);
    172   set(ToTargetIndex(transition_number), target);
    173 }
    174 
    175 
    176 void TransitionArray::SetNumberOfTransitions(int number_of_transitions) {
    177   DCHECK(number_of_transitions <= Capacity(this));
    178   set(kTransitionLengthIndex, Smi::FromInt(number_of_transitions));
    179 }
    180 
    181 }  // namespace internal
    182 }  // namespace v8
    183 
    184 #endif  // V8_TRANSITIONS_INL_H_
    185