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 
cast(Object * object)14 TransitionArray* TransitionArray::cast(Object* object) {
15   DCHECK(object->IsTransitionArray());
16   return reinterpret_cast<TransitionArray*>(object);
17 }
18 
19 
next_link()20 Object* TransitionArray::next_link() { return get(kNextLinkIndex); }
21 
22 
set_next_link(Object * next,WriteBarrierMode mode)23 void TransitionArray::set_next_link(Object* next, WriteBarrierMode mode) {
24   return set(kNextLinkIndex, next, mode);
25 }
26 
27 
HasPrototypeTransitions()28 bool TransitionArray::HasPrototypeTransitions() {
29   return get(kPrototypeTransitionsIndex) != Smi::kZero;
30 }
31 
32 
GetPrototypeTransitions()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 
SetPrototypeTransitions(FixedArray * transitions)40 void TransitionArray::SetPrototypeTransitions(FixedArray* transitions) {
41   DCHECK(transitions->IsFixedArray());
42   set(kPrototypeTransitionsIndex, transitions);
43 }
44 
45 
GetPrototypeTransitionsSlot()46 Object** TransitionArray::GetPrototypeTransitionsSlot() {
47   return RawFieldOfElementAt(kPrototypeTransitionsIndex);
48 }
49 
50 
GetKeySlot(int transition_number)51 Object** TransitionArray::GetKeySlot(int transition_number) {
52   DCHECK(transition_number < number_of_transitions());
53   return RawFieldOfElementAt(ToKeyIndex(transition_number));
54 }
55 
56 
GetKey(int transition_number)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 
GetKey(Object * raw_transitions,int transition_number)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 
SetKey(int transition_number,Name * key)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 
GetTarget(int transition_number)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 
GetTarget(Object * raw_transitions,int transition_number)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 
SetTarget(int transition_number,Map * value)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 
SearchName(Name * name,int * out_insertion_index)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
IsSpecialTransition(Name * name)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 
CompareKeys(Name * key1,uint32_t hash1,PropertyKind kind1,PropertyAttributes attributes1,Name * key2,uint32_t hash2,PropertyKind kind2,PropertyAttributes attributes2)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 
CompareNames(Name * key1,uint32_t hash1,Name * key2,uint32_t hash2)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 
CompareDetails(PropertyKind kind1,PropertyAttributes attributes1,PropertyKind kind2,PropertyAttributes attributes2)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 
GetTargetDetails(Name * name,Map * target)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 
Set(int transition_number,Name * key,Map * target)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 
SetNumberOfTransitions(int number_of_transitions)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