• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
transitions()20 TransitionArray* TransitionsAccessor::transitions() {
21   DCHECK_EQ(kFullTransitionArray, encoding());
22   return TransitionArray::cast(raw_transitions_->ToStrongHeapObject());
23 }
24 
CAST_ACCESSOR(TransitionArray)25 CAST_ACCESSOR(TransitionArray)
26 
27 bool TransitionArray::HasPrototypeTransitions() {
28   return Get(kPrototypeTransitionsIndex) != MaybeObject::FromSmi(Smi::kZero);
29 }
30 
GetPrototypeTransitions()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 
GetKeySlot(int transition_number)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 
SetPrototypeTransitions(WeakFixedArray * transitions)44 void TransitionArray::SetPrototypeTransitions(WeakFixedArray* transitions) {
45   DCHECK(transitions->IsWeakFixedArray());
46   WeakFixedArray::Set(kPrototypeTransitionsIndex,
47                       HeapObjectReference::Strong(transitions));
48 }
49 
NumberOfPrototypeTransitions(WeakFixedArray * proto_transitions)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 
GetKey(int transition_number)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 
GetKey(int transition_number)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 
SetKey(int transition_number,Name * key)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 
GetTargetSlot(int transition_number)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
GetTargetDetails(Name * name,Map * target)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
GetTargetFromRaw(MaybeObject * raw)102 Map* TransitionsAccessor::GetTargetFromRaw(MaybeObject* raw) {
103   return Map::cast(raw->ToWeakHeapObject());
104 }
105 
GetRawTarget(int transition_number)106 MaybeObject* TransitionArray::GetRawTarget(int transition_number) {
107   DCHECK(transition_number < number_of_transitions());
108   return Get(ToTargetIndex(transition_number));
109 }
110 
GetTarget(int transition_number)111 Map* TransitionArray::GetTarget(int transition_number) {
112   MaybeObject* raw = GetRawTarget(transition_number);
113   return TransitionsAccessor::GetTargetFromRaw(raw);
114 }
115 
GetTarget(int transition_number)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 
SetRawTarget(int transition_number,MaybeObject * value)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 
GetTargetIfExists(int transition_number,Isolate * isolate,Map ** target)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 
SearchName(Name * name,int * out_insertion_index)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 
number_of_transitions()154 int TransitionArray::number_of_transitions() const {
155   if (length() < kFirstIndex) return 0;
156   return Smi::ToInt(Get(kTransitionLengthIndex)->ToSmi());
157 }
158 
CompareKeys(Name * key1,uint32_t hash1,PropertyKind kind1,PropertyAttributes attributes1,Name * key2,uint32_t hash2,PropertyKind kind2,PropertyAttributes attributes2)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 
CompareNames(Name * key1,uint32_t hash1,Name * key2,uint32_t hash2)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 
CompareDetails(PropertyKind kind1,PropertyAttributes attributes1,PropertyKind kind2,PropertyAttributes attributes2)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 
Set(int transition_number,Name * key,MaybeObject * target)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 
Capacity()202 int TransitionArray::Capacity() {
203   if (length() <= kFirstIndex) return 0;
204   return (length() - kFirstIndex) / kEntrySize;
205 }
206 
SetNumberOfTransitions(int number_of_transitions)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