From: danno@chromium.org Date: Tue, 19 Jul 2011 16:06:17 +0000 (+0000) Subject: Implement setting the length property for FixedDoubleArrays. X-Git-Tag: upstream/4.7.83~18871 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=837d83ebf3afb9894d0fb5f1cb260963856b7293;p=platform%2Fupstream%2Fv8.git 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 --- diff --git a/src/objects-inl.h b/src/objects-inl.h index e069b79..5726b37 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h @@ -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; } diff --git a/src/objects.cc b/src/objects.cc index b1d5f14..0b73049 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -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(length)) { FixedDoubleArray::cast(elements())->set_the_hole(index); } @@ -7628,31 +7628,54 @@ 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 { - fast_elements->set_length(value); - Address filler_start = fast_elements->address() + - FixedArray::OffsetOfElementAt(value); - int filler_size = (old_capacity - value) * kPointerSize; + 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); + filler_start = fast_elements->address() + + FixedArray::OffsetOfElementAt(value); + 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()); - for (int i = value; i < old_length; i++) { - fast_elements->set_the_hole(i); + 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; } diff --git a/src/objects.h b/src/objects.h index 43747cc..9b55ea7 100644 --- a/src/objects.h +++ b/src/objects.h @@ -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(); diff --git a/test/mjsunit/unbox-double-arrays.js b/test/mjsunit/unbox-double-arrays.js index 312955b..1149838 100644 --- a/test/mjsunit/unbox-double-arrays.js +++ b/test/mjsunit/unbox-double-arrays.js @@ -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 ) { - 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); } +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); + +// 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]); +} + +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();