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 
cast(Object * object)30 TransitionArray* TransitionArray::cast(Object* object) {
31   DCHECK(object->IsTransitionArray());
32   return reinterpret_cast<TransitionArray*>(object);
33 }
34 
35 
HasElementsTransition()36 bool TransitionArray::HasElementsTransition() {
37   return Search(GetHeap()->elements_transition_symbol()) != kNotFound;
38 }
39 
40 
back_pointer_storage()41 Object* TransitionArray::back_pointer_storage() {
42   return get(kBackPointerStorageIndex);
43 }
44 
45 
set_back_pointer_storage(Object * back_pointer,WriteBarrierMode mode)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 
HasPrototypeTransitions()55 bool TransitionArray::HasPrototypeTransitions() {
56   return IsFullTransitionArray() &&
57       get(kPrototypeTransitionsIndex) != Smi::FromInt(0);
58 }
59 
60 
GetPrototypeTransitions()61 FixedArray* TransitionArray::GetPrototypeTransitions() {
62   DCHECK(IsFullTransitionArray());
63   Object* prototype_transitions = get(kPrototypeTransitionsIndex);
64   return FixedArray::cast(prototype_transitions);
65 }
66 
67 
SetPrototypeTransitions(FixedArray * transitions,WriteBarrierMode mode)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 
GetPrototypeTransitionsSlot()79 Object** TransitionArray::GetPrototypeTransitionsSlot() {
80   return HeapObject::RawField(reinterpret_cast<HeapObject*>(this),
81                               kPrototypeTransitionsOffset);
82 }
83 
84 
GetKeySlot(int transition_number)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 
GetKey(int transition_number)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 
SetKey(int transition_number,Name * key)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 
GetTarget(int transition_number)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 
SetTarget(int transition_number,Map * value)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 
GetTargetDetails(int transition_number)131 PropertyDetails TransitionArray::GetTargetDetails(int transition_number) {
132   Map* map = GetTarget(transition_number);
133   return map->GetLastDescriptorDetails();
134 }
135 
136 
Search(Name * name)137 int TransitionArray::Search(Name* name) {
138   if (IsSimpleTransition()) {
139     Name* key = GetKey(kSimpleTransitionIndex);
140     if (key->Equals(name)) return kSimpleTransitionIndex;
141     return kNotFound;
142   }
143   return internal::Search<ALL_ENTRIES>(this, name);
144 }
145 
146 
NoIncrementalWriteBarrierSet(int transition_number,Name * key,Map * target)147 void TransitionArray::NoIncrementalWriteBarrierSet(int transition_number,
148                                                    Name* key,
149                                                    Map* target) {
150   FixedArray::NoIncrementalWriteBarrierSet(
151       this, ToKeyIndex(transition_number), key);
152   FixedArray::NoIncrementalWriteBarrierSet(
153       this, ToTargetIndex(transition_number), target);
154 }
155 
156 
157 #undef FIELD_ADDR
158 #undef WRITE_FIELD
159 #undef CONDITIONAL_WRITE_BARRIER
160 
161 
162 } }  // namespace v8::internal
163 
164 #endif  // V8_TRANSITIONS_INL_H_
165