[INFER] Fix for making dense array type objects when Array.prototype has unknown properties, bug 617558.
authorBrian Hackett <bhackett1024@gmail.com>
Wed, 08 Dec 2010 09:38:38 -0800
changeset 74648 0b73d74d343d71fb48d0083719a1e9668feb2f88
parent 74647 040fd88a48199bcafcafee8672e5f76752dd99ac
child 74649 6f89a3ddb09e70af3a5f272abed889199c4e2d6b
push id2
push userbsmedberg@mozilla.com
push dateFri, 19 Aug 2011 14:38:13 +0000
bugs617558
milestone2.0b8pre
[INFER] Fix for making dense array type objects when Array.prototype has unknown properties, bug 617558.
js/src/jit-test/tests/jaeger/bug617558.js
js/src/jsinfer.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/jaeger/bug617558.js
@@ -0,0 +1,7 @@
+
+Array.prototype.__proto__ = Function.prototype;
+var x = [1,2,3];
+x[0];
+
+[].__proto__.foo = true;
+eval("[]");
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -157,17 +157,17 @@ static bool InferSpewActive(SpewChannel 
 
 #ifdef DEBUG
 
 const char *
 TypeIdStringImpl(jsid id)
 {
     if (JSID_IS_VOID(id))
         return "(index)";
-    static char bufs[100][4];
+    static char bufs[4][100];
     static unsigned which = 0;
     which = (which + 1) & 3;
     PutEscapedString(bufs[which], 100, JSID_TO_STRING(id), 0);
     return bufs[which];
 }
 
 const char *
 TypeObjectString(TypeObject *object)
@@ -1660,40 +1660,31 @@ TypeCompartment::dynamicAssign(JSContext
             obj = obj->getParent();
         analyze::Script *script = obj->getCallObjCalleeFunction()->script()->analysis;
         JS_ASSERT(!script->isEval());
 
         assignTypes = script->getVariable(cx, id);
     } else {
         id = MakeTypeId(id);
 
-        if (!JSID_IS_VOID(id) && id != id_prototype(cx) && id != id___proto__(cx)) {
-            /*
-             * Monitor any object which has had dynamic assignments to string properties,
-             * to avoid making large numbers of type properties for hashmap-style objects.
-             * :FIXME: this is too aggressive for things like prototype library initialization.
-             */
+        /*
+         * Mark as unknown any object which has had dynamic assignments to __proto__,
+         * and any object which has had dynamic assignments to string properties through SETELEM.
+         * The latter avoids making large numbers of type properties for hashmap-style objects.
+         * :FIXME: this is too aggressive for things like prototype library initialization.
+         */
+        JSOp op = JSOp(*cx->regs->pc);
+        if (id == id___proto__(cx) || (op == JSOP_SETELEM && !JSID_IS_VOID(id))) {
             cx->markTypeObjectUnknownProperties(object);
             if (hasPendingRecompiles())
                 processPendingRecompiles(cx);
             return;
         }
 
         assignTypes = object->getProperty(cx, id, true);
-
-        /*
-         * Writing the __proto__ property marks the object's type as unknown.
-         * Can't analyze objects with a mutable prototype.
-         */
-        if (id == id___proto__(cx)) {
-            cx->markTypeObjectUnknownProperties(object);
-            if (hasPendingRecompiles())
-                processPendingRecompiles(cx);
-            return;
-        }
     }
 
     if (assignTypes->hasType(rvtype))
         return;
 
     InferSpew(ISpewDynamic, "MonitorAssign: %s %s: %s",
               TypeIdString(object->name), TypeIdString(id), TypeString(rvtype));
     addDynamicType(cx, assignTypes, rvtype);
@@ -1841,20 +1832,20 @@ TypeObject::TypeObject(JSContext *cx, JS
     : name(name), isFunction(false), propertySet(NULL), propertyCount(0),
       prototype(prototype), instanceList(NULL), instanceNext(NULL), newObject(NULL),
       pool(pool), next(NULL), unknownProperties(false),
       isDenseArray(false), isPackedArray(false), possiblePackedArray(false)
 {
     InferSpew(ISpewOps, "newObject: %s", TypeIdString(name));
 
     if (prototype) {
-        if (prototype == cx->compartment->types.fixedTypeObjects[TYPE_OBJECT_ARRAY_PROTOTYPE])
-            isDenseArray = isPackedArray = true;
         if (prototype->unknownProperties)
             unknownProperties = true;
+        else if (prototype == cx->compartment->types.fixedTypeObjects[TYPE_OBJECT_ARRAY_PROTOTYPE])
+            isDenseArray = isPackedArray = true;
         instanceNext = prototype->instanceList;
         prototype->instanceList = this;
     }
 }
 
 void
 TypeObject::storeToInstances(JSContext *cx, Property *base)
 {