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
10namespace v8 {
11namespace 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
30TransitionArray* TransitionArray::cast(Object* object) {
31  DCHECK(object->IsTransitionArray());
32  return reinterpret_cast<TransitionArray*>(object);
33}
34
35
36bool TransitionArray::HasElementsTransition() {
37  return Search(GetHeap()->elements_transition_symbol()) != kNotFound;
38}
39
40
41Object* TransitionArray::back_pointer_storage() {
42  return get(kBackPointerStorageIndex);
43}
44
45
46void 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
55bool TransitionArray::HasPrototypeTransitions() {
56  return IsFullTransitionArray() &&
57      get(kPrototypeTransitionsIndex) != Smi::FromInt(0);
58}
59
60
61FixedArray* TransitionArray::GetPrototypeTransitions() {
62  DCHECK(IsFullTransitionArray());
63  Object* prototype_transitions = get(kPrototypeTransitionsIndex);
64  return FixedArray::cast(prototype_transitions);
65}
66
67
68void 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
79Object** TransitionArray::GetPrototypeTransitionsSlot() {
80  return HeapObject::RawField(reinterpret_cast<HeapObject*>(this),
81                              kPrototypeTransitionsOffset);
82}
83
84
85Object** TransitionArray::GetKeySlot(int transition_number) {
86  DCHECK(!IsSimpleTransition());
87  DCHECK(transition_number < number_of_transitions());
88  return RawFieldOfElementAt(ToKeyIndex(transition_number));
89}
90
91
92Name* 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
104void 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
111Map* 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
121void 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
131PropertyDetails TransitionArray::GetTargetDetails(int transition_number) {
132  Map* map = GetTarget(transition_number);
133  return map->GetLastDescriptorDetails();
134}
135
136
137int 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
147void 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