[INFER] Fix incorrect uses of getDenseArrayCapacity in array_concat, CloneDensePrimitiveArray, and stubs::GetElem.
authorBrian Hackett <bhackett1024@gmail.com>
Sat, 11 Dec 2010 07:30:44 -0800
changeset 74655 eb1b0cc2360cc41ffc7d7a1166af67cf9c4c6532
parent 74654 0462de4a8aa1fcc1addf410df4a305421539b2bd
child 74656 710a6281442a10b6d2de358b8672ca2234e5d243
push id2
push userbsmedberg@mozilla.com
push dateFri, 19 Aug 2011 14:38:13 +0000
milestone2.0b8pre
[INFER] Fix incorrect uses of getDenseArrayCapacity in array_concat, CloneDensePrimitiveArray, and stubs::GetElem.
js/src/jit-test/tests/basic/testArrayConcat.js
js/src/jsarray.cpp
js/src/methodjit/StubCalls.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/testArrayConcat.js
@@ -0,0 +1,7 @@
+
+var x = Array(4);
+x[0] = 1;
+x[1] = 2;
+x[2] = 3;
+var y = x.concat();
+assertEq(y[3], undefined);
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -2533,25 +2533,19 @@ array_concat(JSContext *cx, uintN argc, 
     if (cx->isTypeCallerMonitored())
         cx->markTypeObjectUnknownProperties(ntype);
 
     /* Create a new Array object and root it using *vp. */
     JSObject *aobj = ComputeThisFromVp(cx, vp);
     JSObject *nobj;
     jsuint length;
     if (aobj->isDenseArray()) {
-        /*
-         * Clone aobj but pass the minimum of its length and capacity, to
-         * handle a = [1,2,3]; a.length = 10000 "dense" cases efficiently. In
-         * the normal case where length is <= capacity, nobj and aobj will have
-         * the same capacity.
-         */
         length = aobj->getArrayLength();
-        jsuint capacity = aobj->getDenseArrayCapacity();
-        nobj = js_NewArrayObject(cx, JS_MIN(length, capacity), aobj->getDenseArrayElements(), ntype);
+        jsuint initlen = aobj->getDenseArrayInitializedLength();
+        nobj = js_NewArrayObject(cx, initlen, aobj->getDenseArrayElements(), ntype);
         if (!nobj)
             return JS_FALSE;
         nobj->setArrayLength(cx, length);
         vp->setObject(*nobj);
         if (argc == 0)
             return JS_TRUE;
         argc--;
         p++;
@@ -3594,30 +3588,23 @@ js_CloneDensePrimitiveArray(JSContext *c
          * This wasn't a dense array. Return JS_TRUE but a NULL clone to signal
          * that no exception was encountered.
          */
         *clone = NULL;
         return JS_TRUE;
     }
 
     jsuint length = obj->getArrayLength();
-
-    /*
-     * Must use the minimum of original array's length and capacity, to handle
-     * |a = [1,2,3]; a.length = 10000| "dense" cases efficiently. In the normal
-     * case where length is <= capacity, the clone and original array will have
-     * the same capacity.
-     */
-    jsuint jsvalCount = JS_MIN(obj->getDenseArrayCapacity(), length);
+    jsuint initlen = obj->getDenseArrayInitializedLength();
 
     js::AutoValueVector vector(cx);
-    if (!vector.reserve(jsvalCount))
+    if (!vector.reserve(initlen))
         return JS_FALSE;
 
-    for (jsuint i = 0; i < jsvalCount; i++) {
+    for (jsuint i = 0; i < initlen; i++) {
         const Value &val = obj->getDenseArrayElement(i);
 
         if (val.isString()) {
             // Strings must be made immutable before being copied to a clone.
             if (!js_MakeStringImmutable(cx, val.toString()))
                 return JS_FALSE;
         } else if (val.isObject()) {
             /*
@@ -3626,15 +3613,15 @@ js_CloneDensePrimitiveArray(JSContext *c
              */
             *clone = NULL;
             return JS_TRUE;
         }
 
         vector.append(val);
     }
 
-    *clone = js_NewArrayObject(cx, jsvalCount, vector.begin(), obj->getTypeObject());
+    *clone = js_NewArrayObject(cx, initlen, vector.begin(), obj->getTypeObject());
     if (!*clone)
         return JS_FALSE;
     (*clone)->setArrayLength(cx, length);
 
     return JS_TRUE;
 }
--- a/js/src/methodjit/StubCalls.cpp
+++ b/js/src/methodjit/StubCalls.cpp
@@ -471,18 +471,17 @@ stubs::GetElem(VMFrame &f)
     const Value *copyFrom;
     Value rval;
     jsid id;
     if (rref.isInt32()) {
         int32_t i = rref.toInt32();
         if (obj->isDenseArray()) {
             jsuint idx = jsuint(i);
 
-            if (idx < obj->getArrayLength() &&
-                idx < obj->getDenseArrayCapacity()) {
+            if (idx < obj->getDenseArrayInitializedLength()) {
                 copyFrom = obj->addressOfDenseArrayElement(idx);
                 if (!copyFrom->isMagic())
                     goto end_getelem;
             }
         } else if (obj->isArguments()) {
             uint32 arg = uint32(i);
 
             if (arg < obj->getArgsInitialLength()) {