Revision: 13056
Author: [email protected]
Date: Mon Nov 26 06:29:21 2012
Log: Ensure double arrays are filled with holes when extended from
variations of empty arrays.
BUG=162085
Review URL: https://chromiumcodereview.appspot.com/11414155
http://code.google.com/p/v8/source/detail?r=13056
Added:
/branches/bleeding_edge/test/mjsunit/regress/regress-crbug-162085.js
Modified:
/branches/bleeding_edge/src/arm/stub-cache-arm.cc
/branches/bleeding_edge/src/elements.cc
/branches/bleeding_edge/src/ia32/stub-cache-ia32.cc
/branches/bleeding_edge/src/parser.cc
/branches/bleeding_edge/src/x64/stub-cache-x64.cc
/branches/bleeding_edge/test/mjsunit/array-natives-elements.js
=======================================
--- /dev/null
+++ /branches/bleeding_edge/test/mjsunit/regress/regress-crbug-162085.js
Mon Nov 26 06:29:21 2012
@@ -0,0 +1,55 @@
+// 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.
+
+// Ensure extending an empty packed smi array with a double initializes the
+// array with holes.
+var a = [1,2,3];
+a.length = 0;
+a[0] = 1.4;
+assertEquals(undefined, a[1]);
+assertEquals(undefined, a[2]);
+assertEquals(undefined, a[3]);
+
+// Ensure the double array growstub initializes the array with holes.
+function grow_store(a,i,v) {
+ a[i] = v;
+}
+
+var a2 = [1.3];
+grow_store(a2,1,1.4);
+a2.length = 0;
+grow_store(a2,0,1.5);
+assertEquals(undefined, a2[1]);
+assertEquals(undefined, a2[2]);
+assertEquals(undefined, a2[3]);
+
+// Check storing objects using the double grow stub.
+var a3 = [1.3];
+var o = {};
+grow_store(a3, 1, o);
+assertEquals(1.3, a3[0]);
+assertEquals(o, a3[1]);
=======================================
--- /branches/bleeding_edge/src/arm/stub-cache-arm.cc Fri Nov 16 00:54:01
2012
+++ /branches/bleeding_edge/src/arm/stub-cache-arm.cc Mon Nov 26 06:29:21
2012
@@ -4783,8 +4783,7 @@
__ AllocateInNewSpace(size, elements_reg, scratch1, scratch2, &slow,
TAG_OBJECT);
- // Initialize the new FixedDoubleArray. Leave elements unitialized for
- // efficiency, they are guaranteed to be initialized before use.
+ // Initialize the new FixedDoubleArray.
__ LoadRoot(scratch1, Heap::kFixedDoubleArrayMapRootIndex);
__ str(scratch1, FieldMemOperand(elements_reg, JSObject::kMapOffset));
__ mov(scratch1,
@@ -4792,6 +4791,24 @@
__ str(scratch1,
FieldMemOperand(elements_reg, FixedDoubleArray::kLengthOffset));
+ __ mov(scratch1, Operand(kHoleNanLower32));
+ __ mov(scratch2, Operand(kHoleNanUpper32));
+ for (int i = 1; i < JSArray::kPreallocatedArrayElements; i++) {
+ int offset = FixedDoubleArray::OffsetOfElementAt(i);
+ __ str(scratch1, FieldMemOperand(elements_reg, offset));
+ __ str(scratch2, FieldMemOperand(elements_reg, offset +
kPointerSize));
+ }
+
+ __ StoreNumberToDoubleElements(value_reg,
+ key_reg,
+ // All registers after this are
overwritten.
+ elements_reg,
+ scratch1,
+ scratch2,
+ scratch3,
+ scratch4,
+ &transition_elements_kind);
+
// Install the new backing store in the JSArray.
__ str(elements_reg,
FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
@@ -4804,7 +4821,7 @@
__ str(length_reg, FieldMemOperand(receiver_reg,
JSArray::kLengthOffset));
__ ldr(elements_reg,
FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
- __ jmp(&finish_store);
+ __ Ret();
__ bind(&check_capacity);
// Make sure that the backing store can hold additional elements.
=======================================
--- /branches/bleeding_edge/src/elements.cc Mon Nov 19 07:00:34 2012
+++ /branches/bleeding_edge/src/elements.cc Mon Nov 26 06:29:21 2012
@@ -375,6 +375,9 @@
copy_size = from->length() - from_start;
if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) {
to_end = to->length();
+ for (uint32_t i = to_start + copy_size; i < to_end; ++i) {
+ to->set_the_hole(i);
+ }
} else {
to_end = to_start + static_cast<uint32_t>(copy_size);
}
@@ -392,10 +395,6 @@
ASSERT(!smi->IsTheHole());
to->set(to_start, Smi::cast(smi)->value());
}
-
- while (to_start < to_end) {
- to->set_the_hole(to_start++);
- }
}
=======================================
--- /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc Thu Nov 15 04:19:14
2012
+++ /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc Mon Nov 26 06:29:21
2012
@@ -4353,13 +4353,22 @@
// ecx: key
// edx: receiver
// edi: elements
- // Initialize the new FixedDoubleArray. Leave elements unitialized for
- // efficiency, they are guaranteed to be initialized before use.
+ // Initialize the new FixedDoubleArray.
__ mov(FieldOperand(edi, JSObject::kMapOffset),
Immediate(masm->isolate()->factory()->fixed_double_array_map()));
__ mov(FieldOperand(edi, FixedDoubleArray::kLengthOffset),
Immediate(Smi::FromInt(JSArray::kPreallocatedArrayElements)));
+ for (int i = 1; i < JSArray::kPreallocatedArrayElements; i++) {
+ int offset = FixedDoubleArray::OffsetOfElementAt(i);
+ __ mov(FieldOperand(edi, offset), Immediate(kHoleNanLower32));
+ __ mov(FieldOperand(edi, offset + kPointerSize),
+ Immediate(kHoleNanUpper32));
+ }
+
+ __ StoreNumberToDoubleElements(eax, edi, ecx, ebx, xmm0,
+ &transition_elements_kind, true);
+
// Install the new backing store in the JSArray.
__ mov(FieldOperand(edx, JSObject::kElementsOffset), edi);
__ RecordWriteField(edx, JSObject::kElementsOffset, edi, ebx,
@@ -4369,7 +4378,7 @@
__ add(FieldOperand(edx, JSArray::kLengthOffset),
Immediate(Smi::FromInt(1)));
__ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
- __ jmp(&finish_store);
+ __ ret(0);
__ bind(&check_capacity);
// eax: value
=======================================
--- /branches/bleeding_edge/src/parser.cc Fri Nov 23 05:23:39 2012
+++ /branches/bleeding_edge/src/parser.cc Mon Nov 26 06:29:21 2012
@@ -3718,7 +3718,6 @@
isolate()->factory()->NewFixedArray(values->length(), TENURED);
Handle<FixedDoubleArray> double_literals;
ElementsKind elements_kind = FAST_SMI_ELEMENTS;
- bool has_only_undefined_values = true;
bool has_hole_values = false;
// Fill in the literals.
@@ -3750,7 +3749,6 @@
// FAST_DOUBLE_ELEMENTS and FAST_ELEMENTS as necessary. Always
remember
// the tagged value, no matter what the ElementsKind is in case we
// ultimately end up in FAST_ELEMENTS.
- has_only_undefined_values = false;
object_literals->set(i, *boilerplate_value);
if (elements_kind == FAST_SMI_ELEMENTS) {
// Smi only elements. Notice if a transition to
FAST_DOUBLE_ELEMENTS or
@@ -3788,13 +3786,6 @@
}
}
}
-
- // Very small array literals that don't have a concrete hint about their
type
- // from a constant value should default to the slow case to avoid lots of
- // elements transitions on really small objects.
- if (has_only_undefined_values && values->length() <= 2) {
- elements_kind = FAST_ELEMENTS;
- }
// Simple and shallow arrays can be lazily copied, we transform the
// elements array to a copy-on-write array.
=======================================
--- /branches/bleeding_edge/src/x64/stub-cache-x64.cc Thu Nov 15 08:16:09
2012
+++ /branches/bleeding_edge/src/x64/stub-cache-x64.cc Mon Nov 26 06:29:21
2012
@@ -4026,7 +4026,7 @@
// -- rsp[0] : return address
// -----------------------------------
Label miss_force_generic, transition_elements_kind, finish_store;
- Label grow, slow, check_capacity;
+ Label grow, slow, check_capacity, restore_key_transition_elements_kind;
// This stub is meant to be tail-jumped to, the receiver must already
// have been verified by the caller to not be a smi.
@@ -4055,7 +4055,7 @@
__ bind(&finish_store);
__ SmiToInteger32(rcx, rcx);
__ StoreNumberToDoubleElements(rax, rdi, rcx, xmm0,
- &transition_elements_kind);
+ &restore_key_transition_elements_kind);
__ ret(0);
// Handle store cache miss, replacing the ic with the generic stub.
@@ -4064,9 +4064,10 @@
masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
__ jmp(ic_force_generic, RelocInfo::CODE_TARGET);
- __ bind(&transition_elements_kind);
+ __ bind(&restore_key_transition_elements_kind);
// Restore smi-tagging of rcx.
__ Integer32ToSmi(rcx, rcx);
+ __ bind(&transition_elements_kind);
Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss();
__ jmp(ic_miss, RelocInfo::CODE_TARGET);
@@ -4107,6 +4108,16 @@
__ Move(FieldOperand(rdi, FixedDoubleArray::kLengthOffset),
Smi::FromInt(JSArray::kPreallocatedArrayElements));
+ __ movq(r8, BitCast<int64_t, uint64_t>(kHoleNanInt64),
RelocInfo::NONE);
+ for (int i = 1; i < JSArray::kPreallocatedArrayElements; i++) {
+ __ movq(FieldOperand(rdi, FixedDoubleArray::OffsetOfElementAt(i)),
r8);
+ }
+
+ // Increment the length of the array.
+ __ SmiToInteger32(rcx, rcx);
+ __ StoreNumberToDoubleElements(rax, rdi, rcx, xmm0,
+ &restore_key_transition_elements_kind);
+
// Install the new backing store in the JSArray.
__ movq(FieldOperand(rdx, JSObject::kElementsOffset), rdi);
__ RecordWriteField(rdx, JSObject::kElementsOffset, rdi, rbx,
@@ -4115,7 +4126,7 @@
// Increment the length of the array.
__ Move(FieldOperand(rdx, JSArray::kLengthOffset), Smi::FromInt(1));
__ movq(rdi, FieldOperand(rdx, JSObject::kElementsOffset));
- __ jmp(&finish_store);
+ __ ret(0);
__ bind(&check_capacity);
// rax: value
=======================================
--- /branches/bleeding_edge/test/mjsunit/array-natives-elements.js Fri Nov
23 05:23:39 2012
+++ /branches/bleeding_edge/test/mjsunit/array-natives-elements.js Mon Nov
26 06:29:21 2012
@@ -49,7 +49,7 @@
function array_natives_test() {
// Ensure small array literals start in specific element kind mode.
- assertTrue(%HasFastObjectElements([]));
+ assertTrue(%HasFastSmiElements([]));
assertTrue(%HasFastSmiElements([1]));
assertTrue(%HasFastSmiElements([1,2]));
assertTrue(%HasFastDoubleElements([1.1]));
@@ -73,7 +73,7 @@
// Concat
var a1;
a1 = [1,2,3].concat([]);
- assertTrue(%HasFastObjectElements(a1));
+ assertTrue(%HasFastSmiElements(a1));
assertEquals([1,2,3], a1);
a1 = [1,2,3].concat([4,5,6]);
assertTrue(%HasFastSmiElements(a1));
@@ -82,7 +82,7 @@
assertTrue(%HasFastSmiElements(a1));
assertEquals([1,2,3,4,5,6,7,8,9], a1);
a1 = [1.1,2,3].concat([]);
- assertTrue(%HasFastObjectElements(a1));
+ assertTrue(%HasFastDoubleElements(a1));
assertEquals([1.1,2,3], a1);
a1 = [1,2,3].concat([1.1, 2]);
assertTrue(%HasFastDoubleElements(a1));
@@ -173,7 +173,7 @@
a3r = a3.splice(0, 0, 2);
// Commented out since handled in js, which takes the best fit.
// assertTrue(%HasFastDoubleElements(a3r));
- assertTrue(%HasFastObjectElements(a3r));
+ assertTrue(%HasFastSmiElements(a3r));
assertTrue(%HasFastDoubleElements(a3));
assertEquals([], a3r);
assertEquals([2, 1.1, 2, 3], a3);
@@ -187,7 +187,7 @@
a3r = a3.splice(0, 0, 2.1);
// Commented out since handled in js, which takes the best fit.
// assertTrue(%HasFastDoubleElements(a3r));
- assertTrue(%HasFastObjectElements(a3r));
+ assertTrue(%HasFastSmiElements(a3r));
assertTrue(%HasFastDoubleElements(a3));
assertEquals([], a3r);
assertEquals([2.1, 1.1, 2, 3], a3);
@@ -201,7 +201,7 @@
a3r = a3.splice(0, 0, 2.1);
// Commented out since handled in js, which takes the best fit.
// assertTrue(%HasFastDoubleElements(a3r));
- assertTrue(%HasFastObjectElements(a3r));
+ assertTrue(%HasFastSmiElements(a3r));
assertTrue(%HasFastDoubleElements(a3));
assertEquals([], a3r);
assertEquals([2.1, 1, 2, 3], a3);
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev