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

Reply via email to