fd8eb8b0b652a463365591b3a0b7a9f00e3bb9a4
[platform/upstream/nodejs.git] / deps / v8 / 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->nonextensible_symbol() ||
161          name == heap->sealed_symbol() || name == heap->frozen_symbol() ||
162          name == heap->elements_transition_symbol() ||
163          name == heap->observed_symbol();
164 }
165 #endif
166
167
168 int TransitionArray::CompareKeys(Name* key1, uint32_t hash1, PropertyKind kind1,
169                                  PropertyAttributes attributes1, Name* key2,
170                                  uint32_t hash2, PropertyKind kind2,
171                                  PropertyAttributes attributes2) {
172   int cmp = CompareNames(key1, hash1, key2, hash2);
173   if (cmp != 0) return cmp;
174
175   return CompareDetails(kind1, attributes1, kind2, attributes2);
176 }
177
178
179 int TransitionArray::CompareNames(Name* key1, uint32_t hash1, Name* key2,
180                                   uint32_t hash2) {
181   if (key1 != key2) {
182     // In case of hash collisions key1 is always "less" than key2.
183     return hash1 <= hash2 ? -1 : 1;
184   }
185
186   return 0;
187 }
188
189
190 int TransitionArray::CompareDetails(PropertyKind kind1,
191                                     PropertyAttributes attributes1,
192                                     PropertyKind kind2,
193                                     PropertyAttributes attributes2) {
194   if (kind1 != kind2) {
195     return static_cast<int>(kind1) < static_cast<int>(kind2) ? -1 : 1;
196   }
197
198   if (attributes1 != attributes2) {
199     return static_cast<int>(attributes1) < static_cast<int>(attributes2) ? -1
200                                                                          : 1;
201   }
202
203   return 0;
204 }
205
206
207 PropertyDetails TransitionArray::GetTargetDetails(Name* name, Map* target) {
208   DCHECK(!IsSpecialTransition(name));
209   int descriptor = target->LastAdded();
210   DescriptorArray* descriptors = target->instance_descriptors();
211   // Transitions are allowed only for the last added property.
212   DCHECK(descriptors->GetKey(descriptor)->Equals(name));
213   return descriptors->GetDetails(descriptor);
214 }
215
216
217 void TransitionArray::NoIncrementalWriteBarrierSet(int transition_number,
218                                                    Name* key,
219                                                    Map* target) {
220   FixedArray::NoIncrementalWriteBarrierSet(
221       this, ToKeyIndex(transition_number), key);
222   FixedArray::NoIncrementalWriteBarrierSet(
223       this, ToTargetIndex(transition_number), target);
224 }
225
226
227 void TransitionArray::SetNumberOfTransitions(int number_of_transitions) {
228   if (IsFullTransitionArray()) {
229     DCHECK(number_of_transitions <= number_of_transitions_storage());
230     WRITE_FIELD(this, kTransitionLengthOffset,
231                 Smi::FromInt(number_of_transitions));
232   }
233 }
234
235
236 #undef FIELD_ADDR
237 #undef WRITE_FIELD
238 #undef CONDITIONAL_WRITE_BARRIER
239
240
241 } }  // namespace v8::internal
242
243 #endif  // V8_TRANSITIONS_INL_H_