Index: src/objects.cc |
diff --git a/src/objects.cc b/src/objects.cc |
index 5c8a8987054a7d0c2096599337e5ff8c26fddf7d..4d879aca0b210b45fb0d66087a26a8f5a1903555 100644 |
--- a/src/objects.cc |
+++ b/src/objects.cc |
@@ -8133,17 +8133,17 @@ static void CopyFastElementsToFast(FixedArray* source, |
FixedArray* destination, |
WriteBarrierMode mode) { |
int count = source->length(); |
+ int copy_size = Min(count, destination->length()); |
if (mode == SKIP_WRITE_BARRIER || |
!Page::FromAddress(destination->address())->IsFlagSet( |
MemoryChunk::POINTERS_FROM_HERE_ARE_INTERESTING)) { |
- ASSERT(count <= destination->length()); |
Address to = destination->address() + FixedArray::kHeaderSize; |
Address from = source->address() + FixedArray::kHeaderSize; |
memcpy(reinterpret_cast<void*>(to), |
reinterpret_cast<void*>(from), |
- kPointerSize * count); |
+ kPointerSize * copy_size); |
} else { |
- for (int i = 0; i < count; ++i) { |
+ for (int i = 0; i < copy_size; ++i) { |
destination->set(i, source->get(i), mode); |
} |
} |
@@ -8153,11 +8153,14 @@ static void CopyFastElementsToFast(FixedArray* source, |
static void CopySlowElementsToFast(NumberDictionary* source, |
FixedArray* destination, |
WriteBarrierMode mode) { |
+ int destination_length = destination->length(); |
for (int i = 0; i < source->Capacity(); ++i) { |
Object* key = source->KeyAt(i); |
if (key->IsNumber()) { |
uint32_t entry = static_cast<uint32_t>(key->Number()); |
- destination->set(entry, source->ValueAt(i), mode); |
+ if (entry < static_cast<uint32_t>(destination_length)) { |
+ destination->set(entry, source->ValueAt(i), mode); |
+ } |
} |
} |
} |
@@ -8368,14 +8371,8 @@ MaybeObject* JSArray::Initialize(int capacity) { |
void JSArray::Expand(int required_size) { |
- Handle<JSArray> self(this); |
- Handle<FixedArray> old_backing(FixedArray::cast(elements())); |
- int old_size = old_backing->length(); |
- int new_size = required_size > old_size ? required_size : old_size; |
- Handle<FixedArray> new_backing = FACTORY->NewFixedArray(new_size); |
- // Can't use this any more now because we may have had a GC! |
- for (int i = 0; i < old_size; i++) new_backing->set(i, old_backing->get(i)); |
- GetIsolate()->factory()->SetContent(self, new_backing); |
+ GetIsolate()->factory()->SetElementsCapacityAndLength( |
+ Handle<JSArray>(this), required_size, Smi::cast(length())->value()); |
} |
@@ -8529,13 +8526,14 @@ MaybeObject* JSReceiver::SetPrototype(Object* value, |
MaybeObject* JSObject::EnsureCanContainElements(Arguments* args, |
uint32_t first_arg, |
- uint32_t arg_count) { |
+ uint32_t arg_count, |
+ EnsureElementsMode mode) { |
// Elements in |Arguments| are ordered backwards (because they're on the |
// stack), but the method that's called here iterates over them in forward |
// direction. |
return EnsureCanContainElements( |
args->arguments() - first_arg - (arg_count - 1), |
- arg_count); |
+ arg_count, mode); |
} |
@@ -9487,31 +9485,45 @@ MUST_USE_RESULT MaybeObject* JSObject::TransitionElementsKind( |
FixedArrayBase* elms = FixedArrayBase::cast(elements()); |
uint32_t capacity = static_cast<uint32_t>(elms->length()); |
uint32_t length = capacity; |
+ |
if (IsJSArray()) { |
- CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length)); |
+ Object* raw_length = JSArray::cast(this)->length(); |
+ if (raw_length->IsUndefined()) { |
+ // If length is undefined, then JSArray is being initialized and has no |
+ // elements, assume a length of zero. |
+ length = 0; |
+ } else { |
+ CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length)); |
+ } |
} |
- if (from_kind == FAST_SMI_ONLY_ELEMENTS) { |
- if (to_kind == FAST_DOUBLE_ELEMENTS) { |
- MaybeObject* maybe_result = |
- SetFastDoubleElementsCapacityAndLength(capacity, length); |
- if (maybe_result->IsFailure()) return maybe_result; |
- return this; |
- } else if (to_kind == FAST_ELEMENTS) { |
- MaybeObject* maybe_new_map = GetElementsTransitionMap(FAST_ELEMENTS); |
- Map* new_map; |
- if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
- if (FLAG_trace_elements_transitions) { |
- PrintElementsTransition(stdout, from_kind, elms, FAST_ELEMENTS, elms); |
- } |
- set_map(new_map); |
- return this; |
+ |
+ if ((from_kind == FAST_SMI_ONLY_ELEMENTS && to_kind == FAST_ELEMENTS) || |
+ (length == 0)) { |
+ MaybeObject* maybe_new_map = GetElementsTransitionMap(to_kind); |
+ Map* new_map; |
+ if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
+ if (FLAG_trace_elements_transitions) { |
+ PrintElementsTransition(stdout, from_kind, elms, to_kind, elms); |
} |
- } else if (from_kind == FAST_DOUBLE_ELEMENTS && to_kind == FAST_ELEMENTS) { |
+ set_map(new_map); |
+ return this; |
+ } |
+ |
+ if (from_kind == FAST_SMI_ONLY_ELEMENTS && |
+ to_kind == FAST_DOUBLE_ELEMENTS) { |
+ MaybeObject* maybe_result = |
+ SetFastDoubleElementsCapacityAndLength(capacity, length); |
+ if (maybe_result->IsFailure()) return maybe_result; |
+ return this; |
+ } |
+ |
+ if (from_kind == FAST_DOUBLE_ELEMENTS && to_kind == FAST_ELEMENTS) { |
MaybeObject* maybe_result = SetFastElementsCapacityAndLength( |
capacity, length, kDontAllowSmiOnlyElements); |
if (maybe_result->IsFailure()) return maybe_result; |
return this; |
} |
+ |
// This method should never be called for any other case than the ones |
// handled above. |
UNREACHABLE(); |