Commit 54e74230 authored by vitalyr@chromium.org's avatar vitalyr@chromium.org

Fix issue 1152: temporary JS array invariant violation in ArrayConcat.

Review URL: http://codereview.chromium.org/6524010

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6793 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 0648103e
...@@ -8356,7 +8356,7 @@ static MaybeObject* Runtime_ArrayConcat(Arguments args) { ...@@ -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); Handle<JSArray> result = Factory::NewJSArray(0);
uint32_t estimate_nof_elements = IterateArguments(arguments, NULL); uint32_t estimate_nof_elements = IterateArguments(arguments, NULL);
...@@ -8365,23 +8365,20 @@ static MaybeObject* Runtime_ArrayConcat(Arguments args) { ...@@ -8365,23 +8365,20 @@ static MaybeObject* Runtime_ArrayConcat(Arguments args) {
// dictionary. // dictionary.
bool fast_case = (estimate_nof_elements * 2) >= result_length; bool fast_case = (estimate_nof_elements * 2) >= result_length;
Handle<Map> map;
Handle<FixedArray> storage; Handle<FixedArray> storage;
if (fast_case) { if (fast_case) {
// The backing storage array must have non-existing elements to // The backing storage array must have non-existing elements to
// preserve holes across concat operations. // preserve holes across concat operations.
map = Factory::GetFastElementsMap(Handle<Map>(result->map()));
storage = Factory::NewFixedArrayWithHoles(result_length); storage = Factory::NewFixedArrayWithHoles(result_length);
Handle<Map> fast_map =
Factory::GetFastElementsMap(Handle<Map>(result->map()));
result->set_map(*fast_map);
} else { } else {
map = Factory::GetSlowElementsMap(Handle<Map>(result->map()));
// TODO(126): move 25% pre-allocation logic into Dictionary::Allocate // TODO(126): move 25% pre-allocation logic into Dictionary::Allocate
uint32_t at_least_space_for = estimate_nof_elements + uint32_t at_least_space_for = estimate_nof_elements +
(estimate_nof_elements >> 2); (estimate_nof_elements >> 2);
storage = Handle<FixedArray>::cast( storage = Handle<FixedArray>::cast(
Factory::NewNumberDictionary(at_least_space_for)); Factory::NewNumberDictionary(at_least_space_for));
Handle<Map> slow_map =
Factory::GetSlowElementsMap(Handle<Map>(result->map()));
result->set_map(*slow_map);
} }
Handle<Object> len = Factory::NewNumber(static_cast<double>(result_length)); Handle<Object> len = Factory::NewNumber(static_cast<double>(result_length));
...@@ -8390,8 +8387,12 @@ static MaybeObject* Runtime_ArrayConcat(Arguments args) { ...@@ -8390,8 +8387,12 @@ static MaybeObject* Runtime_ArrayConcat(Arguments args) {
IterateArguments(arguments, &visitor); 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); result->set_length(*len);
// Please note the storage might have changed in the visitor.
result->set_elements(*visitor.storage()); result->set_elements(*visitor.storage());
return *result; return *result;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment