transitions-inl.h 7.27 KB
Newer Older
1
// Copyright 2012 the V8 project authors. All rights reserved.
2 3
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
4 5 6 7

#ifndef V8_TRANSITIONS_INL_H_
#define V8_TRANSITIONS_INL_H_

8
#include "src/transitions.h"
9

10
#include "src/ic/handler-configuration-inl.h"
11 12
#include "src/objects/fixed-array-inl.h"
#include "src/objects/maybe-object-inl.h"
13

14 15 16
// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"

17 18 19
namespace v8 {
namespace internal {

20 21
TransitionArray* TransitionsAccessor::transitions() {
  DCHECK_EQ(kFullTransitionArray, encoding());
22
  return TransitionArray::cast(raw_transitions_->GetHeapObjectAssumeStrong());
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)->GetHeapObjectAssumeStrong();
35
  return WeakFixedArray::cast(prototype_transitions);
36 37
}

38 39 40 41 42
HeapObjectReference** TransitionArray::GetKeySlot(int transition_number) {
  DCHECK(transition_number < number_of_transitions());
  return reinterpret_cast<HeapObjectReference**>(
      RawFieldOfElementAt(ToKeyIndex(transition_number)));
}
43

44 45
void TransitionArray::SetPrototypeTransitions(WeakFixedArray* transitions) {
  DCHECK(transitions->IsWeakFixedArray());
46 47
  WeakFixedArray::Set(kPrototypeTransitionsIndex,
                      HeapObjectReference::Strong(transitions));
48 49
}

50 51 52 53 54
int TransitionArray::NumberOfPrototypeTransitions(
    WeakFixedArray* proto_transitions) {
  if (proto_transitions->length() == 0) return 0;
  MaybeObject* raw =
      proto_transitions->Get(kProtoTransitionNumberOfEntriesOffset);
55
  return Smi::ToInt(raw->cast<Smi>());
56
}
57

58
Name* TransitionArray::GetKey(int transition_number) {
59
  DCHECK(transition_number < number_of_transitions());
60 61
  return Name::cast(
      Get(ToKeyIndex(transition_number))->GetHeapObjectAssumeStrong());
62 63
}

64 65 66 67 68 69
Name* TransitionsAccessor::GetKey(int transition_number) {
  switch (encoding()) {
    case kPrototypeInfo:
    case kUninitialized:
      UNREACHABLE();
      return nullptr;
70
    case kWeakRef: {
71
      Map* map = Map::cast(raw_transitions_->GetHeapObjectAssumeWeak());
72
      return GetSimpleTransitionKey(map);
73
    }
74 75
    case kFullTransitionArray:
      return transitions()->GetKey(transition_number);
76
  }
77
  UNREACHABLE();
78 79
}

80
void TransitionArray::SetKey(int transition_number, Name* key) {
81
  DCHECK(transition_number < number_of_transitions());
82 83
  WeakFixedArray::Set(ToKeyIndex(transition_number),
                      HeapObjectReference::Strong(key));
84 85
}

86
HeapObjectReference** TransitionArray::GetTargetSlot(int transition_number) {
87
  DCHECK(transition_number < number_of_transitions());
88 89
  return reinterpret_cast<HeapObjectReference**>(
      RawFieldOfElementAt(ToTargetIndex(transition_number)));
90 91
}

92
// static
93 94
PropertyDetails TransitionsAccessor::GetTargetDetails(Name* name, Map* target) {
  DCHECK(!IsSpecialTransition(name->GetReadOnlyRoots(), name));
95 96 97 98 99 100
  int descriptor = target->LastAdded();
  DescriptorArray* descriptors = target->instance_descriptors();
  // Transitions are allowed only for the last added property.
  DCHECK(descriptors->GetKey(descriptor)->Equals(name));
  return descriptors->GetDetails(descriptor);
}
101

102
// static
103
Map* TransitionsAccessor::GetTargetFromRaw(MaybeObject* raw) {
104
  return Map::cast(raw->GetHeapObjectAssumeWeak());
105 106
}

107
MaybeObject* TransitionArray::GetRawTarget(int transition_number) {
108
  DCHECK(transition_number < number_of_transitions());
109
  return Get(ToTargetIndex(transition_number));
110
}
111

112
Map* TransitionArray::GetTarget(int transition_number) {
113
  MaybeObject* raw = GetRawTarget(transition_number);
114 115 116 117 118 119 120 121 122
  return TransitionsAccessor::GetTargetFromRaw(raw);
}

Map* TransitionsAccessor::GetTarget(int transition_number) {
  switch (encoding()) {
    case kPrototypeInfo:
    case kUninitialized:
      UNREACHABLE();
      return nullptr;
123
    case kWeakRef:
124
      return Map::cast(raw_transitions_->GetHeapObjectAssumeWeak());
125 126 127
    case kFullTransitionArray:
      return transitions()->GetTarget(transition_number);
  }
128
  UNREACHABLE();
129 130
}

131
void TransitionArray::SetRawTarget(int transition_number, MaybeObject* value) {
132
  DCHECK(transition_number < number_of_transitions());
133 134
  DCHECK(value->IsWeak());
  DCHECK(value->GetHeapObjectAssumeWeak()->IsMap());
135
  WeakFixedArray::Set(ToTargetIndex(transition_number), value);
136 137
}

138 139
bool TransitionArray::GetTargetIfExists(int transition_number, Isolate* isolate,
                                        Map** target) {
140 141
  MaybeObject* raw = GetRawTarget(transition_number);
  HeapObject* heap_object;
142
  if (raw->GetHeapObjectIfStrong(&heap_object) &&
143
      heap_object->IsUndefined(isolate)) {
144 145 146 147 148
    return false;
  }
  *target = TransitionsAccessor::GetTargetFromRaw(raw);
  return true;
}
149

150
int TransitionArray::SearchName(Name* name, int* out_insertion_index) {
151
  DCHECK(name->IsUniqueName());
152 153
  return internal::Search<ALL_ENTRIES>(this, name, number_of_entries(),
                                       out_insertion_index);
154 155
}

156 157
int TransitionArray::number_of_transitions() const {
  if (length() < kFirstIndex) return 0;
158
  return Smi::ToInt(Get(kTransitionLengthIndex)->cast<Smi>());
159 160
}

161
int TransitionArray::CompareKeys(Name* key1, uint32_t hash1, PropertyKind kind1,
162
                                 PropertyAttributes attributes1, Name* key2,
163
                                 uint32_t hash2, PropertyKind kind2,
164 165 166 167
                                 PropertyAttributes attributes2) {
  int cmp = CompareNames(key1, hash1, key2, hash2);
  if (cmp != 0) return cmp;

168
  return CompareDetails(kind1, attributes1, kind2, attributes2);
169 170 171 172 173 174 175 176 177 178 179 180
}

int TransitionArray::CompareNames(Name* key1, uint32_t hash1, Name* key2,
                                  uint32_t hash2) {
  if (key1 != key2) {
    // In case of hash collisions key1 is always "less" than key2.
    return hash1 <= hash2 ? -1 : 1;
  }

  return 0;
}

181
int TransitionArray::CompareDetails(PropertyKind kind1,
182
                                    PropertyAttributes attributes1,
183
                                    PropertyKind kind2,
184
                                    PropertyAttributes attributes2) {
185 186
  if (kind1 != kind2) {
    return static_cast<int>(kind1) < static_cast<int>(kind2) ? -1 : 1;
187 188 189 190 191 192 193 194 195 196
  }

  if (attributes1 != attributes2) {
    return static_cast<int>(attributes1) < static_cast<int>(attributes2) ? -1
                                                                         : 1;
  }

  return 0;
}

197 198 199 200 201
void TransitionArray::Set(int transition_number, Name* key,
                          MaybeObject* target) {
  WeakFixedArray::Set(ToKeyIndex(transition_number),
                      MaybeObject::FromObject(key));
  WeakFixedArray::Set(ToTargetIndex(transition_number), target);
202 203
}

204 205
int TransitionArray::Capacity() {
  if (length() <= kFirstIndex) return 0;
206
  return (length() - kFirstIndex) / kEntrySize;
207
}
208

209
void TransitionArray::SetNumberOfTransitions(int number_of_transitions) {
210
  DCHECK(number_of_transitions <= Capacity());
211 212 213
  WeakFixedArray::Set(
      kTransitionLengthIndex,
      MaybeObject::FromSmi(Smi::FromInt(number_of_transitions)));
214 215
}

216 217
}  // namespace internal
}  // namespace v8
218

219 220
#include "src/objects/object-macros-undef.h"

221
#endif  // V8_TRANSITIONS_INL_H_