Reland "Limit the number of transitions allowed per hidden class."
[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 Search(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::Search(Name* name) {
144   if (IsSimpleTransition()) {
145     Name* key = GetKey(kSimpleTransitionIndex);
146     if (key->Equals(name)) return kSimpleTransitionIndex;
147     return kNotFound;
148   }
149   return internal::Search<ALL_ENTRIES>(this, name);
150 }
151
152
153 void TransitionArray::NoIncrementalWriteBarrierSet(int transition_number,
154                                                    Name* key,
155                                                    Map* target) {
156   FixedArray::NoIncrementalWriteBarrierSet(
157       this, ToKeyIndex(transition_number), key);
158   FixedArray::NoIncrementalWriteBarrierSet(
159       this, ToTargetIndex(transition_number), target);
160 }
161
162
163 void TransitionArray::SetNumberOfTransitions(int number_of_transitions) {
164   if (IsFullTransitionArray()) {
165     DCHECK(number_of_transitions <= number_of_transitions_storage());
166     WRITE_FIELD(this, kTransitionLengthOffset,
167                 Smi::FromInt(number_of_transitions));
168   }
169 }
170
171
172 #undef FIELD_ADDR
173 #undef WRITE_FIELD
174 #undef CONDITIONAL_WRITE_BARRIER
175
176
177 } }  // namespace v8::internal
178
179 #endif  // V8_TRANSITIONS_INL_H_