Inline SetLengthWithoutNormalize into its callers

BUG=

Review URL: https://codereview.chromium.org/1194943002

Cr-Commit-Position: refs/heads/master@{#29165}
This commit is contained in:
verwaest 2015-06-19 11:59:11 -07:00 committed by Commit bot
parent 0f502f679e
commit 7028e4b531
3 changed files with 53 additions and 89 deletions

View File

@ -862,55 +862,6 @@ class FastElementsAccessor
typedef typename KindTraits::BackingStore BackingStore; typedef typename KindTraits::BackingStore BackingStore;
// Adjusts the length of the fast backing store.
static uint32_t SetLengthWithoutNormalize(
Handle<FixedArrayBase> backing_store, Handle<JSArray> array,
uint32_t length) {
Isolate* isolate = array->GetIsolate();
uint32_t old_capacity = backing_store->length();
Handle<Object> old_length(array->length(), isolate);
bool same_or_smaller_size = old_length->IsSmi() &&
static_cast<uint32_t>(Handle<Smi>::cast(old_length)->value()) >= length;
ElementsKind kind = array->GetElementsKind();
if (!same_or_smaller_size && IsFastElementsKind(kind) &&
!IsFastHoleyElementsKind(kind)) {
kind = GetHoleyElementsKind(kind);
JSObject::TransitionElementsKind(array, kind);
}
// Check whether the backing store should be shrunk.
if (length <= old_capacity) {
if (array->HasFastSmiOrObjectElements()) {
backing_store = JSObject::EnsureWritableFastElements(array);
}
if (2 * length <= old_capacity) {
// If more than half the elements won't be used, trim the array.
if (length == 0) {
array->initialize_elements();
} else {
isolate->heap()->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>(
*backing_store, old_capacity - length);
}
} else {
// Otherwise, fill the unused tail with holes.
int old_length = FastD2IChecked(array->length()->Number());
for (int i = length; i < old_length; i++) {
Handle<BackingStore>::cast(backing_store)->set_the_hole(i);
}
}
return length;
}
// Check whether the backing store should be expanded.
uint32_t min = JSObject::NewElementsCapacity(old_capacity);
uint32_t new_capacity = length > min ? length : min;
FastElementsAccessorSubclass::SetFastElementsCapacityAndLength(
array, new_capacity, length);
JSObject::ValidateElements(array);
return length;
}
static void DeleteCommon(Handle<JSObject> obj, uint32_t key, static void DeleteCommon(Handle<JSObject> obj, uint32_t key,
LanguageMode language_mode) { LanguageMode language_mode) {
DCHECK(obj->HasFastSmiOrObjectElements() || DCHECK(obj->HasFastSmiOrObjectElements() ||
@ -1321,33 +1272,13 @@ class DictionaryElementsAccessor
static void SetLengthImpl(Handle<JSArray> array, uint32_t length, static void SetLengthImpl(Handle<JSArray> array, uint32_t length,
Handle<FixedArrayBase> backing_store) { Handle<FixedArrayBase> backing_store) {
uint32_t new_length =
SetLengthWithoutNormalize(backing_store, array, length);
// SetLengthWithoutNormalize does not allow length to drop below the last
// non-deletable element.
DCHECK_GE(new_length, length);
if (new_length <= Smi::kMaxValue) {
array->set_length(Smi::FromInt(new_length));
} else {
Isolate* isolate = array->GetIsolate();
Handle<Object> length_obj =
isolate->factory()->NewNumberFromUint(new_length);
array->set_length(*length_obj);
}
}
// Adjusts the length of the dictionary backing store and returns the new
// length according to ES5 section 15.4.5.2 behavior.
static uint32_t SetLengthWithoutNormalize(Handle<FixedArrayBase> store,
Handle<JSArray> array,
uint32_t length) {
Handle<SeededNumberDictionary> dict = Handle<SeededNumberDictionary> dict =
Handle<SeededNumberDictionary>::cast(store); Handle<SeededNumberDictionary>::cast(backing_store);
Isolate* isolate = array->GetIsolate(); Isolate* isolate = array->GetIsolate();
int capacity = dict->Capacity(); int capacity = dict->Capacity();
uint32_t old_length = 0; uint32_t old_length = 0;
CHECK(array->length()->ToArrayLength(&old_length)); CHECK(array->length()->ToArrayLength(&old_length));
if (length < old_length) { if (dict->requires_slow_elements() && length < old_length) {
// Find last non-deletable element in range of elements to be // Find last non-deletable element in range of elements to be
// deleted and adjust range accordingly. // deleted and adjust range accordingly.
for (int i = 0; i < capacity; i++) { for (int i = 0; i < capacity; i++) {
@ -1385,7 +1316,14 @@ class DictionaryElementsAccessor
// Update the number of elements. // Update the number of elements.
dict->ElementsRemoved(removed_entries); dict->ElementsRemoved(removed_entries);
} }
return length;
if (length <= Smi::kMaxValue) {
array->set_length(Smi::FromInt(length));
} else {
Isolate* isolate = array->GetIsolate();
Handle<Object> length_obj = isolate->factory()->NewNumberFromUint(length);
array->set_length(*length_obj);
}
} }
static void DeleteCommon(Handle<JSObject> obj, uint32_t key, static void DeleteCommon(Handle<JSObject> obj, uint32_t key,
@ -1707,23 +1645,46 @@ template <typename ElementsAccessorSubclass, typename ElementsKindTraits>
void ElementsAccessorBase<ElementsAccessorSubclass, ElementsKindTraits>:: void ElementsAccessorBase<ElementsAccessorSubclass, ElementsKindTraits>::
SetLengthImpl(Handle<JSArray> array, uint32_t length, SetLengthImpl(Handle<JSArray> array, uint32_t length,
Handle<FixedArrayBase> backing_store) { Handle<FixedArrayBase> backing_store) {
// Normalize if the length does not fit in a smi. Fast mode arrays only DCHECK(!JSArray::SetLengthWouldNormalize(array->GetHeap(), length));
// support smi length. DCHECK(IsFastElementsKind(array->GetElementsKind()));
if (JSArray::SetLengthWouldNormalize(array->GetHeap(), length)) { uint32_t old_length = 0;
Handle<SeededNumberDictionary> dictionary = CHECK(array->length()->ToArrayIndex(&old_length));
JSObject::NormalizeElements(array);
DCHECK(!dictionary.is_null()); if (old_length < length) {
DictionaryElementsAccessor::SetLengthImpl(array, length, dictionary); ElementsKind kind = array->GetElementsKind();
} else { if (!IsFastHoleyElementsKind(kind)) {
#ifdef DEBUG kind = GetHoleyElementsKind(kind);
uint32_t max = Smi::kMaxValue; JSObject::TransitionElementsKind(array, kind);
DCHECK_LE(length, max); }
#endif
uint32_t new_length = ElementsAccessorSubclass::SetLengthWithoutNormalize(
backing_store, array, length);
DCHECK_EQ(length, new_length);
array->set_length(Smi::FromInt(new_length));
} }
// Check whether the backing store should be shrunk.
uint32_t capacity = backing_store->length();
if (length == 0) {
array->initialize_elements();
} else if (length <= capacity) {
if (array->HasFastSmiOrObjectElements()) {
backing_store = JSObject::EnsureWritableFastElements(array);
}
if (2 * length <= capacity) {
// If more than half the elements won't be used, trim the array.
array->GetHeap()->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>(
*backing_store, capacity - length);
} else {
// Otherwise, fill the unused tail with holes.
for (uint32_t i = length; i < old_length; i++) {
BackingStore::cast(*backing_store)->set_the_hole(i);
}
}
} else {
// Check whether the backing store should be expanded.
capacity = Max(length, JSObject::NewElementsCapacity(capacity));
ElementsAccessorSubclass::SetFastElementsCapacityAndLength(array, capacity,
length);
}
array->set_length(Smi::FromInt(length));
JSObject::ValidateElements(array);
} }

View File

@ -11978,6 +11978,9 @@ static bool GetOldValue(Isolate* isolate,
void JSArray::SetLength(Handle<JSArray> array, uint32_t new_length) { void JSArray::SetLength(Handle<JSArray> array, uint32_t new_length) {
// We should never end in here with a pixel or external array. // We should never end in here with a pixel or external array.
DCHECK(array->AllowsSetLength()); DCHECK(array->AllowsSetLength());
if (JSArray::SetLengthWouldNormalize(array->GetHeap(), new_length)) {
JSObject::NormalizeElements(array);
}
array->GetElementsAccessor()->SetLength(array, new_length); array->GetElementsAccessor()->SetLength(array, new_length);
} }

View File

@ -2037,7 +2037,7 @@ class JSObject: public JSReceiver {
bool ShouldConvertToFastDoubleElements(bool* has_smi_only_elements); bool ShouldConvertToFastDoubleElements(bool* has_smi_only_elements);
// Computes the new capacity when expanding the elements of a JSObject. // Computes the new capacity when expanding the elements of a JSObject.
static int NewElementsCapacity(int old_capacity) { static uint32_t NewElementsCapacity(uint32_t old_capacity) {
// (old_capacity + 50%) + 16 // (old_capacity + 50%) + 16
return old_capacity + (old_capacity >> 1) + 16; return old_capacity + (old_capacity >> 1) + 16;
} }