bug 599468: clean up non-holes when shrinking array, r=gal, a=clegnitto
authorNicholas Nethercote <nnethercote@mozilla.com>
Thu, 18 Nov 2010 14:37:48 -0800
changeset 27214 815454d74e8ad1af0a9d7a9a2f0637c4b41eea70
parent 27213 da1f11e5b1e06fe02f8c24051abd816476477023
child 27215 4fac36e8cd3ee00ad63a4bfdce43a38507590173
push id2571
push userdveditz@mozilla.com
push dateThu, 18 Nov 2010 22:38:50 +0000
reviewersgal, clegnitto
bugs599468
milestone1.9.1.16pre
bug 599468: clean up non-holes when shrinking array, r=gal, a=clegnitto
js/src/jsarray.cpp
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -647,19 +647,26 @@ array_length_setter(JSContext *cx, JSObj
 
     if (oldlen < newlen) {
         obj->fslots[JSSLOT_ARRAY_LENGTH] = newlen;
         return JS_TRUE;
     }
 
     if (OBJ_IS_DENSE_ARRAY(cx, obj)) {
         /* Don't reallocate if we're not actually shrinking our slots. */
-        jsuint oldsize = js_DenseArrayCapacity(obj);
-        if (oldsize >= newlen && !ResizeSlots(cx, obj, oldsize, newlen))
-            return JS_FALSE;
+        jsuint capacity = js_DenseArrayCapacity(obj);
+        if (capacity > newlen) {
+            jsuint numNonHolesRemoved = 0;
+            for (jsval *slots = obj->dslots + newlen; slots < obj->dslots + capacity; slots++)
+                if (*slots != JSVAL_HOLE)
+                    numNonHolesRemoved++;
+            if (!ResizeSlots(cx, obj, capacity, newlen))
+                return JS_FALSE;
+            obj->fslots[JSSLOT_ARRAY_COUNT] -= numNonHolesRemoved;
+        }
     } else if (oldlen - newlen < (1 << 24)) {
         do {
             --oldlen;
             if (!JS_CHECK_OPERATION_LIMIT(cx) ||
                 !DeleteArrayElement(cx, obj, oldlen)) {
                 return JS_FALSE;
             }
         } while (oldlen != newlen);