// Copyright 2012 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef V8_TRANSITIONS_INL_H_ #define V8_TRANSITIONS_INL_H_ #include "src/transitions.h" namespace v8 { namespace internal { TransitionArray* TransitionArray::cast(Object* object) { DCHECK(object->IsTransitionArray()); return reinterpret_cast<TransitionArray*>(object); } Object* TransitionArray::next_link() { return get(kNextLinkIndex); } void TransitionArray::set_next_link(Object* next, WriteBarrierMode mode) { return set(kNextLinkIndex, next, mode); } bool TransitionArray::HasPrototypeTransitions() { return get(kPrototypeTransitionsIndex) != Smi::kZero; } FixedArray* TransitionArray::GetPrototypeTransitions() { DCHECK(HasPrototypeTransitions()); // Callers must check first. Object* prototype_transitions = get(kPrototypeTransitionsIndex); return FixedArray::cast(prototype_transitions); } void TransitionArray::SetPrototypeTransitions(FixedArray* transitions) { DCHECK(transitions->IsFixedArray()); set(kPrototypeTransitionsIndex, transitions); } Object** TransitionArray::GetPrototypeTransitionsSlot() { return RawFieldOfElementAt(kPrototypeTransitionsIndex); } Object** TransitionArray::GetKeySlot(int transition_number) { DCHECK(transition_number < number_of_transitions()); return RawFieldOfElementAt(ToKeyIndex(transition_number)); } Name* TransitionArray::GetKey(int transition_number) { DCHECK(transition_number < number_of_transitions()); return Name::cast(get(ToKeyIndex(transition_number))); } Name* TransitionArray::GetKey(Object* raw_transitions, int transition_number) { if (IsSimpleTransition(raw_transitions)) { DCHECK(transition_number == 0); return GetSimpleTransitionKey(GetSimpleTransition(raw_transitions)); } DCHECK(IsFullTransitionArray(raw_transitions)); return TransitionArray::cast(raw_transitions)->GetKey(transition_number); } void TransitionArray::SetKey(int transition_number, Name* key) { DCHECK(transition_number < number_of_transitions()); set(ToKeyIndex(transition_number), key); } Map* TransitionArray::GetTarget(int transition_number) { DCHECK(transition_number < number_of_transitions()); return Map::cast(get(ToTargetIndex(transition_number))); } Map* TransitionArray::GetTarget(Object* raw_transitions, int transition_number) { if (IsSimpleTransition(raw_transitions)) { DCHECK(transition_number == 0); return GetSimpleTransition(raw_transitions); } DCHECK(IsFullTransitionArray(raw_transitions)); return TransitionArray::cast(raw_transitions)->GetTarget(transition_number); } void TransitionArray::SetTarget(int transition_number, Map* value) { DCHECK(transition_number < number_of_transitions()); set(ToTargetIndex(transition_number), value); } int TransitionArray::SearchName(Name* name, int* out_insertion_index) { DCHECK(name->IsUniqueName()); return internal::Search<ALL_ENTRIES>(this, name, number_of_entries(), out_insertion_index); } #ifdef DEBUG bool TransitionArray::IsSpecialTransition(Name* name) { if (!name->IsSymbol()) return false; Heap* heap = name->GetHeap(); return name == heap->nonextensible_symbol() || name == heap->sealed_symbol() || name == heap->frozen_symbol() || name == heap->elements_transition_symbol() || name == heap->strict_function_transition_symbol(); } #endif int TransitionArray::CompareKeys(Name* key1, uint32_t hash1, PropertyKind kind1, PropertyAttributes attributes1, Name* key2, uint32_t hash2, PropertyKind kind2, PropertyAttributes attributes2) { int cmp = CompareNames(key1, hash1, key2, hash2); if (cmp != 0) return cmp; return CompareDetails(kind1, attributes1, kind2, attributes2); } int TransitionArray::CompareNames(Name* key1, uint32_t hash1, Name* key2, uint32_t hash2) { if (key1 != key2) { // In case of hash collisions key1 is always "less" than key2. return hash1 <= hash2 ? -1 : 1; } return 0; } int TransitionArray::CompareDetails(PropertyKind kind1, PropertyAttributes attributes1, PropertyKind kind2, PropertyAttributes attributes2) { if (kind1 != kind2) { return static_cast<int>(kind1) < static_cast<int>(kind2) ? -1 : 1; } if (attributes1 != attributes2) { return static_cast<int>(attributes1) < static_cast<int>(attributes2) ? -1 : 1; } return 0; } PropertyDetails TransitionArray::GetTargetDetails(Name* name, Map* target) { DCHECK(!IsSpecialTransition(name)); int descriptor = target->LastAdded(); DescriptorArray* descriptors = target->instance_descriptors(); // Transitions are allowed only for the last added property. DCHECK(descriptors->GetKey(descriptor)->Equals(name)); return descriptors->GetDetails(descriptor); } void TransitionArray::Set(int transition_number, Name* key, Map* target) { set(ToKeyIndex(transition_number), key); set(ToTargetIndex(transition_number), target); } void TransitionArray::SetNumberOfTransitions(int number_of_transitions) { DCHECK(number_of_transitions <= Capacity(this)); set(kTransitionLengthIndex, Smi::FromInt(number_of_transitions)); } } // namespace internal } // namespace v8 #endif // V8_TRANSITIONS_INL_H_