Reland of "TransitionArray now uses <is_data_property, name, attributes> tuple as...
[platform/upstream/v8.git] / src / transitions-inl.h
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
14 #define FIELD_ADDR(p, offset) \
15   (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
16
17 #define WRITE_FIELD(p, offset, value) \
18   (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value)
19
20 #define CONDITIONAL_WRITE_BARRIER(heap, object, offset, value, mode)    \
21   if (mode == UPDATE_WRITE_BARRIER) {                                   \
22     heap->incremental_marking()->RecordWrite(                           \
23       object, HeapObject::RawField(object, offset), value);             \
24     if (heap->InNewSpace(value)) {                                      \
25       heap->RecordWrite(object->address(), offset);                     \
26     }                                                                   \
27   }
28
29
30 TransitionArray* TransitionArray::cast(Object* object) {
31   DCHECK(object->IsTransitionArray());
32   return reinterpret_cast<TransitionArray*>(object);
33 }
34
35
36 bool TransitionArray::HasElementsTransition() {
37   return SearchSpecial(GetHeap()->elements_transition_symbol()) != kNotFound;
38 }
39
40
41 Object* TransitionArray::back_pointer_storage() {
42   return get(kBackPointerStorageIndex);
43 }
44
45
46 void TransitionArray::set_back_pointer_storage(Object* back_pointer,
47                                                WriteBarrierMode mode) {
48   Heap* heap = GetHeap();
49   WRITE_FIELD(this, kBackPointerStorageOffset, back_pointer);
50   CONDITIONAL_WRITE_BARRIER(
51       heap, this, kBackPointerStorageOffset, back_pointer, mode);
52 }
53
54
55 bool TransitionArray::HasPrototypeTransitions() {
56   return IsFullTransitionArray() &&
57       get(kPrototypeTransitionsIndex) != Smi::FromInt(0);
58 }
59
60
61 FixedArray* TransitionArray::GetPrototypeTransitions() {
62   DCHECK(IsFullTransitionArray());
63   Object* prototype_transitions = get(kPrototypeTransitionsIndex);
64   return FixedArray::cast(prototype_transitions);
65 }
66
67
68 void TransitionArray::SetPrototypeTransitions(FixedArray* transitions,
69                                               WriteBarrierMode mode) {
70   DCHECK(IsFullTransitionArray());
71   DCHECK(transitions->IsFixedArray());
72   Heap* heap = GetHeap();
73   WRITE_FIELD(this, kPrototypeTransitionsOffset, transitions);
74   CONDITIONAL_WRITE_BARRIER(
75       heap, this, kPrototypeTransitionsOffset, transitions, mode);
76 }
77
78
79 Object** TransitionArray::GetPrototypeTransitionsSlot() {
80   return HeapObject::RawField(reinterpret_cast<HeapObject*>(this),
81                               kPrototypeTransitionsOffset);
82 }
83
84
85 Object** TransitionArray::GetKeySlot(int transition_number) {
86   DCHECK(!IsSimpleTransition());
87   DCHECK(transition_number < number_of_transitions());
88   return RawFieldOfElementAt(ToKeyIndex(transition_number));
89 }
90
91
92 Name* TransitionArray::GetKey(int transition_number) {
93   if (IsSimpleTransition()) {
94     Map* target = GetTarget(kSimpleTransitionIndex);
95     int descriptor = target->LastAdded();
96     Name* key = target->instance_descriptors()->GetKey(descriptor);
97     return key;
98   }
99   DCHECK(transition_number < number_of_transitions());
100   return Name::cast(get(ToKeyIndex(transition_number)));
101 }
102
103
104 void TransitionArray::SetKey(int transition_number, Name* key) {
105   DCHECK(!IsSimpleTransition());
106   DCHECK(transition_number < number_of_transitions());
107   set(ToKeyIndex(transition_number), key);
108 }
109
110
111 Map* TransitionArray::GetTarget(int transition_number) {
112   if (IsSimpleTransition()) {
113     DCHECK(transition_number == kSimpleTransitionIndex);
114     return Map::cast(get(kSimpleTransitionTarget));
115   }
116   DCHECK(transition_number < number_of_transitions());
117   return Map::cast(get(ToTargetIndex(transition_number)));
118 }
119
120
121 void TransitionArray::SetTarget(int transition_number, Map* value) {
122   if (IsSimpleTransition()) {
123     DCHECK(transition_number == kSimpleTransitionIndex);
124     return set(kSimpleTransitionTarget, value);
125   }
126   DCHECK(transition_number < number_of_transitions());
127   set(ToTargetIndex(transition_number), value);
128 }
129
130
131 PropertyDetails TransitionArray::GetTargetDetails(int transition_number) {
132   Map* map = GetTarget(transition_number);
133   return map->GetLastDescriptorDetails();
134 }
135
136
137 Object* TransitionArray::GetTargetValue(int transition_number) {
138   Map* map = GetTarget(transition_number);
139   return map->instance_descriptors()->GetValue(map->LastAdded());
140 }
141
142
143 int TransitionArray::SearchName(Name* name, int* out_insertion_index) {
144   if (IsSimpleTransition()) {
145     Name* key = GetKey(kSimpleTransitionIndex);
146     if (key->Equals(name)) return kSimpleTransitionIndex;
147     if (out_insertion_index != NULL) {
148       *out_insertion_index = key->Hash() > name->Hash() ? 0 : 1;
149     }
150     return kNotFound;
151   }
152   return internal::Search<ALL_ENTRIES>(this, name, 0, out_insertion_index);
153 }
154
155
156 #ifdef DEBUG
157 bool TransitionArray::IsSpecialTransition(Name* name) {
158   if (!name->IsSymbol()) return false;
159   Heap* heap = name->GetHeap();
160   return name == heap->frozen_symbol() ||
161          name == heap->elements_transition_symbol() ||
162          name == heap->observed_symbol();
163 }
164 #endif
165
166
167 int TransitionArray::CompareKeys(Name* key1, uint32_t hash1,
168                                  bool is_data_property1,
169                                  PropertyAttributes attributes1, Name* key2,
170                                  uint32_t hash2, bool is_data_property2,
171                                  PropertyAttributes attributes2) {
172   int cmp = CompareNames(key1, hash1, key2, hash2);
173   if (cmp != 0) return cmp;
174
175   return CompareDetails(is_data_property1, attributes1, is_data_property2,
176                         attributes2);
177 }
178
179
180 int TransitionArray::CompareNames(Name* key1, uint32_t hash1, Name* key2,
181                                   uint32_t hash2) {
182   if (key1 != key2) {
183     // In case of hash collisions key1 is always "less" than key2.
184     return hash1 <= hash2 ? -1 : 1;
185   }
186
187   return 0;
188 }
189
190
191 int TransitionArray::CompareDetails(bool is_data_property1,
192                                     PropertyAttributes attributes1,
193                                     bool is_data_property2,
194                                     PropertyAttributes attributes2) {
195   if (is_data_property1 != is_data_property2) {
196     return static_cast<int>(is_data_property1) <
197                    static_cast<int>(is_data_property2)
198                ? -1
199                : 1;
200   }
201
202   if (attributes1 != attributes2) {
203     return static_cast<int>(attributes1) < static_cast<int>(attributes2) ? -1
204                                                                          : 1;
205   }
206
207   return 0;
208 }
209
210
211 PropertyDetails TransitionArray::GetTargetDetails(Name* name, Map* target) {
212   DCHECK(!IsSpecialTransition(name));
213   int descriptor = target->LastAdded();
214   DescriptorArray* descriptors = target->instance_descriptors();
215   // Transitions are allowed only for the last added property.
216   DCHECK(descriptors->GetKey(descriptor)->Equals(name));
217   return descriptors->GetDetails(descriptor);
218 }
219
220
221 void TransitionArray::NoIncrementalWriteBarrierSet(int transition_number,
222                                                    Name* key,
223                                                    Map* target) {
224   FixedArray::NoIncrementalWriteBarrierSet(
225       this, ToKeyIndex(transition_number), key);
226   FixedArray::NoIncrementalWriteBarrierSet(
227       this, ToTargetIndex(transition_number), target);
228 }
229
230
231 void TransitionArray::SetNumberOfTransitions(int number_of_transitions) {
232   if (IsFullTransitionArray()) {
233     DCHECK(number_of_transitions <= number_of_transitions_storage());
234     WRITE_FIELD(this, kTransitionLengthOffset,
235                 Smi::FromInt(number_of_transitions));
236   }
237 }
238
239
240 #undef FIELD_ADDR
241 #undef WRITE_FIELD
242 #undef CONDITIONAL_WRITE_BARRIER
243
244
245 } }  // namespace v8::internal
246
247 #endif  // V8_TRANSITIONS_INL_H_