Make ElementsAccessors more tolerant of varying backing store types
authorverwaest@chromium.org <verwaest@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 28 Nov 2012 08:41:45 +0000 (08:41 +0000)
committerverwaest@chromium.org <verwaest@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 28 Nov 2012 08:41:45 +0000 (08:41 +0000)
This avoids bogus calls to Fixed*Array::cast() when FastElements-backed objects are empty (and thus backed by empty_fixed_array).

Review URL: https://chromiumcodereview.appspot.com/11299190
Patch from Adam Klein <adamk@chromium.org>.

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13071 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/elements.cc
test/mjsunit/regress/regress-observe-empty-double-array.js [new file with mode: 0644]

index 9ff77f7..ae5c7de 100644 (file)
@@ -528,7 +528,7 @@ class ElementsAccessorBase : public ElementsAccessor {
   static bool HasElementImpl(Object* receiver,
                              JSObject* holder,
                              uint32_t key,
-                             BackingStore* backing_store) {
+                             FixedArrayBase* backing_store) {
     return ElementsAccessorSubclass::GetAttributesImpl(
         receiver, holder, key, backing_store) != ABSENT;
   }
@@ -573,18 +573,18 @@ class ElementsAccessorBase : public ElementsAccessor {
       backing_store = holder->elements();
     }
     return ElementsAccessorSubclass::GetAttributesImpl(
-        receiver, holder, key, BackingStore::cast(backing_store));
+        receiver, holder, key, backing_store);
   }
 
   MUST_USE_RESULT static PropertyAttributes GetAttributesImpl(
         Object* receiver,
         JSObject* obj,
         uint32_t key,
-        BackingStore* backing_store) {
+        FixedArrayBase* backing_store) {
     if (key >= ElementsAccessorSubclass::GetCapacityImpl(backing_store)) {
       return ABSENT;
     }
-    return backing_store->is_the_hole(key) ? ABSENT : NONE;
+    return BackingStore::cast(backing_store)->is_the_hole(key) ? ABSENT : NONE;
   }
 
   MUST_USE_RESULT virtual PropertyType GetType(
@@ -784,13 +784,12 @@ class ElementsAccessorBase : public ElementsAccessor {
   }
 
  protected:
-  static uint32_t GetCapacityImpl(BackingStore* backing_store) {
+  static uint32_t GetCapacityImpl(FixedArrayBase* backing_store) {
     return backing_store->length();
   }
 
   virtual uint32_t GetCapacity(FixedArrayBase* backing_store) {
-    return ElementsAccessorSubclass::GetCapacityImpl(
-        BackingStore::cast(backing_store));
+    return ElementsAccessorSubclass::GetCapacityImpl(backing_store);
   }
 
   static uint32_t GetKeyForIndexImpl(BackingStore* backing_store,
@@ -1210,7 +1209,7 @@ class ExternalElementsAccessor
       Object* receiver,
       JSObject* obj,
       uint32_t key,
-      BackingStore* backing_store) {
+      FixedArrayBase* backing_store) {
     return
         key < ExternalElementsAccessorSubclass::GetCapacityImpl(backing_store)
           ? NONE : ABSENT;
@@ -1519,10 +1518,12 @@ class DictionaryElementsAccessor
       Object* receiver,
       JSObject* obj,
       uint32_t key,
-      SeededNumberDictionary* backing_store) {
-    int entry = backing_store->FindEntry(key);
+      FixedArrayBase* backing_store) {
+    SeededNumberDictionary* dictionary =
+        SeededNumberDictionary::cast(backing_store);
+    int entry = dictionary->FindEntry(key);
     if (entry != SeededNumberDictionary::kNotFound) {
-      return backing_store->DetailsAt(entry).attributes();
+      return dictionary->DetailsAt(entry).attributes();
     }
     return ABSENT;
   }
@@ -1616,7 +1617,8 @@ class NonStrictArgumentsElementsAccessor : public ElementsAccessorBase<
       Object* receiver,
       JSObject* obj,
       uint32_t key,
-      FixedArray* parameter_map) {
+      FixedArrayBase* backing_store) {
+    FixedArray* parameter_map = FixedArray::cast(backing_store);
     Object* probe = GetParameterMapArg(obj, parameter_map, key);
     if (!probe->IsTheHole()) {
       return NONE;
@@ -1708,7 +1710,8 @@ class NonStrictArgumentsElementsAccessor : public ElementsAccessorBase<
                                   to_start, copy_size, arguments);
   }
 
-  static uint32_t GetCapacityImpl(FixedArray* parameter_map) {
+  static uint32_t GetCapacityImpl(FixedArrayBase* backing_store) {
+    FixedArray* parameter_map = FixedArray::cast(backing_store);
     FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1));
     return Max(static_cast<uint32_t>(parameter_map->length() - 2),
                ForArray(arguments)->GetCapacity(arguments));
diff --git a/test/mjsunit/regress/regress-observe-empty-double-array.js b/test/mjsunit/regress/regress-observe-empty-double-array.js
new file mode 100644 (file)
index 0000000..aea9c73
--- /dev/null
@@ -0,0 +1,37 @@
+// 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: --harmony-observation --allow-natives-syntax
+//
+// Test passes if it does not crash.
+
+arr = [1.1];
+Object.observe(arr, function(){});
+arr.length = 0;
+assertTrue(%HasFastDoubleElements(arr));
+// Should not crash
+arr.push(1.1);