Reviewers: Jakob,
Message:
PTAL
Description:
Properly set ElementsKind of empty FAST_DOUBLE_ELEMENTS arrays when
transitioning.
[email protected]
BUG=chromium:117409
TEST=test/mjsunit/regress/regress-117409.js
Please review this at https://chromiumcodereview.appspot.com/10386045/
SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge
Affected files:
M src/builtins.cc
M src/objects-printer.cc
M src/objects.cc
A test/mjsunit/regress/regress-117409.js
Index: src/builtins.cc
diff --git a/src/builtins.cc b/src/builtins.cc
index
0f79510d9fcf2b0ac77dbc9e12bfc2bd931ab925..6d1c6a978599a96720b6e259469681ddf3c70f7e
100644
--- a/src/builtins.cc
+++ b/src/builtins.cc
@@ -412,12 +412,19 @@ static inline MaybeObject*
EnsureJSArrayWithWritableFastElements(
HeapObject* elms = array->elements();
Map* map = elms->map();
if (map == heap->fixed_array_map()) {
- if (args == NULL || !array->HasFastSmiOnlyElements()) {
+ if (array->HasFastElements()) return elms;
+ if (args == NULL) {
+ if (array->HasFastDoubleElements()) {
+ ASSERT(elms == heap->empty_fixed_array());
+ MaybeObject* maybe_transition =
+ array->TransitionElementsKind(FAST_ELEMENTS);
+ if (maybe_transition->IsFailure()) return maybe_transition;
+ }
return elms;
}
} else if (map == heap->fixed_cow_array_map()) {
MaybeObject* maybe_writable_result =
array->EnsureWritableFastElements();
- if (args == NULL || !array->HasFastSmiOnlyElements() ||
+ if (args == NULL || array->HasFastElements() ||
maybe_writable_result->IsFailure()) {
return maybe_writable_result;
}
Index: src/objects-printer.cc
diff --git a/src/objects-printer.cc b/src/objects-printer.cc
index
7d6ef67a30780135544660dd7cc1d90f9032b299..febdaabb12e0fa978a184db467a02522624765bb
100644
--- a/src/objects-printer.cc
+++ b/src/objects-printer.cc
@@ -331,14 +331,16 @@ void JSObject::PrintElements(FILE* out) {
}
case FAST_DOUBLE_ELEMENTS: {
// Print in array notation for non-sparse arrays.
- FixedDoubleArray* p = FixedDoubleArray::cast(elements());
- for (int i = 0; i < p->length(); i++) {
- if (p->is_the_hole(i)) {
- PrintF(out, " %d: <the hole>", i);
- } else {
- PrintF(out, " %d: %g", i, p->get_scalar(i));
+ if (elements()->length() > 0) {
+ FixedDoubleArray* p = FixedDoubleArray::cast(elements());
+ for (int i = 0; i < p->length(); i++) {
+ if (p->is_the_hole(i)) {
+ PrintF(out, " %d: <the hole>", i);
+ } else {
+ PrintF(out, " %d: %g", i, p->get_scalar(i));
+ }
+ PrintF(out, "\n");
}
- PrintF(out, "\n");
}
break;
}
Index: src/objects.cc
diff --git a/src/objects.cc b/src/objects.cc
index
5649a56464bb69300c1b031dd5c5cf4a45fbf53e..08a2e8eeac04102228d9176d9cd0e1340301af23
100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -8653,7 +8653,7 @@ MaybeObject*
JSObject::SetFastDoubleElementsCapacityAndLength(
// We should never end in here with a pixel or external array.
ASSERT(!HasExternalArrayElements());
- FixedDoubleArray* elems;
+ FixedArrayBase* elems;
{ MaybeObject* maybe_obj =
heap->AllocateUninitializedFixedDoubleArray(capacity);
if (!maybe_obj->To(&elems)) return maybe_obj;
@@ -9807,9 +9807,10 @@ MaybeObject*
JSObject::TransitionElementsKind(ElementsKind to_kind) {
ElementsKind from_kind = map()->elements_kind();
Isolate* isolate = GetIsolate();
- if (from_kind == FAST_SMI_ONLY_ELEMENTS &&
- (to_kind == FAST_ELEMENTS ||
- elements() == isolate->heap()->empty_fixed_array())) {
+ if ((from_kind == FAST_SMI_ONLY_ELEMENTS ||
+ elements() == isolate->heap()->empty_fixed_array()) &&
+ to_kind == FAST_ELEMENTS) {
+ ASSERT(from_kind != FAST_ELEMENTS);
MaybeObject* maybe_new_map = GetElementsTransitionMap(isolate,
to_kind);
Map* new_map;
if (!maybe_new_map->To(&new_map)) return maybe_new_map;
Index: test/mjsunit/regress/regress-117409.js
diff --git a/test/mjsunit/regress/regress-117409.js
b/test/mjsunit/regress/regress-117409.js
new file mode 100644
index
0000000000000000000000000000000000000000..7cc892eb0aca8af9101b3d1b5dcb3c4cad605330
--- /dev/null
+++ b/test/mjsunit/regress/regress-117409.js
@@ -0,0 +1,53 @@
+// 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.
+
+// Flags: --expose-gc
+
+function KeyedStoreIC(a) { a[0] = Math.E; }
+
+// literal with a fast double elements backing store
+var literal = [1.2];
+
+// specialize the IC for fast double elements
+KeyedStoreIC(literal);
+KeyedStoreIC(literal);
+
+// truncate js array to 0 elements:
+// backing store will be replaces with empty fixed array
+literal.length = 0;
+
+// ArrayPush built-in will replace empty fixed array backing
+// store with 19 elements fixed array backing store.
+// Leading to a mismatch between the map and the backing store.
+// Debug mode will crash here in set_elements accessor.
+literal.push(Math.E, Math.E);
+
+// Corrupt the backing store!
+KeyedStoreIC(literal);
+
+// Release mode will crash here when trying to visit parts of E as
pointers.
+gc();
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev