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.
7 #include "src/objects.h"
8 #include "src/transitions-inl.h"
15 Handle<TransitionArray> TransitionArray::Allocate(Isolate* isolate,
16 int number_of_transitions,
18 Handle<FixedArray> array = isolate->factory()->NewFixedArray(
19 LengthFor(number_of_transitions + slack));
20 array->set(kPrototypeTransitionsIndex, Smi::FromInt(0));
21 array->set(kTransitionLengthIndex, Smi::FromInt(number_of_transitions));
22 return Handle<TransitionArray>::cast(array);
26 Handle<TransitionArray> TransitionArray::AllocateSimple(Isolate* isolate,
28 Handle<FixedArray> array =
29 isolate->factory()->NewFixedArray(kSimpleTransitionSize);
30 array->set(kSimpleTransitionTarget, *target);
31 return Handle<TransitionArray>::cast(array);
35 void TransitionArray::NoIncrementalWriteBarrierCopyFrom(TransitionArray* origin,
36 int origin_transition,
37 int target_transition) {
38 NoIncrementalWriteBarrierSet(target_transition,
39 origin->GetKey(origin_transition),
40 origin->GetTarget(origin_transition));
44 Handle<TransitionArray> TransitionArray::NewWith(Handle<Map> map,
47 SimpleTransitionFlag flag) {
48 Handle<TransitionArray> result;
49 Isolate* isolate = name->GetIsolate();
51 if (flag == SIMPLE_TRANSITION) {
52 result = AllocateSimple(isolate, target);
54 result = Allocate(isolate, 1);
55 result->NoIncrementalWriteBarrierSet(0, *name, *target);
57 result->set_back_pointer_storage(map->GetBackPointer());
62 Handle<TransitionArray> TransitionArray::ExtendToFullTransitionArray(
63 Handle<Map> containing_map) {
64 DCHECK(!containing_map->transitions()->IsFullTransitionArray());
65 int nof = containing_map->transitions()->number_of_transitions();
67 // A transition array may shrink during GC.
68 Handle<TransitionArray> result = Allocate(containing_map->GetIsolate(), nof);
69 DisallowHeapAllocation no_gc;
70 int new_nof = containing_map->transitions()->number_of_transitions();
73 result->Shrink(ToKeyIndex(0));
74 result->SetNumberOfTransitions(0);
75 } else if (nof == 1) {
76 result->NoIncrementalWriteBarrierCopyFrom(
77 containing_map->transitions(), kSimpleTransitionIndex, 0);
80 result->set_back_pointer_storage(
81 containing_map->transitions()->back_pointer_storage());
86 Handle<TransitionArray> TransitionArray::Insert(Handle<Map> map,
89 SimpleTransitionFlag flag) {
90 if (!map->HasTransitionArray()) {
91 return TransitionArray::NewWith(map, name, target, flag);
94 int number_of_transitions = map->transitions()->number_of_transitions();
95 int new_nof = number_of_transitions;
97 int insertion_index = kNotFound;
98 int index = map->transitions()->Search(*name, &insertion_index);
100 if (index == kNotFound) {
103 insertion_index = index;
105 DCHECK(insertion_index >= 0 && insertion_index <= number_of_transitions);
107 CHECK(new_nof <= kMaxNumberOfTransitions);
109 if (new_nof <= map->transitions()->number_of_transitions_storage()) {
110 DisallowHeapAllocation no_gc;
111 TransitionArray* array = map->transitions();
113 if (index != kNotFound) {
114 array->SetTarget(index, *target);
115 return handle(array);
118 array->SetNumberOfTransitions(new_nof);
119 for (index = number_of_transitions; index > insertion_index; --index) {
120 Name* key = array->GetKey(index - 1);
121 DCHECK(key->Hash() > name->Hash());
122 array->SetKey(index, key);
123 array->SetTarget(index, array->GetTarget(index - 1));
125 array->SetKey(index, *name);
126 array->SetTarget(index, *target);
127 return handle(array);
130 Handle<TransitionArray> result = Allocate(
131 map->GetIsolate(), new_nof,
132 Map::SlackForArraySize(number_of_transitions, kMaxNumberOfTransitions));
134 // The map's transition array may grown smaller during the allocation above as
135 // it was weakly traversed, though it is guaranteed not to disappear. Trim the
136 // result copy if needed, and recompute variables.
137 DCHECK(map->HasTransitionArray());
138 DisallowHeapAllocation no_gc;
139 TransitionArray* array = map->transitions();
140 if (array->number_of_transitions() != number_of_transitions) {
141 DCHECK(array->number_of_transitions() < number_of_transitions);
143 number_of_transitions = array->number_of_transitions();
144 new_nof = number_of_transitions;
146 insertion_index = kNotFound;
147 index = array->Search(*name, &insertion_index);
148 if (index == kNotFound) {
151 insertion_index = index;
153 DCHECK(insertion_index >= 0 && insertion_index <= number_of_transitions);
155 result->Shrink(ToKeyIndex(new_nof));
156 result->SetNumberOfTransitions(new_nof);
159 if (array->HasPrototypeTransitions()) {
160 result->SetPrototypeTransitions(array->GetPrototypeTransitions());
163 DCHECK_NE(kNotFound, insertion_index);
164 for (int i = 0; i < insertion_index; ++i) {
165 result->NoIncrementalWriteBarrierCopyFrom(array, i, i);
167 result->NoIncrementalWriteBarrierSet(insertion_index, *name, *target);
168 for (int i = insertion_index; i < number_of_transitions; ++i) {
169 result->NoIncrementalWriteBarrierCopyFrom(array, i, i + 1);
172 result->set_back_pointer_storage(array->back_pointer_storage());
177 } } // namespace v8::internal