diff --git a/src/objects-inl.h b/src/objects-inl.h index f4e0767198..8b22755c82 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h @@ -3582,6 +3582,14 @@ Map* Map::elements_transition_map() { } +bool Map::CanHaveMoreTransitions() { + if (!HasTransitionArray()) return true; + return FixedArray::SizeFor(transitions()->length() + + TransitionArray::kTransitionSize) + <= Page::kMaxNonCodeHeapObjectSize; +} + + MaybeObject* Map::AddTransition(String* key, Map* target) { if (HasTransitionArray()) return transitions()->CopyInsert(key, target); return TransitionArray::NewWith(key, target); diff --git a/src/objects.cc b/src/objects.cc index 4905c04518..fe94a42c4a 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -2120,8 +2120,6 @@ template static void RightTrimFixedArray(Heap* heap, FixedArray* elms, int to_trim) { ASSERT(elms->map() != HEAP->fixed_cow_array_map()); // For now this trick is only applied to fixed arrays in new and paged space. - // In large object space the object's start must coincide with chunk - // and thus the trick is just not applicable. ASSERT(!HEAP->lo_space()->Contains(elms)); const int len = elms->length(); @@ -2217,7 +2215,7 @@ void Map::CopyAppendCallbackDescriptors(Handle map, } // If duplicates were detected, trim the descriptor array to the right size. - int new_array_size = DescriptorArray::SizeFor(new_number_of_descriptors); + int new_array_size = DescriptorArray::LengthFor(new_number_of_descriptors); if (new_array_size < result->length()) { RightTrimFixedArray( isolate->heap(), *result, result->length() - new_array_size); @@ -4883,7 +4881,7 @@ MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors, result->SetLastAdded(last_added); } - if (flag == INSERT_TRANSITION) { + if (flag == INSERT_TRANSITION && CanHaveMoreTransitions()) { TransitionArray* transitions; MaybeObject* maybe_transitions = AddTransition(name, result); if (!maybe_transitions->To(&transitions)) return maybe_transitions; @@ -5843,7 +5841,7 @@ MaybeObject* DescriptorArray::Allocate(int number_of_descriptors, } // Allocate the array of keys. MaybeObject* maybe_array = - heap->AllocateFixedArray(SizeFor(number_of_descriptors)); + heap->AllocateFixedArray(LengthFor(number_of_descriptors)); if (!maybe_array->To(&result)) return maybe_array; result->set(kEnumCacheIndex, Smi::FromInt(0)); diff --git a/src/objects.h b/src/objects.h index fa33b8192f..7ed2973403 100644 --- a/src/objects.h +++ b/src/objects.h @@ -2635,7 +2635,9 @@ class DescriptorArray: public FixedArray { // fit in a page). static const int kMaxNumberOfDescriptors = 1024 + 512; - static int SizeFor(int number_of_descriptors) { + // Returns the fixed array length required to hold number_of_descriptors + // descriptors. + static int LengthFor(int number_of_descriptors) { return ToKeyIndex(number_of_descriptors); } @@ -4896,6 +4898,11 @@ class Map: public HeapObject { String* name, LookupResult* result); + // The size of transition arrays are limited so they do not end up in large + // object space. Otherwise ClearNonLiveTransitions would leak memory while + // applying in-place right trimming. + inline bool CanHaveMoreTransitions(); + void SetLastAdded(int index) { set_bit_field3(LastAddedBits::update(bit_field3(), index)); }