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 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 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