Replace ad-hoc weakness in transition array with WeakCell.
[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 TransitionArray* TransitionArray::cast(Object* object) {
15   DCHECK(object->IsTransitionArray());
16   return reinterpret_cast<TransitionArray*>(object);
17 }
18
19
20 bool TransitionArray::HasPrototypeTransitions() {
21   return get(kPrototypeTransitionsIndex) != Smi::FromInt(0);
22 }
23
24
25 FixedArray* TransitionArray::GetPrototypeTransitions() {
26   DCHECK(HasPrototypeTransitions());  // Callers must check first.
27   Object* prototype_transitions = get(kPrototypeTransitionsIndex);
28   return FixedArray::cast(prototype_transitions);
29 }
30
31
32 void TransitionArray::SetPrototypeTransitions(FixedArray* transitions,
33                                               WriteBarrierMode mode) {
34   DCHECK(transitions->IsFixedArray());
35   set(kPrototypeTransitionsIndex, transitions, mode);
36 }
37
38
39 Object** TransitionArray::GetPrototypeTransitionsSlot() {
40   return RawFieldOfElementAt(kPrototypeTransitionsIndex);
41 }
42
43
44 Object** TransitionArray::GetKeySlot(int transition_number) {
45   DCHECK(transition_number < number_of_transitions());
46   return RawFieldOfElementAt(ToKeyIndex(transition_number));
47 }
48
49
50 Object** TransitionArray::GetTargetSlot(int transition_number) {
51   DCHECK(transition_number < number_of_transitions());
52   return RawFieldOfElementAt(ToTargetIndex(transition_number));
53 }
54
55
56 Name* TransitionArray::GetKey(int transition_number) {
57   DCHECK(transition_number < number_of_transitions());
58   return Name::cast(get(ToKeyIndex(transition_number)));
59 }
60
61
62 Name* TransitionArray::GetKey(Object* raw_transitions, int transition_number) {
63   if (IsSimpleTransition(raw_transitions)) {
64     DCHECK(transition_number == 0);
65     return GetSimpleTransitionKey(GetSimpleTransition(raw_transitions));
66   }
67   DCHECK(IsFullTransitionArray(raw_transitions));
68   return TransitionArray::cast(raw_transitions)->GetKey(transition_number);
69 }
70
71
72 void TransitionArray::SetKey(int transition_number, Name* key) {
73   DCHECK(transition_number < number_of_transitions());
74   set(ToKeyIndex(transition_number), key);
75 }
76
77
78 Map* TransitionArray::GetTarget(int transition_number) {
79   DCHECK(transition_number < number_of_transitions());
80   WeakCell* cell = GetTargetCell(transition_number);
81   return Map::cast(cell->value());
82 }
83
84
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
96 WeakCell* TransitionArray::GetTargetCell(int transition_number) {
97   DCHECK(transition_number < number_of_transitions());
98   return WeakCell::cast(get(ToTargetIndex(transition_number)));
99 }
100
101
102 void TransitionArray::SetTargetCell(int transition_number, WeakCell* value) {
103   DCHECK(transition_number < number_of_transitions());
104   set(ToTargetIndex(transition_number), value);
105 }
106
107
108 int TransitionArray::SearchName(Name* name, int* out_insertion_index) {
109   return internal::Search<ALL_ENTRIES>(this, name, 0, out_insertion_index);
110 }
111
112
113 #ifdef DEBUG
114 bool TransitionArray::IsSpecialTransition(Name* name) {
115   if (!name->IsSymbol()) return false;
116   Heap* heap = name->GetHeap();
117   return name == heap->nonextensible_symbol() ||
118          name == heap->sealed_symbol() || name == heap->frozen_symbol() ||
119          name == heap->elements_transition_symbol() ||
120          name == heap->observed_symbol();
121 }
122 #endif
123
124
125 int TransitionArray::CompareKeys(Name* key1, uint32_t hash1, PropertyKind kind1,
126                                  PropertyAttributes attributes1, Name* key2,
127                                  uint32_t hash2, PropertyKind kind2,
128                                  PropertyAttributes attributes2) {
129   int cmp = CompareNames(key1, hash1, key2, hash2);
130   if (cmp != 0) return cmp;
131
132   return CompareDetails(kind1, attributes1, kind2, attributes2);
133 }
134
135
136 int TransitionArray::CompareNames(Name* key1, uint32_t hash1, Name* key2,
137                                   uint32_t hash2) {
138   if (key1 != key2) {
139     // In case of hash collisions key1 is always "less" than key2.
140     return hash1 <= hash2 ? -1 : 1;
141   }
142
143   return 0;
144 }
145
146
147 int TransitionArray::CompareDetails(PropertyKind kind1,
148                                     PropertyAttributes attributes1,
149                                     PropertyKind kind2,
150                                     PropertyAttributes attributes2) {
151   if (kind1 != kind2) {
152     return static_cast<int>(kind1) < static_cast<int>(kind2) ? -1 : 1;
153   }
154
155   if (attributes1 != attributes2) {
156     return static_cast<int>(attributes1) < static_cast<int>(attributes2) ? -1
157                                                                          : 1;
158   }
159
160   return 0;
161 }
162
163
164 PropertyDetails TransitionArray::GetTargetDetails(Name* name, Map* target) {
165   DCHECK(!IsSpecialTransition(name));
166   int descriptor = target->LastAdded();
167   DescriptorArray* descriptors = target->instance_descriptors();
168   // Transitions are allowed only for the last added property.
169   DCHECK(descriptors->GetKey(descriptor)->Equals(name));
170   return descriptors->GetDetails(descriptor);
171 }
172
173
174 void TransitionArray::Set(int transition_number, Name* key, WeakCell* target) {
175   set(ToKeyIndex(transition_number), key);
176   set(ToTargetIndex(transition_number), target);
177 }
178
179
180 void TransitionArray::SetNumberOfTransitions(int number_of_transitions) {
181   DCHECK(number_of_transitions <= Capacity(this));
182   set(kTransitionLengthIndex, Smi::FromInt(number_of_transitions));
183 }
184
185 } }  // namespace v8::internal
186
187 #endif  // V8_TRANSITIONS_INL_H_