[INFER] Use the 'this' array type as the result in Array.concat, bug 642412.
authorBrian Hackett <bhackett1024@gmail.com>
Fri, 18 Mar 2011 07:56:50 -0700
changeset 74807 bff02e9994e3927b164081d20d4eb8a74ee97724
parent 74806 a900619f0e0467f25e0d4a887645b384e8d959c1
child 74808 ac5f63354ab2d2f43f49dc96b5d675b29a02d4fd
push id2
push userbsmedberg@mozilla.com
push dateFri, 19 Aug 2011 14:38:13 +0000
bugs642412
milestone2.0b13pre
[INFER] Use the 'this' array type as the result in Array.concat, bug 642412.
js/src/jsarray.cpp
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -2585,52 +2585,50 @@ array_splice(JSContext *cx, uintN argc, 
  * Python-esque sequence operations.
  */
 static JSBool
 array_concat(JSContext *cx, uintN argc, Value *vp)
 {
     /* Treat our |this| object as the first argument; see ECMA 15.4.4.4. */
     Value *p = JS_ARGV(cx, vp) - 1;
 
-    /* Get the type object to use for the result. */
-    TypeObject *ntype = cx->getTypeCallerInitObject(true);
-    if (!ntype)
-        return false;
-
     /* Create a new Array object and root it using *vp. */
     JSObject *aobj = ToObject(cx, &vp[1]);
     if (!aobj)
         return false;
 
     JSObject *nobj;
     jsuint length;
     if (aobj->isDenseArray()) {
         length = aobj->getArrayLength();
         Value *vector = aobj->getDenseArrayElements();
         jsuint initlen = aobj->getDenseArrayInitializedLength();
         nobj = NewDenseCopiedArray(cx, initlen, vector);
         if (!nobj)
             return JS_FALSE;
-        nobj->setType(ntype);
+        if (nobj->getProto() == aobj->getProto())
+            nobj->setType(aobj->getType());
+        else if (!cx->markTypeCallerUnexpected(TYPE_UNKNOWN))
+            return JS_FALSE;
+        nobj->setType(aobj->getType());
         if (!nobj->setArrayLength(cx, length))
             return JS_FALSE;
-        if (!InitArrayTypes(cx, ntype, vector, initlen))
-            return JS_FALSE;
         if (!aobj->isPackedDenseArray() && !nobj->setDenseArrayNotPacked(cx))
             return JS_FALSE;
         vp->setObject(*nobj);
         if (argc == 0)
             return JS_TRUE;
         argc--;
         p++;
     } else {
         nobj = NewDenseEmptyArray(cx);
         if (!nobj)
             return JS_FALSE;
-        nobj->setType(ntype);
+        if (!cx->markTypeCallerUnexpected(TYPE_UNKNOWN))
+            return JS_FALSE;
         vp->setObject(*nobj);
         length = 0;
     }
 
     AutoValueRooter tvr(cx);
 
     /* Loop over [0, argc] to concat args into nobj, expanding all Arrays. */
     for (uintN i = 0; i <= argc; i++) {
@@ -2649,34 +2647,34 @@ array_concat(JSContext *cx, uintN argc, 
                     return false;
                 for (jsuint slot = 0; slot < alength; slot++) {
                     JSBool hole;
                     if (!JS_CHECK_OPERATION_LIMIT(cx) ||
                         !GetElement(cx, aobj, slot, &hole, tvr.addr())) {
                         return false;
                     }
 
-                    if (!hole && !cx->addTypePropertyId(ntype, JSID_VOID, tvr.value()))
+                    if (!hole && !cx->addTypePropertyId(nobj->getType(), JSID_VOID, tvr.value()))
                         return false;
 
                     /*
                      * Per ECMA 262, 15.4.4.4, step 9, ignore nonexistent
                      * properties.
                      */
                     if (!hole &&
                         !SetArrayElement(cx, nobj, length+slot, tvr.value())) {
                         return false;
                     }
                 }
                 length += alength;
                 continue;
             }
         }
 
-        if (!cx->addTypePropertyId(ntype, JSID_VOID, v))
+        if (!cx->addTypePropertyId(nobj->getType(), JSID_VOID, v))
             return false;
 
         if (!SetArrayElement(cx, nobj, length, v))
             return false;
         length++;
     }
 
     return js_SetLengthProperty(cx, nobj, length);
@@ -3204,43 +3202,23 @@ array_TypeConcat(JSContext *cx, JSTypeFu
     TypeCallsite *site = Valueify(jssite);
 
     if (!site->compileAndGo()) {
         if (site->returnTypes)
             site->returnTypes->addType(cx, TYPE_UNKNOWN);
         return;
     }
 
-    /* Treat the returned array as a new allocation site. */
-    TypeObject *object = site->getInitObject(cx, true);
-    if (!object)
-        return;
-
     if (!site->forceThisTypes(cx))
         return;
 
     if (site->returnTypes) {
         if (site->isNew)
             site->returnTypes->addType(cx, TYPE_UNKNOWN);
-        site->returnTypes->addType(cx, (jstype) object);
-    }
-
-    if (object->unknownProperties)
-        return;
-
-    /* Propagate elements of the 'this' array to the result. */
-    TypeSet *indexTypes = object->getProperty(cx, JSID_VOID, false);
-    if (!indexTypes)
-        return;
-    site->thisTypes->addGetProperty(cx, site->script, site->pc, indexTypes, JSID_VOID);
-
-    /* Ditto for all arguments to the call. */
-    for (size_t ind = 0; ind < site->argumentCount; ind++) {
-        site->argumentTypes[ind]->addGetProperty(cx, site->script, site->pc,
-                                                 indexTypes, JSID_VOID);
+        site->thisTypes->addSubset(cx, site->script, site->returnTypes);
     }
 }
 
 /* Handler for all higher order array builtins. */
 static void
 array_TypeExtra(JSContext *cx, JSTypeFunction *jsfun, JSTypeCallsite *jssite,
                 ArrayExtraMode mode)
 {