[INFER] Account for singletons with lazy types when testing type barriers, bug 680842.
authorBrian Hackett <bhackett1024@gmail.com>
Mon, 22 Aug 2011 15:25:53 -0700
changeset 76144 ffd0982472fa6bdaf7fb7ca4c291258acf935baf
parent 76143 8fe193e034cb542f1edf2de21e673432325449e1
child 76145 a30c64a27b4ae57764efd2b34086b3968ea17efe
push id3
push userfelipc@gmail.com
push dateFri, 30 Sep 2011 20:09:13 +0000
bugs680842
milestone9.0a1
[INFER] Account for singletons with lazy types when testing type barriers, bug 680842.
js/src/jit-test/tests/jaeger/bug680842.js
js/src/methodjit/BaseAssembler.h
js/src/methodjit/Compiler.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/jaeger/bug680842.js
@@ -0,0 +1,27 @@
+
+var gTestcases = new Array;
+var gTc = gTestcases;
+var msg = '';
+function TestCase(n, d, e, a) {
+  gTestcases[gTc++]=this;
+}
+TestCase.prototype.dump=function () {
+  lines = msg
+  for (var i=0; i<lines; ) {  }
+}
+function writeHeaderToLog( string ) {
+  for (var i = 0; ; i++) {
+    gTestcases[i].dump();
+  }
+}
+try {
+  TIME_2000 = 946684800000
+} catch (exc1) {}
+addNewTestCase( Date, 999 );
+try {
+  addNewTestCase( Date,TIME_2000 )( writeHeaderToLog( 2000,0,1,0,0,0,0), 0 );
+} catch (exc2) {}
+function addNewTestCase( DateCase, DateString, ResultArray ) {
+  new TestCase
+  Date.prototype=new TestCase
+}
--- a/js/src/methodjit/BaseAssembler.h
+++ b/js/src/methodjit/BaseAssembler.h
@@ -1189,29 +1189,36 @@ static const JSC::MacroAssembler::Regist
         if (count != 0) {
             if (!mismatches->append(testObject(Assembler::NotEqual, address)))
                 return false;
             Registers tempRegs(Registers::AvailRegs);
             RegisterID reg = tempRegs.takeAnyReg().reg();
 
             loadPayload(address, reg);
 
+            Jump notSingleton = branchTest32(Assembler::Zero,
+                                             Address(reg, offsetof(JSObject, flags)),
+                                             Imm32(JSObject::SINGLETON_TYPE));
+
             for (unsigned i = 0; i < count; i++) {
-                JSObject *object = types->getSingleObject(i);
-                if (object) {
+                if (JSObject *object = types->getSingleObject(i)) {
                     if (!matches.append(branchPtr(Assembler::Equal, reg, ImmPtr(object))))
                         return false;
                 }
             }
 
+            if (!mismatches->append(jump()))
+                return false;
+
+            notSingleton.linkTo(label(), this);
+
             loadPtr(Address(reg, JSObject::offsetOfType()), reg);
 
             for (unsigned i = 0; i < count; i++) {
-                types::TypeObject *object = types->getTypeObject(i);
-                if (object) {
+                if (types::TypeObject *object = types->getTypeObject(i)) {
                     if (!matches.append(branchPtr(Assembler::Equal, reg, ImmPtr(object))))
                         return false;
                 }
             }
         }
 
         if (!mismatches->append(jump()))
             return false;
--- a/js/src/methodjit/Compiler.cpp
+++ b/js/src/methodjit/Compiler.cpp
@@ -7230,23 +7230,40 @@ mjit::Compiler::addTypeTest(types::TypeS
         matches.append(masm.testObject(Assembler::Equal, typeReg));
     else
         count = types->getObjectCount();
 
     if (count != 0) {
         Jump notObject = masm.testObject(Assembler::NotEqual, typeReg);
         Address typeAddress(dataReg, JSObject::offsetOfType());
 
+        /*
+         * Test for a singleton objects first. If singletons have lazy types
+         * then they may share their gctype() with another type object in the
+         * observed set and we can get a spurious match.
+         */
+        Jump notSingleton = masm.branchTest32(Assembler::Zero,
+                                              Address(dataReg, offsetof(JSObject, flags)),
+                                              Imm32(JSObject::SINGLETON_TYPE));
+
         for (unsigned i = 0; i < count; i++) {
             if (JSObject *object = types->getSingleObject(i))
                 matches.append(masm.branchPtr(Assembler::Equal, dataReg, ImmPtr(object)));
-            else if (types::TypeObject *object = types->getTypeObject(i))
+        }
+
+        Jump singletonMismatch = masm.jump();
+
+        notSingleton.linkTo(masm.label(), &masm);
+
+        for (unsigned i = 0; i < count; i++) {
+            if (types::TypeObject *object = types->getTypeObject(i))
                 matches.append(masm.branchPtr(Assembler::Equal, typeAddress, ImmPtr(object)));
         }
 
+        singletonMismatch.linkTo(masm.label(), &masm);
         notObject.linkTo(masm.label(), &masm);
     }
 
     Jump mismatch = masm.jump();
 
     for (unsigned i = 0; i < matches.length(); i++)
         matches[i].linkTo(masm.label(), &masm);