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::FromInt(0);
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 return internal::Search<ALL_ENTRIES>(this, name, 0, out_insertion_index);
104 }
105
106
107 #ifdef DEBUG
IsSpecialTransition(Name * name)108 bool TransitionArray::IsSpecialTransition(Name* name) {
109 if (!name->IsSymbol()) return false;
110 Heap* heap = name->GetHeap();
111 return name == heap->nonextensible_symbol() ||
112 name == heap->sealed_symbol() || name == heap->frozen_symbol() ||
113 name == heap->elements_transition_symbol() ||
114 name == heap->strict_function_transition_symbol() ||
115 name == heap->strong_function_transition_symbol() ||
116 name == heap->observed_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