| Index: src/objects.cc
|
| diff --git a/src/objects.cc b/src/objects.cc
|
| index 46d5264c410583c8ba65953c9a2a7276b9b735b8..f27a1a1a33a58acf5643b674b2d94cc416f437ba 100644
|
| --- a/src/objects.cc
|
| +++ b/src/objects.cc
|
| @@ -8724,10 +8724,10 @@ MaybeObject* JSObject::SetFastElement(uint32_t index,
|
| if (!maybe->ToObject(&writable)) return maybe;
|
| backing_store = FixedArray::cast(writable);
|
| }
|
| - uint32_t length = static_cast<uint32_t>(backing_store->length());
|
| + uint32_t capacity = static_cast<uint32_t>(backing_store->length());
|
|
|
| if (check_prototype &&
|
| - (index >= length || backing_store->get(index)->IsTheHole())) {
|
| + (index >= capacity || backing_store->get(index)->IsTheHole())) {
|
| bool found;
|
| MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index,
|
| value,
|
| @@ -8736,63 +8736,71 @@ MaybeObject* JSObject::SetFastElement(uint32_t index,
|
| if (found) return result;
|
| }
|
|
|
| - // Check whether there is extra space in fixed array.
|
| - if (index < length) {
|
| - if (HasFastSmiOnlyElements()) {
|
| - if (!value->IsSmi()) {
|
| - // If the value is a number, transition from smi-only to
|
| - // FastDoubleElements.
|
| - if (value->IsNumber()) {
|
| - MaybeObject* maybe =
|
| - SetFastDoubleElementsCapacityAndLength(length, length);
|
| - if (maybe->IsFailure()) return maybe;
|
| - FixedDoubleArray::cast(elements())->set(index, value->Number());
|
| - return value;
|
| - }
|
| - // Value is not a number, transition to generic fast elements.
|
| - MaybeObject* maybe_new_map = GetElementsTransitionMap(FAST_ELEMENTS);
|
| - Map* new_map;
|
| - if (!maybe_new_map->To<Map>(&new_map)) return maybe_new_map;
|
| - set_map(new_map);
|
| - }
|
| + uint32_t new_capacity = capacity;
|
| + // Check if the length property of this object needs to be updated.
|
| + uint32_t array_length = 0;
|
| + bool must_update_array_length = false;
|
| + if (IsJSArray()) {
|
| + CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length));
|
| + if (index >= array_length) {
|
| + must_update_array_length = true;
|
| + array_length = index + 1;
|
| }
|
| - backing_store->set(index, value);
|
| - if (IsJSArray()) {
|
| - // Update the length of the array if needed.
|
| - uint32_t array_length = 0;
|
| - CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length));
|
| - if (index >= array_length) {
|
| - JSArray::cast(this)->set_length(Smi::FromInt(index + 1));
|
| + }
|
| + // Check if the capacity of the backing store needs to be increased, or if
|
| + // a transition to slow elements is necessary.
|
| + if (index >= capacity) {
|
| + bool convert_to_slow = true;
|
| + if ((index - capacity) < kMaxGap) {
|
| + new_capacity = NewElementsCapacity(index + 1);
|
| + ASSERT(new_capacity > index);
|
| + if (!ShouldConvertToSlowElements(new_capacity)) {
|
| + convert_to_slow = false;
|
| }
|
| }
|
| + if (convert_to_slow) {
|
| + MaybeObject* result = NormalizeElements();
|
| + if (result->IsFailure()) return result;
|
| + return SetDictionaryElement(index, value, strict_mode, check_prototype);
|
| + }
|
| + }
|
| + // Convert to fast double elements if appropriate.
|
| + if (HasFastSmiOnlyElements() && !value->IsSmi() && value->IsNumber()) {
|
| + MaybeObject* maybe =
|
| + SetFastDoubleElementsCapacityAndLength(new_capacity, array_length);
|
| + if (maybe->IsFailure()) return maybe;
|
| + FixedDoubleArray::cast(elements())->set(index, value->Number());
|
| return value;
|
| }
|
| -
|
| - // Allow gap in fast case.
|
| - if ((index - length) < kMaxGap) {
|
| - // Try allocating extra space.
|
| - int new_capacity = NewElementsCapacity(index + 1);
|
| - if (!ShouldConvertToSlowElements(new_capacity)) {
|
| - ASSERT(static_cast<uint32_t>(new_capacity) > index);
|
| - Object* new_elements;
|
| - SetFastElementsCapacityMode set_capacity_mode =
|
| - value->IsSmi() && HasFastSmiOnlyElements()
|
| - ? kAllowSmiOnlyElements
|
| - : kDontAllowSmiOnlyElements;
|
| - MaybeObject* maybe =
|
| - SetFastElementsCapacityAndLength(new_capacity,
|
| - index + 1,
|
| - set_capacity_mode);
|
| - if (!maybe->ToObject(&new_elements)) return maybe;
|
| - FixedArray::cast(new_elements)->set(index, value);
|
| - return value;
|
| - }
|
| + // Change elements kind from SMI_ONLY to generic FAST if necessary.
|
| + if (HasFastSmiOnlyElements() && !value->IsSmi()) {
|
| + MaybeObject* maybe_new_map = GetElementsTransitionMap(FAST_ELEMENTS);
|
| + Map* new_map;
|
| + if (!maybe_new_map->To<Map>(&new_map)) return maybe_new_map;
|
| + set_map(new_map);
|
| }
|
| -
|
| - // Otherwise default to slow case.
|
| - MaybeObject* result = NormalizeElements();
|
| - if (result->IsFailure()) return result;
|
| - return SetDictionaryElement(index, value, strict_mode, check_prototype);
|
| + // Increase backing store capacity if that's been decided previously.
|
| + if (new_capacity != capacity) {
|
| + Object* new_elements;
|
| + SetFastElementsCapacityMode set_capacity_mode =
|
| + value->IsSmi() && HasFastSmiOnlyElements()
|
| + ? kAllowSmiOnlyElements
|
| + : kDontAllowSmiOnlyElements;
|
| + MaybeObject* maybe =
|
| + SetFastElementsCapacityAndLength(new_capacity,
|
| + array_length,
|
| + set_capacity_mode);
|
| + if (!maybe->ToObject(&new_elements)) return maybe;
|
| + FixedArray::cast(new_elements)->set(index, value);
|
| + return value;
|
| + }
|
| + // Finally, set the new element and length.
|
| + ASSERT(elements()->IsFixedArray());
|
| + backing_store->set(index, value);
|
| + if (must_update_array_length) {
|
| + JSArray::cast(this)->set_length(Smi::FromInt(array_length));
|
| + }
|
| + return value;
|
| }
|
|
|
|
|
|
|