[INFER] Inline typed array access if the object may be undefined, bug 670885. r=bhackett
authorJan de Mooij <jandemooij@gmail.com>
Wed, 13 Jul 2011 15:13:04 +0200
changeset 76035 8e009db2de15ed820e4a7c45346eeae3fb0f1a07
parent 76034 b67c4240345870b7f65ba403a29468ab81ec59a5
child 76036 d7d452b4b90bcbd6321b02c397da4be876475cb9
push id3
push userfelipc@gmail.com
push dateFri, 30 Sep 2011 20:09:13 +0000
reviewersbhackett
bugs670885
milestone8.0a1
[INFER] Inline typed array access if the object may be undefined, bug 670885. r=bhackett
js/src/jit-test/tests/basic/testTypedArrayMaybeUndefined.js
js/src/jit-test/tests/jaeger/bug670885.js
js/src/methodjit/FastOps.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/testTypedArrayMaybeUndefined.js
@@ -0,0 +1,46 @@
+// Testing GETELEM and SETELEM on a typed array where the
+// type set of the object may include undefined or other
+// primitive types.
+
+// Argument x has type {void, double, Uint16Array}.
+function testSet(x) {
+    var y = 0;
+    for (var i=0; i<40; i++) {
+        x[i] = 3;
+    }
+    return x[10];
+}
+
+// Argument x has type {void, int32, Uint16Array}.
+function testGet(x) {
+    var y = 0;
+    for (var i=0; i<40; i++) {
+        y += x[i];
+    }
+    return y;
+}
+
+var arr = new Uint16Array(40);
+assertEq(testSet(arr), 3);
+try {
+    testSet(undefined);
+} catch(e) {
+    assertEq(e instanceof TypeError, true);
+}
+try {
+    testSet(4.5);
+} catch(e) {
+    assertEq(e instanceof TypeError, true);
+}
+
+assertEq(testGet(arr), 120);
+try {
+    testGet(undefined);
+} catch(e) {
+    assertEq(e instanceof TypeError, true);
+}
+try {
+    testGet(12345);
+} catch(e) {
+    assertEq(e instanceof TypeError, true);
+}
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/jaeger/bug670885.js
@@ -0,0 +1,16 @@
+// arr is an Int8Array, then changes to Int16Array.
+// This should trigger recompilation of f.
+var arr = new Int8Array(100);
+var arr16 = new Int16Array(100);
+arr16[2] = 12345;
+function f(a) {
+    var x;
+    for(var i=0; i<30; i++) {
+        x = a[2];
+    }
+    return x;
+}
+assertEq(f(arr), 0);
+assertEq(f(arr), 0);
+this.arr = arr16;
+assertEq(f(arr), 12345);
--- a/js/src/methodjit/FastOps.cpp
+++ b/js/src/methodjit/FastOps.cpp
@@ -1444,25 +1444,26 @@ mjit::Compiler::jsop_setelem(bool popGua
         if (!types->hasObjectFlags(cx, types::OBJECT_FLAG_NON_DENSE_ARRAY) &&
             !arrayPrototypeHasIndexedProperty()) {
             // Inline dense array path.
             jsop_setelem_dense();
             return true;
         }
 
 #ifdef JS_METHODJIT_TYPED_ARRAY
-        if (!types->hasObjectFlags(cx, types::OBJECT_FLAG_NON_TYPED_ARRAY) &&
-            (value->mightBeType(JSVAL_TYPE_INT32) || value->mightBeType(JSVAL_TYPE_DOUBLE))) {
+        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.
-            if (types::TypeObject *objType = types->getSingleObject()) {
-                int atype = objType->proto->getClass() - TypedArray::slowClasses;
-                JS_ASSERT(atype >= 0 && atype < TypedArray::TYPE_MAX);
-                jsop_setelem_typed(atype);
-                return true;
-            }
+            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;
         }
 #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
@@ -1965,24 +1966,25 @@ 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->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.
-            if (types::TypeObject *objType = types->getSingleObject()) {
-                int atype = objType->proto->getClass() - TypedArray::slowClasses;
-                JS_ASSERT(atype >= 0 && atype < TypedArray::TYPE_MAX);
-                jsop_getelem_typed(atype);
-                return true;
-            }
+            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;
         }
 #endif
     }
 
     frame.forgetMismatchedObject(obj);
 
     GetElementICInfo ic = GetElementICInfo(JSOp(*PC));