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 #include "src/ic/handler-configuration-inl.h"
     11 #include "src/objects/fixed-array-inl.h"
     12 #include "src/objects/maybe-object-inl.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 TransitionArray* TransitionsAccessor::transitions() {
     21   DCHECK_EQ(kFullTransitionArray, encoding());
     22   return TransitionArray::cast(raw_transitions_->ToStrongHeapObject());
     23 }
     24 
     25 CAST_ACCESSOR(TransitionArray)
     26 
     27 bool TransitionArray::HasPrototypeTransitions() {
     28   return Get(kPrototypeTransitionsIndex) != MaybeObject::FromSmi(Smi::kZero);
     29 }
     30 
     31 WeakFixedArray* TransitionArray::GetPrototypeTransitions() {
     32   DCHECK(HasPrototypeTransitions());  // Callers must check first.
     33   Object* prototype_transitions =
     34       Get(kPrototypeTransitionsIndex)->ToStrongHeapObject();
     35   return WeakFixedArray::cast(prototype_transitions);
     36 }
     37 
     38 HeapObjectReference** TransitionArray::GetKeySlot(int transition_number) {
     39   DCHECK(transition_number < number_of_transitions());
     40   return reinterpret_cast<HeapObjectReference**>(
     41       RawFieldOfElementAt(ToKeyIndex(transition_number)));
     42 }
     43 
     44 void TransitionArray::SetPrototypeTransitions(WeakFixedArray* transitions) {
     45   DCHECK(transitions->IsWeakFixedArray());
     46   WeakFixedArray::Set(kPrototypeTransitionsIndex,
     47                       HeapObjectReference::Strong(transitions));
     48 }
     49 
     50 int TransitionArray::NumberOfPrototypeTransitions(
     51     WeakFixedArray* proto_transitions) {
     52   if (proto_transitions->length() == 0) return 0;
     53   MaybeObject* raw =
     54       proto_transitions->Get(kProtoTransitionNumberOfEntriesOffset);
     55   return Smi::ToInt(raw->ToSmi());
     56 }
     57 
     58 Name* TransitionArray::GetKey(int transition_number) {
     59   DCHECK(transition_number < number_of_transitions());
     60   return Name::cast(Get(ToKeyIndex(transition_number))->ToStrongHeapObject());
     61 }
     62 
     63 Name* TransitionsAccessor::GetKey(int transition_number) {
     64   switch (encoding()) {
     65     case kPrototypeInfo:
     66     case kUninitialized:
     67       UNREACHABLE();
     68       return nullptr;
     69     case kWeakRef: {
     70       Map* map = Map::cast(raw_transitions_->ToWeakHeapObject());
     71       return GetSimpleTransitionKey(map);
     72     }
     73     case kFullTransitionArray:
     74       return transitions()->GetKey(transition_number);
     75   }
     76   UNREACHABLE();
     77 }
     78 
     79 void TransitionArray::SetKey(int transition_number, Name* key) {
     80   DCHECK(transition_number < number_of_transitions());
     81   WeakFixedArray::Set(ToKeyIndex(transition_number),
     82                       HeapObjectReference::Strong(key));
     83 }
     84 
     85 HeapObjectReference** TransitionArray::GetTargetSlot(int transition_number) {
     86   DCHECK(transition_number < number_of_transitions());
     87   return reinterpret_cast<HeapObjectReference**>(
     88       RawFieldOfElementAt(ToTargetIndex(transition_number)));
     89 }
     90 
     91 // static
     92 PropertyDetails TransitionsAccessor::GetTargetDetails(Name* name, Map* target) {
     93   DCHECK(!IsSpecialTransition(name->GetReadOnlyRoots(), name));
     94   int descriptor = target->LastAdded();
     95   DescriptorArray* descriptors = target->instance_descriptors();
     96   // Transitions are allowed only for the last added property.
     97   DCHECK(descriptors->GetKey(descriptor)->Equals(name));
     98   return descriptors->GetDetails(descriptor);
     99 }
    100 
    101 // static
    102 Map* TransitionsAccessor::GetTargetFromRaw(MaybeObject* raw) {
    103   return Map::cast(raw->ToWeakHeapObject());
    104 }
    105 
    106 MaybeObject* TransitionArray::GetRawTarget(int transition_number) {
    107   DCHECK(transition_number < number_of_transitions());
    108   return Get(ToTargetIndex(transition_number));
    109 }
    110 
    111 Map* TransitionArray::GetTarget(int transition_number) {
    112   MaybeObject* raw = GetRawTarget(transition_number);
    113   return TransitionsAccessor::GetTargetFromRaw(raw);
    114 }
    115 
    116 Map* TransitionsAccessor::GetTarget(int transition_number) {
    117   switch (encoding()) {
    118     case kPrototypeInfo:
    119     case kUninitialized:
    120       UNREACHABLE();
    121       return nullptr;
    122     case kWeakRef:
    123       return Map::cast(raw_transitions_->ToWeakHeapObject());
    124     case kFullTransitionArray:
    125       return transitions()->GetTarget(transition_number);
    126   }
    127   UNREACHABLE();
    128 }
    129 
    130 void TransitionArray::SetRawTarget(int transition_number, MaybeObject* value) {
    131   DCHECK(transition_number < number_of_transitions());
    132   DCHECK(value->IsWeakHeapObject() && value->ToWeakHeapObject()->IsMap());
    133   WeakFixedArray::Set(ToTargetIndex(transition_number), value);
    134 }
    135 
    136 bool TransitionArray::GetTargetIfExists(int transition_number, Isolate* isolate,
    137                                         Map** target) {
    138   MaybeObject* raw = GetRawTarget(transition_number);
    139   HeapObject* heap_object;
    140   if (raw->ToStrongHeapObject(&heap_object) &&
    141       heap_object->IsUndefined(isolate)) {
    142     return false;
    143   }
    144   *target = TransitionsAccessor::GetTargetFromRaw(raw);
    145   return true;
    146 }
    147 
    148 int TransitionArray::SearchName(Name* name, int* out_insertion_index) {
    149   DCHECK(name->IsUniqueName());
    150   return internal::Search<ALL_ENTRIES>(this, name, number_of_entries(),
    151                                        out_insertion_index);
    152 }
    153 
    154 int TransitionArray::number_of_transitions() const {
    155   if (length() < kFirstIndex) return 0;
    156   return Smi::ToInt(Get(kTransitionLengthIndex)->ToSmi());
    157 }
    158 
    159 int TransitionArray::CompareKeys(Name* key1, uint32_t hash1, PropertyKind kind1,
    160                                  PropertyAttributes attributes1, Name* key2,
    161                                  uint32_t hash2, PropertyKind kind2,
    162                                  PropertyAttributes attributes2) {
    163   int cmp = CompareNames(key1, hash1, key2, hash2);
    164   if (cmp != 0) return cmp;
    165 
    166   return CompareDetails(kind1, attributes1, kind2, attributes2);
    167 }
    168 
    169 int TransitionArray::CompareNames(Name* key1, uint32_t hash1, Name* key2,
    170                                   uint32_t hash2) {
    171   if (key1 != key2) {
    172     // In case of hash collisions key1 is always "less" than key2.
    173     return hash1 <= hash2 ? -1 : 1;
    174   }
    175 
    176   return 0;
    177 }
    178 
    179 int TransitionArray::CompareDetails(PropertyKind kind1,
    180                                     PropertyAttributes attributes1,
    181                                     PropertyKind kind2,
    182                                     PropertyAttributes attributes2) {
    183   if (kind1 != kind2) {
    184     return static_cast<int>(kind1) < static_cast<int>(kind2) ? -1 : 1;
    185   }
    186 
    187   if (attributes1 != attributes2) {
    188     return static_cast<int>(attributes1) < static_cast<int>(attributes2) ? -1
    189                                                                          : 1;
    190   }
    191 
    192   return 0;
    193 }
    194 
    195 void TransitionArray::Set(int transition_number, Name* key,
    196                           MaybeObject* target) {
    197   WeakFixedArray::Set(ToKeyIndex(transition_number),
    198                       MaybeObject::FromObject(key));
    199   WeakFixedArray::Set(ToTargetIndex(transition_number), target);
    200 }
    201 
    202 int TransitionArray::Capacity() {
    203   if (length() <= kFirstIndex) return 0;
    204   return (length() - kFirstIndex) / kEntrySize;
    205 }
    206 
    207 void TransitionArray::SetNumberOfTransitions(int number_of_transitions) {
    208   DCHECK(number_of_transitions <= Capacity());
    209   WeakFixedArray::Set(
    210       kTransitionLengthIndex,
    211       MaybeObject::FromSmi(Smi::FromInt(number_of_transitions)));
    212 }
    213 
    214 }  // namespace internal
    215 }  // namespace v8
    216 
    217 #include "src/objects/object-macros-undef.h"
    218 
    219 #endif  // V8_TRANSITIONS_INL_H_
    220