| Index: src/runtime.cc
|
| diff --git a/src/runtime.cc b/src/runtime.cc
|
| index 81ce7e4bba63041b072ee3c88ee85d09e0025306..75bb1ae1f133ade6824baf3afd4f2a1cd3b40825 100644
|
| --- a/src/runtime.cc
|
| +++ b/src/runtime.cc
|
| @@ -8356,7 +8356,7 @@ static MaybeObject* Runtime_ArrayConcat(Arguments args) {
|
| }
|
| }
|
|
|
| - // Allocate an empty array, will set length and content later.
|
| + // Allocate an empty array, will set map, length, and content later.
|
| Handle<JSArray> result = Factory::NewJSArray(0);
|
|
|
| uint32_t estimate_nof_elements = IterateArguments(arguments, NULL);
|
| @@ -8365,23 +8365,20 @@ static MaybeObject* Runtime_ArrayConcat(Arguments args) {
|
| // dictionary.
|
| bool fast_case = (estimate_nof_elements * 2) >= result_length;
|
|
|
| + Handle<Map> map;
|
| Handle<FixedArray> storage;
|
| if (fast_case) {
|
| // The backing storage array must have non-existing elements to
|
| // preserve holes across concat operations.
|
| + map = Factory::GetFastElementsMap(Handle<Map>(result->map()));
|
| storage = Factory::NewFixedArrayWithHoles(result_length);
|
| - Handle<Map> fast_map =
|
| - Factory::GetFastElementsMap(Handle<Map>(result->map()));
|
| - result->set_map(*fast_map);
|
| } else {
|
| + map = Factory::GetSlowElementsMap(Handle<Map>(result->map()));
|
| // TODO(126): move 25% pre-allocation logic into Dictionary::Allocate
|
| uint32_t at_least_space_for = estimate_nof_elements +
|
| (estimate_nof_elements >> 2);
|
| storage = Handle<FixedArray>::cast(
|
| - Factory::NewNumberDictionary(at_least_space_for));
|
| - Handle<Map> slow_map =
|
| - Factory::GetSlowElementsMap(Handle<Map>(result->map()));
|
| - result->set_map(*slow_map);
|
| + Factory::NewNumberDictionary(at_least_space_for));
|
| }
|
|
|
| Handle<Object> len = Factory::NewNumber(static_cast<double>(result_length));
|
| @@ -8390,8 +8387,12 @@ static MaybeObject* Runtime_ArrayConcat(Arguments args) {
|
|
|
| IterateArguments(arguments, &visitor);
|
|
|
| + // Please note:
|
| + // - the storage might have been changed in the visitor;
|
| + // - the map and the storage must be set together to avoid breaking
|
| + // the invariant that the map describes the array's elements.
|
| + result->set_map(*map);
|
| result->set_length(*len);
|
| - // Please note the storage might have changed in the visitor.
|
| result->set_elements(*visitor.storage());
|
|
|
| return *result;
|
|
|