Commit 837d83eb authored by danno@chromium.org's avatar danno@chromium.org

Implement setting the length property for FixedDoubleArrays.

R=ager@chromium.org
BUG=none
TEST=none

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@8683 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 11c7b474
......@@ -4007,7 +4007,8 @@ bool JSObject::HasIndexedInterceptor() {
bool JSObject::AllowsSetElementsLength() {
bool result = elements()->IsFixedArray();
bool result = elements()->IsFixedArray() ||
elements()->IsFixedDoubleArray();
ASSERT(result == !HasExternalArrayElements());
return result;
}
......
......@@ -3207,7 +3207,7 @@ MaybeObject* JSObject::DeleteElement(uint32_t index, DeleteMode mode) {
case FAST_DOUBLE_ELEMENTS: {
int length = IsJSArray()
? Smi::cast(JSArray::cast(this)->length())->value()
: FixedArray::cast(elements())->length();
: FixedDoubleArray::cast(elements())->length();
if (index < static_cast<uint32_t>(length)) {
FixedDoubleArray::cast(elements())->set_the_hole(index);
}
......@@ -7628,32 +7628,55 @@ MaybeObject* JSObject::SetElementsLength(Object* len) {
const int value = Smi::cast(smi_length)->value();
if (value < 0) return ArrayLengthRangeError(GetHeap());
switch (GetElementsKind()) {
case FAST_ELEMENTS: {
int old_capacity = FixedArray::cast(elements())->length();
case FAST_ELEMENTS:
case FAST_DOUBLE_ELEMENTS: {
int old_capacity = FixedArrayBase::cast(elements())->length();
if (value <= old_capacity) {
if (IsJSArray()) {
Object* obj;
{ MaybeObject* maybe_obj = EnsureWritableFastElements();
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
FixedArray* fast_elements = FixedArray::cast(elements());
if (2 * value <= old_capacity) {
// If more than half the elements won't be used, trim the array.
if (value == 0) {
initialize_elements();
} else {
Address filler_start;
int filler_size;
if (GetElementsKind() == FAST_ELEMENTS) {
Object* obj;
{ MaybeObject* maybe_obj = EnsureWritableFastElements();
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
FixedArray* fast_elements = FixedArray::cast(elements());
fast_elements->set_length(value);
Address filler_start = fast_elements->address() +
filler_start = fast_elements->address() +
FixedArray::OffsetOfElementAt(value);
int filler_size = (old_capacity - value) * kPointerSize;
filler_size = (old_capacity - value) * kPointerSize;
} else {
ASSERT(GetElementsKind() == FAST_DOUBLE_ELEMENTS);
FixedDoubleArray* fast_double_elements =
FixedDoubleArray::cast(elements());
fast_double_elements->set_length(value);
filler_start = fast_double_elements->address() +
FixedDoubleArray::OffsetOfElementAt(value);
filler_size = (old_capacity - value) * kDoubleSize;
}
GetHeap()->CreateFillerObjectAt(filler_start, filler_size);
}
} else {
// Otherwise, fill the unused tail with holes.
int old_length = FastD2I(JSArray::cast(this)->length()->Number());
if (GetElementsKind() == FAST_ELEMENTS) {
FixedArray* fast_elements = FixedArray::cast(elements());
for (int i = value; i < old_length; i++) {
fast_elements->set_the_hole(i);
}
} else {
ASSERT(GetElementsKind() == FAST_DOUBLE_ELEMENTS);
FixedDoubleArray* fast_double_elements =
FixedDoubleArray::cast(elements());
for (int i = value; i < old_length; i++) {
fast_double_elements->set_the_hole(i);
}
}
}
JSArray::cast(this)->set_length(Smi::cast(smi_length));
}
......@@ -7663,8 +7686,18 @@ MaybeObject* JSObject::SetElementsLength(Object* len) {
int new_capacity = value > min ? value : min;
if (new_capacity <= kMaxFastElementsLength ||
!ShouldConvertToSlowElements(new_capacity)) {
MaybeObject* result =
SetFastElementsCapacityAndLength(new_capacity, value);
MaybeObject* result;
if (GetElementsKind() == FAST_ELEMENTS) {
Object* obj;
{ MaybeObject* maybe_obj = EnsureWritableFastElements();
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
result = SetFastElementsCapacityAndLength(new_capacity, value);
} else {
ASSERT(GetElementsKind() == FAST_DOUBLE_ELEMENTS);
result = SetFastDoubleElementsCapacityAndLength(new_capacity,
value);
}
if (result->IsFailure()) return result;
return this;
}
......@@ -7700,7 +7733,6 @@ MaybeObject* JSObject::SetElementsLength(Object* len) {
case EXTERNAL_FLOAT_ELEMENTS:
case EXTERNAL_DOUBLE_ELEMENTS:
case EXTERNAL_PIXEL_ELEMENTS:
case FAST_DOUBLE_ELEMENTS:
UNREACHABLE();
break;
}
......
......@@ -2169,6 +2169,9 @@ class FixedDoubleArray: public FixedArrayBase {
return kHeaderSize + length * kDoubleSize;
}
// Code Generation support.
static int OffsetOfElementAt(int index) { return SizeFor(index); }
inline static bool is_the_hole_nan(double value);
inline static double hole_nan_as_double();
inline static double canonical_not_the_hole_nan_as_double();
......
......@@ -28,8 +28,8 @@
// Test dictionary -> double elements -> dictionary elements round trip
// Flags: --allow-natives-syntax --unbox-double-arrays --expose-gc
var large_array_size = 500000;
var approx_dict_to_elements_threshold = 69000;
var large_array_size = 100000;
var approx_dict_to_elements_threshold = 75000;
var name = 0;
......@@ -42,14 +42,21 @@ function expected_array_value(i) {
}
function force_to_fast_double_array(a) {
a[large_array_size - 2] = 1;
for (var i= 0; i < approx_dict_to_elements_threshold; ++i ) {
a[i] = expected_array_value(i);
}
assertTrue(%HasFastDoubleElements(a));
}
function make_object_like_array(size) {
obj = new Object();
obj.length = size;
return obj;
}
function testOneArrayType(allocator) {
var large_array = new allocator(500000);
var large_array = new allocator(large_array_size);
force_to_fast_double_array(large_array);
var six = 6;
......@@ -319,35 +326,94 @@ function testOneArrayType(allocator) {
// Make sure that we haven't converted from fast double.
assertTrue(%HasFastDoubleElements(large_array));
// Cause the array to grow beyond it's JSArray length. This will double the
// size of the capacity and force the array into "slow" dictionary case.
large_array[large_array_size+1] = 50;
assertTrue(%HasDictionaryElements(large_array));
assertEquals(50, large_array[large_array_size+1]);
assertEquals(large_array_size+2, large_array.length);
assertEquals(Infinity, large_array[5]);
assertEquals(undefined, large_array[large_array_size-1]);
assertEquals(undefined, large_array[-1]);
assertEquals(large_array_size+2, large_array.length);
// Test dictionary -> double elements -> fast elements.
var large_array2 = new allocator(large_array_size);
force_to_fast_double_array(large_array2);
delete large_array2[5];
// Convert back to fast elements and make sure the contents of the array are
// unchanged.
large_array2[25] = new Object();
assertTrue(%HasFastElements(large_array2));
for (var i= 0; i < approx_dict_to_elements_threshold; i += 500 ) {
}
testOneArrayType(make_object_like_array);
testOneArrayType(Array);
var large_array = new Array(large_array_size);
force_to_fast_double_array(large_array);
assertTrue(%HasFastDoubleElements(large_array));
// Cause the array to grow beyond it's JSArray length. This will double the
// size of the capacity and force the array into "slow" dictionary case.
large_array[5] = Infinity;
large_array[large_array_size+10001] = 50;
assertTrue(%HasDictionaryElements(large_array));
assertEquals(50, large_array[large_array_size+10001]);
assertEquals(large_array_size+10002, large_array.length);
assertEquals(Infinity, large_array[5]);
assertEquals(undefined, large_array[large_array_size-1]);
assertEquals(undefined, large_array[-1]);
assertEquals(large_array_size+10002, large_array.length);
// Test dictionary -> double elements -> fast elements.
var large_array2 = new Array(large_array_size);
force_to_fast_double_array(large_array2);
delete large_array2[5];
// Convert back to fast elements and make sure the contents of the array are
// unchanged.
large_array2[25] = new Object();
assertTrue(%HasFastElements(large_array2));
for (var i= 0; i < approx_dict_to_elements_threshold; i += 500 ) {
if (i != 25 && i != 5) {
assertEquals(expected_array_value(i), large_array2[i]);
}
}
assertEquals(undefined, large_array2[5])
assertEquals(undefined, large_array2[large_array_size-1])
assertEquals(undefined, large_array2[-1])
assertEquals(large_array_size, large_array2.length);
}
assertEquals(undefined, large_array2[5]);
assertEquals(undefined, large_array2[large_array_size-1]);
assertEquals(undefined, large_array2[-1]);
assertEquals(large_array_size, large_array2.length);
// Make sure it's possible to change the array's length and that array is still
// intact after the resize.
var large_array3 = new Array(large_array_size);
force_to_fast_double_array(large_array3);
large_array3.length = 60000;
assertEquals(60000, large_array3.length);
assertEquals(undefined, large_array3[60000]);
assertTrue(%HasFastDoubleElements(large_array3));
assertEquals(expected_array_value(5), large_array3[5]);
assertEquals(expected_array_value(6), large_array3[6]);
assertEquals(expected_array_value(7), large_array3[7]);
assertEquals(expected_array_value(large_array3.length-1),
large_array3[large_array3.length-1]);
assertEquals(undefined, large_array3[large_array_size-1]);
assertEquals(undefined, large_array3[-1]);
gc();
for (var i= 0; i < large_array3.length; i += 501 ) {
assertEquals(expected_array_value(i), large_array3[i]);
}
testOneArrayType(Array);
large_array3.length = 25;
assertEquals(25, large_array3.length);
assertTrue(%HasFastDoubleElements(large_array3));
assertEquals(undefined, large_array3[25]);
assertEquals(expected_array_value(5), large_array3[5]);
assertEquals(expected_array_value(6), large_array3[6]);
assertEquals(expected_array_value(7), large_array3[7]);
assertEquals(expected_array_value(large_array3.length-1),
large_array3[large_array3.length-1]);
assertEquals(undefined, large_array3[large_array_size-1]);
assertEquals(undefined, large_array3[-1]);
gc();
for (var i= 0; i < large_array3.length; ++i) {
assertEquals(expected_array_value(i), large_array3[i]);
}
large_array3.length = 100;
assertEquals(100, large_array3.length);
large_array3[95] = 95;
assertTrue(%HasFastDoubleElements(large_array3));
assertEquals(undefined, large_array3[100]);
assertEquals(95, large_array3[95]);
assertEquals(expected_array_value(5), large_array3[5]);
assertEquals(expected_array_value(6), large_array3[6]);
assertEquals(expected_array_value(7), large_array3[7]);
assertEquals(undefined, large_array3[large_array3.length-1]);
assertEquals(undefined, large_array3[large_array_size-1]);
assertEquals(undefined, large_array3[-1]);
gc();
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