[INFER] Enable typed array paths if the type set contains multiple objects with the same array type, bug 670885. r=bhackett
authorJan de Mooij <jandemooij@gmail.com>
Thu, 14 Jul 2011 16:42:37 +0200
changeset 76036 d7d452b4b90bcbd6321b02c397da4be876475cb9
parent 76035 8e009db2de15ed820e4a7c45346eeae3fb0f1a07
child 76041 f2ca662099dac226136749631b5f7f0448bbe7d8
push id3
push userfelipc@gmail.com
push dateFri, 30 Sep 2011 20:09:13 +0000
reviewersbhackett
bugs670885
milestone8.0a1
[INFER] Enable typed array paths if the type set contains multiple objects with the same array type, bug 670885. r=bhackett
js/src/jsinfer.cpp
js/src/jsinfer.h
js/src/methodjit/FastOps.cpp
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -1844,16 +1844,54 @@ TypeSet::knownNonEmpty(JSContext *cx)
         return true;
 
     add(cx, ArenaNew<TypeConstraintFreeze>(cx->compartment->pool,
                                            cx->compartment->types.compiledScript), false);
 
     return false;
 }
 
+int
+TypeSet::getTypedArrayType(JSContext *cx)
+{
+    int arrayType = TypedArray::TYPE_MAX;
+    unsigned count = getObjectCount();
+
+    for (unsigned i = 0; i < count; i++) {
+        TypeObject *object = getObject(i);
+        if (!object)
+            continue;
+
+        JS_ASSERT(!object->hasAnyFlags(OBJECT_FLAG_NON_TYPED_ARRAY));
+        int objArrayType = object->proto->getClass() - TypedArray::slowClasses;
+        JS_ASSERT(objArrayType >= 0 && objArrayType < TypedArray::TYPE_MAX);
+
+        /*
+         * Set arrayType to the type of the first array. Return if there is an array
+         * of another type.
+         */
+        if (arrayType == TypedArray::TYPE_MAX)
+            arrayType = objArrayType;
+        else if (arrayType != objArrayType)
+            return TypedArray::TYPE_MAX;
+    }
+
+    /*
+     * Assume the caller checked that OBJECT_FLAG_NON_TYPED_ARRAY is not set.
+     * This means the set contains at least one object because sets with no
+     * objects have all object flags.
+     */
+    JS_ASSERT(arrayType != TypedArray::TYPE_MAX);
+
+    /* Recompile when another typed array is added to this set. */
+    addFreeze(cx);
+
+    return arrayType;
+}
+
 JSObject *
 TypeSet::getSingleton(JSContext *cx)
 {
     if (baseFlags() != 0 || objectCount != 1)
         return NULL;
 
     TypeObject *object = (TypeObject *) objectSet;
     if (!object->singleton)
--- a/js/src/jsinfer.h
+++ b/js/src/jsinfer.h
@@ -428,16 +428,22 @@ class TypeSet
     bool hasUnknownProperties(JSContext *cx);
 
     /* Get whether this type set is non-empty. */
     bool knownNonEmpty(JSContext *cx);
 
     /* Get the single value which can appear in this type set, otherwise NULL. */
     JSObject *getSingleton(JSContext *cx);
 
+    /*
+     * Get the typed array type of all objects in this set. Returns
+     * TypedArray::TYPE_MAX if the set contains different array types.
+     */
+    int getTypedArrayType(JSContext *cx);
+
     /* Mark all current and future types in this set as pushed by script/pc. */
     void pushAllTypes(JSContext *cx, JSScript *script, jsbytecode *pc);
 
     /*
      * Clone (possibly NULL) source onto target; if any new types are added to
      * source in the future, the script will be recompiled.
      */
     static void Clone(JSContext *cx, TypeSet *source, ClonedTypeSet *target);
--- a/js/src/methodjit/FastOps.cpp
+++ b/js/src/methodjit/FastOps.cpp
@@ -1445,25 +1445,23 @@ mjit::Compiler::jsop_setelem(bool popGua
             !arrayPrototypeHasIndexedProperty()) {
             // Inline dense array path.
             jsop_setelem_dense();
             return true;
         }
 
 #ifdef JS_METHODJIT_TYPED_ARRAY
         if ((value->mightBeType(JSVAL_TYPE_INT32) || value->mightBeType(JSVAL_TYPE_DOUBLE)) &&
-            !types->hasObjectFlags(cx, types::OBJECT_FLAG_NON_TYPED_ARRAY) &&
-            types->getObjectCount() == 1) {
-            // Inline typed array path. Look at the proto to determine the typed array type.
-            types::TypeObject *object = types->getObject(0);
-            types->addFreeze(cx);
-            int atype = object->proto->getClass() - TypedArray::slowClasses;
-            JS_ASSERT(atype >= 0 && atype < TypedArray::TYPE_MAX);
-            jsop_setelem_typed(atype);
-            return true;
+            !types->hasObjectFlags(cx, types::OBJECT_FLAG_NON_TYPED_ARRAY)) {
+            // Inline typed array path.
+            int atype = types->getTypedArrayType(cx);
+            if (atype != TypedArray::TYPE_MAX) {
+                jsop_setelem_typed(atype);
+                return true;
+            }
         }
 #endif
     }
 
     SetElementICInfo ic = SetElementICInfo(JSOp(*PC));
 
     // One by one, check if the most important stack entries have registers,
     // and if so, pin them. This is to avoid spilling and reloading from the
@@ -1966,25 +1964,23 @@ mjit::Compiler::jsop_getelem(bool isCall
             // Inline dense array path.
             bool packed = !types->hasObjectFlags(cx, types::OBJECT_FLAG_NON_PACKED_ARRAY);
             jsop_getelem_dense(packed);
             return true;
         }
 
 #ifdef JS_METHODJIT_TYPED_ARRAY
         if (obj->mightBeType(JSVAL_TYPE_OBJECT) &&
-            !types->hasObjectFlags(cx, types::OBJECT_FLAG_NON_TYPED_ARRAY) &&
-            types->getObjectCount() == 1) {
-            // Inline typed array path. Look at the proto to determine the typed array type.
-            types::TypeObject *object = types->getObject(0);
-            types->addFreeze(cx);
-            int atype = object->proto->getClass() - TypedArray::slowClasses;
-            JS_ASSERT(atype >= 0 && atype < TypedArray::TYPE_MAX);
-            jsop_getelem_typed(atype);
-            return true;
+            !types->hasObjectFlags(cx, types::OBJECT_FLAG_NON_TYPED_ARRAY)) {
+            // Inline typed array path.
+            int atype = types->getTypedArrayType(cx);
+            if (atype != TypedArray::TYPE_MAX) {
+                jsop_getelem_typed(atype);
+                return true;
+            }
         }
 #endif
     }
 
     frame.forgetMismatchedObject(obj);
 
     GetElementICInfo ic = GetElementICInfo(JSOp(*PC));