Fix setting array length to zero for slow elements.
R=verwaest@chromium.org BUG=chromium:146910 TEST=mjsunit/regress/regress-crbug-146910 Review URL: https://codereview.chromium.org/10937026 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12547 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
ab94a69d3d
commit
c012afb6d4
@ -1268,7 +1268,30 @@ class DictionaryElementsAccessor
|
||||
JSArray* array,
|
||||
Object* length_object,
|
||||
uint32_t length) {
|
||||
if (length == 0) {
|
||||
Heap* heap = array->GetHeap();
|
||||
int capacity = dict->Capacity();
|
||||
uint32_t new_length = length;
|
||||
uint32_t old_length = static_cast<uint32_t>(array->length()->Number());
|
||||
if (new_length < old_length) {
|
||||
// Find last non-deletable element in range of elements to be
|
||||
// deleted and adjust range accordingly.
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
Object* key = dict->KeyAt(i);
|
||||
if (key->IsNumber()) {
|
||||
uint32_t number = static_cast<uint32_t>(key->Number());
|
||||
if (new_length <= number && number < old_length) {
|
||||
PropertyDetails details = dict->DetailsAt(i);
|
||||
if (details.IsDontDelete()) new_length = number + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (new_length != length) {
|
||||
MaybeObject* maybe_object = heap->NumberFromUint32(new_length);
|
||||
if (!maybe_object->To(&length_object)) return maybe_object;
|
||||
}
|
||||
}
|
||||
|
||||
if (new_length == 0) {
|
||||
// If the length of a slow array is reset to zero, we clear
|
||||
// the array and flush backing storage. This has the added
|
||||
// benefit that the array returns to fast mode.
|
||||
@ -1276,45 +1299,22 @@ class DictionaryElementsAccessor
|
||||
MaybeObject* maybe_obj = array->ResetElements();
|
||||
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
|
||||
} else {
|
||||
uint32_t new_length = length;
|
||||
uint32_t old_length = static_cast<uint32_t>(array->length()->Number());
|
||||
if (new_length < old_length) {
|
||||
// Find last non-deletable element in range of elements to be
|
||||
// deleted and adjust range accordingly.
|
||||
Heap* heap = array->GetHeap();
|
||||
int capacity = dict->Capacity();
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
Object* key = dict->KeyAt(i);
|
||||
if (key->IsNumber()) {
|
||||
uint32_t number = static_cast<uint32_t>(key->Number());
|
||||
if (new_length <= number && number < old_length) {
|
||||
PropertyDetails details = dict->DetailsAt(i);
|
||||
if (details.IsDontDelete()) new_length = number + 1;
|
||||
}
|
||||
// Remove elements that should be deleted.
|
||||
int removed_entries = 0;
|
||||
Object* the_hole_value = heap->the_hole_value();
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
Object* key = dict->KeyAt(i);
|
||||
if (key->IsNumber()) {
|
||||
uint32_t number = static_cast<uint32_t>(key->Number());
|
||||
if (new_length <= number && number < old_length) {
|
||||
dict->SetEntry(i, the_hole_value, the_hole_value);
|
||||
removed_entries++;
|
||||
}
|
||||
}
|
||||
if (new_length != length) {
|
||||
MaybeObject* maybe_object = heap->NumberFromUint32(new_length);
|
||||
if (!maybe_object->To(&length_object)) return maybe_object;
|
||||
}
|
||||
|
||||
// Remove elements that should be deleted.
|
||||
int removed_entries = 0;
|
||||
Object* the_hole_value = heap->the_hole_value();
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
Object* key = dict->KeyAt(i);
|
||||
if (key->IsNumber()) {
|
||||
uint32_t number = static_cast<uint32_t>(key->Number());
|
||||
if (new_length <= number && number < old_length) {
|
||||
dict->SetEntry(i, the_hole_value, the_hole_value);
|
||||
removed_entries++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update the number of elements.
|
||||
dict->ElementsRemoved(removed_entries);
|
||||
}
|
||||
|
||||
// Update the number of elements.
|
||||
dict->ElementsRemoved(removed_entries);
|
||||
}
|
||||
return length_object;
|
||||
}
|
||||
|
38
test/mjsunit/regress/regress-crbug-146910.js
Normal file
38
test/mjsunit/regress/regress-crbug-146910.js
Normal file
@ -0,0 +1,38 @@
|
||||
// Copyright 2012 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
var x = [];
|
||||
assertSame(0, x.length);
|
||||
assertSame(undefined, x[0]);
|
||||
|
||||
Object.defineProperty(x, '0', { value: 7, configurable: false });
|
||||
assertSame(1, x.length);
|
||||
assertSame(7, x[0]);
|
||||
|
||||
x.length = 0;
|
||||
assertSame(1, x.length);
|
||||
assertSame(7, x[0]);
|
Loading…
Reference in New Issue
Block a user