Index: src/transitions.cc |
diff --git a/src/transitions.cc b/src/transitions.cc |
index 6154b4c1e10db478fc58186d4a396f2e4c5038c3..43fc90b1b51796ddd8c96fd478f902ea822c8a3a 100644 |
--- a/src/transitions.cc |
+++ b/src/transitions.cc |
@@ -11,326 +11,6 @@ |
namespace v8 { |
namespace internal { |
- |
-// static |
-void TransitionArray::Insert(Handle<Map> map, Handle<Name> name, |
- Handle<Map> target, SimpleTransitionFlag flag) { |
- Isolate* isolate = map->GetIsolate(); |
- target->SetBackPointer(*map); |
- |
- // If the map doesn't have any transitions at all yet, install the new one. |
- if (CanStoreSimpleTransition(map->raw_transitions())) { |
- if (flag == SIMPLE_PROPERTY_TRANSITION) { |
- Handle<WeakCell> cell = Map::WeakCellForMap(target); |
- map->set_raw_transitions(*cell); |
- return; |
- } |
- // If the flag requires a full TransitionArray, allocate one. |
- Handle<TransitionArray> result = Allocate(isolate, 0, 1); |
- map->set_raw_transitions(*result); |
- } |
- |
- bool is_special_transition = flag == SPECIAL_TRANSITION; |
- // If the map has a simple transition, check if it should be overwritten. |
- if (IsSimpleTransition(map->raw_transitions())) { |
- Map* old_target = GetSimpleTransition(map->raw_transitions()); |
- Name* key = GetSimpleTransitionKey(old_target); |
- PropertyDetails old_details = GetSimpleTargetDetails(old_target); |
- PropertyDetails new_details = is_special_transition |
- ? PropertyDetails(NONE, DATA, 0) |
- : GetTargetDetails(*name, *target); |
- if (flag == SIMPLE_PROPERTY_TRANSITION && key->Equals(*name) && |
- old_details.kind() == new_details.kind() && |
- old_details.attributes() == new_details.attributes()) { |
- Handle<WeakCell> cell = Map::WeakCellForMap(target); |
- map->set_raw_transitions(*cell); |
- return; |
- } |
- // Otherwise allocate a full TransitionArray with slack for a new entry. |
- Handle<TransitionArray> result = Allocate(isolate, 1, 1); |
- // Re-read existing data; the allocation might have caused it to be cleared. |
- if (IsSimpleTransition(map->raw_transitions())) { |
- old_target = GetSimpleTransition(map->raw_transitions()); |
- result->NoIncrementalWriteBarrierSet( |
- 0, GetSimpleTransitionKey(old_target), old_target); |
- } else { |
- result->SetNumberOfTransitions(0); |
- } |
- map->set_raw_transitions(*result); |
- } |
- |
- // At this point, we know that the map has a full TransitionArray. |
- DCHECK(IsFullTransitionArray(map->raw_transitions())); |
- |
- int number_of_transitions = 0; |
- int new_nof = 0; |
- int insertion_index = kNotFound; |
- DCHECK_EQ(is_special_transition, IsSpecialTransition(*name)); |
- PropertyDetails details = is_special_transition |
- ? PropertyDetails(NONE, DATA, 0) |
- : GetTargetDetails(*name, *target); |
- |
- { |
- DisallowHeapAllocation no_gc; |
- TransitionArray* array = TransitionArray::cast(map->raw_transitions()); |
- number_of_transitions = array->number_of_transitions(); |
- new_nof = number_of_transitions; |
- |
- int index = |
- is_special_transition |
- ? array->SearchSpecial(Symbol::cast(*name), &insertion_index) |
- : array->Search(details.kind(), *name, details.attributes(), |
- &insertion_index); |
- // If an existing entry was found, overwrite it and return. |
- if (index != kNotFound) { |
- array->SetTarget(index, *target); |
- return; |
- } |
- |
- ++new_nof; |
- CHECK(new_nof <= kMaxNumberOfTransitions); |
- DCHECK(insertion_index >= 0 && insertion_index <= number_of_transitions); |
- |
- // If there is enough capacity, insert new entry into the existing array. |
- if (new_nof <= Capacity(array)) { |
- array->SetNumberOfTransitions(new_nof); |
- for (index = number_of_transitions; index > insertion_index; --index) { |
- array->SetKey(index, array->GetKey(index - 1)); |
- array->SetTarget(index, array->GetTarget(index - 1)); |
- } |
- array->SetKey(index, *name); |
- array->SetTarget(index, *target); |
- SLOW_DCHECK(array->IsSortedNoDuplicates()); |
- return; |
- } |
- } |
- |
- // We're gonna need a bigger TransitionArray. |
- Handle<TransitionArray> result = Allocate( |
- map->GetIsolate(), new_nof, |
- Map::SlackForArraySize(number_of_transitions, kMaxNumberOfTransitions)); |
- |
- // The map's transition array may have shrunk during the allocation above as |
- // it was weakly traversed, though it is guaranteed not to disappear. Trim the |
- // result copy if needed, and recompute variables. |
- DCHECK(IsFullTransitionArray(map->raw_transitions())); |
- DisallowHeapAllocation no_gc; |
- TransitionArray* array = TransitionArray::cast(map->raw_transitions()); |
- if (array->number_of_transitions() != number_of_transitions) { |
- DCHECK(array->number_of_transitions() < number_of_transitions); |
- |
- number_of_transitions = array->number_of_transitions(); |
- new_nof = number_of_transitions; |
- |
- insertion_index = kNotFound; |
- int index = |
- is_special_transition |
- ? array->SearchSpecial(Symbol::cast(*name), &insertion_index) |
- : array->Search(details.kind(), *name, details.attributes(), |
- &insertion_index); |
- if (index == kNotFound) { |
- ++new_nof; |
- } else { |
- insertion_index = index; |
- } |
- DCHECK(insertion_index >= 0 && insertion_index <= number_of_transitions); |
- |
- result->Shrink(ToKeyIndex(new_nof)); |
- result->SetNumberOfTransitions(new_nof); |
- } |
- |
- if (array->HasPrototypeTransitions()) { |
- result->SetPrototypeTransitions(array->GetPrototypeTransitions()); |
- } |
- |
- DCHECK_NE(kNotFound, insertion_index); |
- for (int i = 0; i < insertion_index; ++i) { |
- result->NoIncrementalWriteBarrierCopyFrom(array, i, i); |
- } |
- result->NoIncrementalWriteBarrierSet(insertion_index, *name, *target); |
- for (int i = insertion_index; i < number_of_transitions; ++i) { |
- result->NoIncrementalWriteBarrierCopyFrom(array, i, i + 1); |
- } |
- |
- SLOW_DCHECK(result->IsSortedNoDuplicates()); |
- map->set_raw_transitions(*result); |
-} |
- |
- |
-// static |
-Map* TransitionArray::SearchTransition(Map* map, PropertyKind kind, Name* name, |
- PropertyAttributes attributes) { |
- Object* raw_transitions = map->raw_transitions(); |
- if (IsSimpleTransition(raw_transitions)) { |
- Map* target = GetSimpleTransition(raw_transitions); |
- Name* key = GetSimpleTransitionKey(target); |
- if (!key->Equals(name)) return NULL; |
- PropertyDetails details = GetSimpleTargetDetails(target); |
- if (details.attributes() != attributes) return NULL; |
- if (details.kind() != kind) return NULL; |
- return target; |
- } |
- if (IsFullTransitionArray(raw_transitions)) { |
- TransitionArray* transitions = TransitionArray::cast(raw_transitions); |
- int transition = transitions->Search(kind, name, attributes); |
- if (transition == kNotFound) return NULL; |
- return transitions->GetTarget(transition); |
- } |
- return NULL; |
-} |
- |
- |
-// static |
-Map* TransitionArray::SearchSpecial(Map* map, Symbol* name) { |
- Object* raw_transitions = map->raw_transitions(); |
- if (IsFullTransitionArray(raw_transitions)) { |
- TransitionArray* transitions = TransitionArray::cast(raw_transitions); |
- int transition = transitions->SearchSpecial(name); |
- if (transition == kNotFound) return NULL; |
- return transitions->GetTarget(transition); |
- } |
- return NULL; |
-} |
- |
- |
-// static |
-Handle<Map> TransitionArray::FindTransitionToField(Handle<Map> map, |
- Handle<Name> name) { |
- DisallowHeapAllocation no_gc; |
- Map* target = SearchTransition(*map, kData, *name, NONE); |
- if (target == NULL) return Handle<Map>::null(); |
- PropertyDetails details = target->GetLastDescriptorDetails(); |
- DCHECK_EQ(NONE, details.attributes()); |
- if (details.type() != DATA) return Handle<Map>::null(); |
- return Handle<Map>(target); |
-} |
- |
- |
-// static |
-Handle<String> TransitionArray::ExpectedTransitionKey(Handle<Map> map) { |
- DisallowHeapAllocation no_gc; |
- Object* raw_transition = map->raw_transitions(); |
- if (!IsSimpleTransition(raw_transition)) return Handle<String>::null(); |
- Map* target = GetSimpleTransition(raw_transition); |
- PropertyDetails details = GetSimpleTargetDetails(target); |
- if (details.type() != DATA) return Handle<String>::null(); |
- if (details.attributes() != NONE) return Handle<String>::null(); |
- Name* name = GetSimpleTransitionKey(target); |
- if (!name->IsString()) return Handle<String>::null(); |
- return Handle<String>(String::cast(name)); |
-} |
- |
- |
-// static |
-bool TransitionArray::CanHaveMoreTransitions(Handle<Map> map) { |
- Object* raw_transitions = map->raw_transitions(); |
- if (IsFullTransitionArray(raw_transitions)) { |
- TransitionArray* transitions = TransitionArray::cast(raw_transitions); |
- return transitions->number_of_transitions() < kMaxNumberOfTransitions; |
- } |
- return true; |
-} |
- |
- |
-// static |
-Handle<Map> TransitionArray::PutPrototypeTransition(Handle<Map> map, |
- Handle<Object> prototype, |
- Handle<Map> target_map) { |
- DCHECK(HeapObject::cast(*prototype)->map()->IsMap()); |
- // Don't cache prototype transition if this map is either shared, or a map of |
- // a prototype. |
- if (map->is_prototype_map()) return map; |
- if (map->is_dictionary_map() || !FLAG_cache_prototype_transitions) return map; |
- |
- const int header = kProtoTransitionHeaderSize; |
- |
- Handle<FixedArray> cache(GetPrototypeTransitions(*map)); |
- int capacity = cache->length() - header; |
- int transitions = NumberOfPrototypeTransitions(*cache) + 1; |
- |
- if (transitions > capacity) { |
- // Grow array by factor 2 up to MaxCachedPrototypeTransitions. |
- int new_capacity = Min(kMaxCachedPrototypeTransitions, transitions * 2); |
- if (new_capacity == capacity) return map; |
- |
- cache = FixedArray::CopySize(cache, header + new_capacity); |
- if (capacity < 0) { |
- // There was no prototype transitions array before, so the size |
- // couldn't be copied. Initialize it explicitly. |
- SetNumberOfPrototypeTransitions(*cache, 0); |
- } |
- |
- SetPrototypeTransitions(map, cache); |
- } |
- |
- // Reload number of transitions as GC might shrink them. |
- int last = NumberOfPrototypeTransitions(*cache); |
- int entry = header + last; |
- |
- cache->set(entry, *target_map); |
- SetNumberOfPrototypeTransitions(*cache, last + 1); |
- |
- return map; |
-} |
- |
- |
-// static |
-Handle<Map> TransitionArray::GetPrototypeTransition(Handle<Map> map, |
- Handle<Object> prototype) { |
- DisallowHeapAllocation no_gc; |
- FixedArray* cache = GetPrototypeTransitions(*map); |
- int number_of_transitions = NumberOfPrototypeTransitions(cache); |
- for (int i = 0; i < number_of_transitions; i++) { |
- Map* target = Map::cast(cache->get(kProtoTransitionHeaderSize + i)); |
- if (target->prototype() == *prototype) return handle(target); |
- } |
- return Handle<Map>(); |
-} |
- |
- |
-// static |
-FixedArray* TransitionArray::GetPrototypeTransitions(Map* map) { |
- Object* raw_transitions = map->raw_transitions(); |
- Heap* heap = map->GetHeap(); |
- if (!IsFullTransitionArray(raw_transitions)) { |
- return heap->empty_fixed_array(); |
- } |
- TransitionArray* transitions = TransitionArray::cast(raw_transitions); |
- if (!transitions->HasPrototypeTransitions()) { |
- return heap->empty_fixed_array(); |
- } |
- return transitions->GetPrototypeTransitions(); |
-} |
- |
- |
-// static |
-void TransitionArray::SetNumberOfPrototypeTransitions( |
- FixedArray* proto_transitions, int value) { |
- DCHECK(proto_transitions->length() != 0); |
- proto_transitions->set(kProtoTransitionNumberOfEntriesOffset, |
- Smi::FromInt(value)); |
-} |
- |
- |
-// static |
-int TransitionArray::NumberOfTransitions(Object* raw_transitions) { |
- if (CanStoreSimpleTransition(raw_transitions)) return 0; |
- if (IsSimpleTransition(raw_transitions)) return 1; |
- DCHECK(IsFullTransitionArray(raw_transitions)); |
- return TransitionArray::cast(raw_transitions)->number_of_transitions(); |
-} |
- |
- |
-// static |
-int TransitionArray::Capacity(Object* raw_transitions) { |
- if (!IsFullTransitionArray(raw_transitions)) return 1; |
- TransitionArray* t = TransitionArray::cast(raw_transitions); |
- if (t->length() <= kFirstIndex) return 0; |
- return (t->length() - kFirstIndex) / kTransitionSize; |
-} |
- |
- |
-// Private static helper functions. |
Handle<TransitionArray> TransitionArray::Allocate(Isolate* isolate, |
int number_of_transitions, |
@@ -343,6 +23,15 @@ |
} |
+Handle<TransitionArray> TransitionArray::AllocateSimple(Isolate* isolate, |
+ Handle<Map> target) { |
+ Handle<FixedArray> array = |
+ isolate->factory()->NewFixedArray(kSimpleTransitionSize); |
+ array->set(kSimpleTransitionTarget, *target); |
+ return Handle<TransitionArray>::cast(array); |
+} |
+ |
+ |
void TransitionArray::NoIncrementalWriteBarrierCopyFrom(TransitionArray* origin, |
int origin_transition, |
int target_transition) { |
@@ -352,131 +41,153 @@ |
} |
-static void ZapTransitionArray(TransitionArray* transitions) { |
- MemsetPointer(transitions->data_start(), |
- transitions->GetHeap()->the_hole_value(), |
- transitions->length()); |
-} |
- |
- |
-void TransitionArray::ReplaceTransitions(Handle<Map> map, |
- Object* new_transitions) { |
- Object* raw_transitions = map->raw_transitions(); |
- if (IsFullTransitionArray(raw_transitions)) { |
- TransitionArray* old_transitions = TransitionArray::cast(raw_transitions); |
-#ifdef DEBUG |
- CheckNewTransitionsAreConsistent(map, old_transitions, new_transitions); |
- DCHECK(old_transitions != new_transitions); |
-#endif |
- // Transition arrays are not shared. When one is replaced, it should not |
- // keep referenced objects alive, so we zap it. |
- // When there is another reference to the array somewhere (e.g. a handle), |
- // not zapping turns from a waste of memory into a source of crashes. |
- ZapTransitionArray(old_transitions); |
- } |
- map->set_raw_transitions(new_transitions); |
-} |
- |
- |
-static void ZapPrototypeTransitions(Object* raw_transitions) { |
- DCHECK(TransitionArray::IsFullTransitionArray(raw_transitions)); |
- TransitionArray* transitions = TransitionArray::cast(raw_transitions); |
- if (!transitions->HasPrototypeTransitions()) return; |
- FixedArray* proto_transitions = transitions->GetPrototypeTransitions(); |
- MemsetPointer(proto_transitions->data_start(), |
- proto_transitions->GetHeap()->the_hole_value(), |
- proto_transitions->length()); |
-} |
- |
- |
-void TransitionArray::SetPrototypeTransitions( |
- Handle<Map> map, Handle<FixedArray> proto_transitions) { |
- EnsureHasFullTransitionArray(map); |
- if (Heap::ShouldZapGarbage()) { |
- Object* raw_transitions = map->raw_transitions(); |
- DCHECK(raw_transitions != *proto_transitions); |
- ZapPrototypeTransitions(raw_transitions); |
- } |
- TransitionArray* transitions = TransitionArray::cast(map->raw_transitions()); |
- transitions->SetPrototypeTransitions(*proto_transitions); |
-} |
- |
- |
-void TransitionArray::EnsureHasFullTransitionArray(Handle<Map> map) { |
- Object* raw_transitions = map->raw_transitions(); |
- if (IsFullTransitionArray(raw_transitions)) return; |
- int nof = IsSimpleTransition(raw_transitions) ? 1 : 0; |
- Handle<TransitionArray> result = Allocate(map->GetIsolate(), nof); |
+Handle<TransitionArray> TransitionArray::NewWith(Handle<Map> map, |
+ Handle<Name> name, |
+ Handle<Map> target, |
+ SimpleTransitionFlag flag) { |
+ Handle<TransitionArray> result; |
+ Isolate* isolate = name->GetIsolate(); |
+ |
+ if (flag == SIMPLE_PROPERTY_TRANSITION) { |
+ result = AllocateSimple(isolate, target); |
+ } else { |
+ result = Allocate(isolate, 1); |
+ result->NoIncrementalWriteBarrierSet(0, *name, *target); |
+ } |
+ result->set_back_pointer_storage(map->GetBackPointer()); |
+ return result; |
+} |
+ |
+ |
+Handle<TransitionArray> TransitionArray::ExtendToFullTransitionArray( |
+ Handle<Map> containing_map) { |
+ DCHECK(!containing_map->transitions()->IsFullTransitionArray()); |
+ int nof = containing_map->transitions()->number_of_transitions(); |
+ |
+ // A transition array may shrink during GC. |
+ Handle<TransitionArray> result = Allocate(containing_map->GetIsolate(), nof); |
DisallowHeapAllocation no_gc; |
- // Reload pointer after the allocation that just happened. |
- raw_transitions = map->raw_transitions(); |
- int new_nof = IsSimpleTransition(raw_transitions) ? 1 : 0; |
+ int new_nof = containing_map->transitions()->number_of_transitions(); |
if (new_nof != nof) { |
DCHECK(new_nof == 0); |
result->Shrink(ToKeyIndex(0)); |
result->SetNumberOfTransitions(0); |
} else if (nof == 1) { |
- Map* target = GetSimpleTransition(raw_transitions); |
- Name* key = GetSimpleTransitionKey(target); |
- result->NoIncrementalWriteBarrierSet(0, key, target); |
- } |
- ReplaceTransitions(map, *result); |
-} |
- |
- |
-void TransitionArray::TraverseTransitionTreeInternal(Map* map, |
- TraverseCallback callback, |
- void* data) { |
- Object* raw_transitions = map->raw_transitions(); |
- if (IsFullTransitionArray(raw_transitions)) { |
- TransitionArray* transitions = TransitionArray::cast(raw_transitions); |
- if (transitions->HasPrototypeTransitions()) { |
- FixedArray* proto_trans = transitions->GetPrototypeTransitions(); |
- for (int i = 0; i < NumberOfPrototypeTransitions(proto_trans); ++i) { |
- int index = TransitionArray::kProtoTransitionHeaderSize + i; |
- TraverseTransitionTreeInternal(Map::cast(proto_trans->get(index)), |
- callback, data); |
- } |
- } |
- for (int i = 0; i < transitions->number_of_transitions(); ++i) { |
- TraverseTransitionTreeInternal(transitions->GetTarget(i), callback, data); |
- } |
- } else if (IsSimpleTransition(raw_transitions)) { |
- TraverseTransitionTreeInternal(GetSimpleTransition(raw_transitions), |
- callback, data); |
- } |
- callback(map, data); |
-} |
- |
- |
-#ifdef DEBUG |
-void TransitionArray::CheckNewTransitionsAreConsistent( |
- Handle<Map> map, TransitionArray* old_transitions, Object* transitions) { |
- // This function only handles full transition arrays. |
- DCHECK(IsFullTransitionArray(transitions)); |
- TransitionArray* new_transitions = TransitionArray::cast(transitions); |
- for (int i = 0; i < old_transitions->number_of_transitions(); i++) { |
- Map* target = old_transitions->GetTarget(i); |
- if (target->instance_descriptors() == map->instance_descriptors()) { |
- Name* key = old_transitions->GetKey(i); |
- int new_target_index; |
- if (TransitionArray::IsSpecialTransition(key)) { |
- new_target_index = new_transitions->SearchSpecial(Symbol::cast(key)); |
- } else { |
- PropertyDetails details = |
- TransitionArray::GetTargetDetails(key, target); |
- new_target_index = |
- new_transitions->Search(details.kind(), key, details.attributes()); |
- } |
- DCHECK_NE(TransitionArray::kNotFound, new_target_index); |
- DCHECK_EQ(target, new_transitions->GetTarget(new_target_index)); |
- } |
- } |
-} |
-#endif |
- |
- |
-// Private non-static helper functions (operating on full transition arrays). |
+ result->NoIncrementalWriteBarrierCopyFrom( |
+ containing_map->transitions(), kSimpleTransitionIndex, 0); |
+ } |
+ |
+ result->set_back_pointer_storage( |
+ containing_map->transitions()->back_pointer_storage()); |
+ return result; |
+} |
+ |
+ |
+Handle<TransitionArray> TransitionArray::Insert(Handle<Map> map, |
+ Handle<Name> name, |
+ Handle<Map> target, |
+ SimpleTransitionFlag flag) { |
+ if (!map->HasTransitionArray()) { |
+ return TransitionArray::NewWith(map, name, target, flag); |
+ } |
+ |
+ int number_of_transitions = map->transitions()->number_of_transitions(); |
+ int new_nof = number_of_transitions; |
+ |
+ bool is_special_transition = flag == SPECIAL_TRANSITION; |
+ DCHECK_EQ(is_special_transition, IsSpecialTransition(*name)); |
+ PropertyDetails details = is_special_transition |
+ ? PropertyDetails(NONE, DATA, 0) |
+ : GetTargetDetails(*name, *target); |
+ |
+ int insertion_index = kNotFound; |
+ int index = |
+ is_special_transition |
+ ? map->transitions()->SearchSpecial(Symbol::cast(*name), |
+ &insertion_index) |
+ : map->transitions()->Search(details.kind(), *name, |
+ details.attributes(), &insertion_index); |
+ if (index == kNotFound) { |
+ ++new_nof; |
+ } else { |
+ insertion_index = index; |
+ } |
+ DCHECK(insertion_index >= 0 && insertion_index <= number_of_transitions); |
+ |
+ CHECK(new_nof <= kMaxNumberOfTransitions); |
+ |
+ if (new_nof <= map->transitions()->number_of_transitions_storage()) { |
+ DisallowHeapAllocation no_gc; |
+ TransitionArray* array = map->transitions(); |
+ |
+ if (index != kNotFound) { |
+ array->SetTarget(index, *target); |
+ return handle(array); |
+ } |
+ |
+ array->SetNumberOfTransitions(new_nof); |
+ for (index = number_of_transitions; index > insertion_index; --index) { |
+ Name* key = array->GetKey(index - 1); |
+ array->SetKey(index, key); |
+ array->SetTarget(index, array->GetTarget(index - 1)); |
+ } |
+ array->SetKey(index, *name); |
+ array->SetTarget(index, *target); |
+ SLOW_DCHECK(array->IsSortedNoDuplicates()); |
+ return handle(array); |
+ } |
+ |
+ Handle<TransitionArray> result = Allocate( |
+ map->GetIsolate(), new_nof, |
+ Map::SlackForArraySize(number_of_transitions, kMaxNumberOfTransitions)); |
+ |
+ // The map's transition array may grown smaller during the allocation above as |
+ // it was weakly traversed, though it is guaranteed not to disappear. Trim the |
+ // result copy if needed, and recompute variables. |
+ DCHECK(map->HasTransitionArray()); |
+ DisallowHeapAllocation no_gc; |
+ TransitionArray* array = map->transitions(); |
+ if (array->number_of_transitions() != number_of_transitions) { |
+ DCHECK(array->number_of_transitions() < number_of_transitions); |
+ |
+ number_of_transitions = array->number_of_transitions(); |
+ new_nof = number_of_transitions; |
+ |
+ insertion_index = kNotFound; |
+ index = is_special_transition ? map->transitions()->SearchSpecial( |
+ Symbol::cast(*name), &insertion_index) |
+ : map->transitions()->Search( |
+ details.kind(), *name, |
+ details.attributes(), &insertion_index); |
+ if (index == kNotFound) { |
+ ++new_nof; |
+ } else { |
+ insertion_index = index; |
+ } |
+ DCHECK(insertion_index >= 0 && insertion_index <= number_of_transitions); |
+ |
+ result->Shrink(ToKeyIndex(new_nof)); |
+ result->SetNumberOfTransitions(new_nof); |
+ } |
+ |
+ if (array->HasPrototypeTransitions()) { |
+ result->SetPrototypeTransitions(array->GetPrototypeTransitions()); |
+ } |
+ |
+ DCHECK_NE(kNotFound, insertion_index); |
+ for (int i = 0; i < insertion_index; ++i) { |
+ result->NoIncrementalWriteBarrierCopyFrom(array, i, i); |
+ } |
+ result->NoIncrementalWriteBarrierSet(insertion_index, *name, *target); |
+ for (int i = insertion_index; i < number_of_transitions; ++i) { |
+ result->NoIncrementalWriteBarrierCopyFrom(array, i, i + 1); |
+ } |
+ |
+ result->set_back_pointer_storage(array->back_pointer_storage()); |
+ SLOW_DCHECK(result->IsSortedNoDuplicates()); |
+ return result; |
+} |
+ |
int TransitionArray::SearchDetails(int transition, PropertyKind kind, |
PropertyAttributes attributes, |