[INFER] Compiler types should reflect inferred types for JSOP_THIS in scripts which have not executed, bug 684084.
authorBrian Hackett <bhackett1024@gmail.com>
Sun, 04 Sep 2011 13:33:04 -0700
changeset 77890 77e9502bd20f3c61a639f6533535a4f763b8d792
parent 77889 8385e0145b8dbcc44b5be0baaf17a05e11af0320
child 77891 aa9f4b139e389262a9e3fcd0583aefe62b20b986
push id78
push userclegnitto@mozilla.com
push dateFri, 16 Dec 2011 17:32:24 +0000
treeherdermozilla-release@79d24e644fdd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs684084
milestone9.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
[INFER] Compiler types should reflect inferred types for JSOP_THIS in scripts which have not executed, bug 684084.
js/src/jit-test/tests/jaeger/bug684084.js
js/src/methodjit/Compiler.cpp
js/src/methodjit/StubCalls.cpp
js/src/methodjit/StubCalls.h
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/jaeger/bug684084.js
@@ -0,0 +1,7 @@
+// |jit-test| error: TypeError
+function Integer( value, exception ) {
+  try {  } catch ( e ) {  }
+  new (value = this)( this.value );
+  if ( Math.floor(value) != value || isNaN(value) ) {  }
+}
+new Integer( 3, false );
--- a/js/src/methodjit/Compiler.cpp
+++ b/js/src/methodjit/Compiler.cpp
@@ -2735,19 +2735,18 @@ mjit::Compiler::generateMethod()
           }
           END_CASE(JSOP_DEBUGGER)
 
           BEGIN_CASE(JSOP_UNBRAND)
             jsop_unbrand();
           END_CASE(JSOP_UNBRAND)
 
           BEGIN_CASE(JSOP_UNBRANDTHIS)
-            jsop_this();
-            jsop_unbrand();
-            frame.pop();
+            prepareStubCall(Uses(1));
+            INLINE_STUBCALL(stubs::UnbrandThis, REJOIN_FALLTHROUGH);
           END_CASE(JSOP_UNBRANDTHIS)
 
           BEGIN_CASE(JSOP_GETGLOBAL)
           BEGIN_CASE(JSOP_CALLGLOBAL)
             jsop_getglobal(GET_SLOTNO(PC));
             if (op == JSOP_CALLGLOBAL)
                 frame.push(UndefinedValue());
           END_CASE(JSOP_GETGLOBAL)
@@ -5572,16 +5571,26 @@ mjit::Compiler::jsop_this()
             if (type != JSVAL_TYPE_OBJECT) {
                 Jump notObj = frame.testObject(Assembler::NotEqual, thisFe);
                 stubcc.linkExit(notObj, Uses(1));
                 stubcc.leave();
                 OOL_STUBCALL(stubs::This, REJOIN_FALLTHROUGH);
                 stubcc.rejoin(Changes(1));
             }
 
+            /*
+             * Watch out for an obscure case where we don't know we are pushing
+             * an object: the script has not yet had a 'this' value assigned,
+             * so no pushed 'this' type has been inferred. Don't mark the type
+             * as known in this case, preserving the invariant that compiler
+             * types reflect inferred types.
+             */
+            if (cx->typeInferenceEnabled() && knownPushedType(0) != JSVAL_TYPE_OBJECT)
+                return;
+
             // Now we know that |this| is an object.
             frame.pop();
             frame.learnThisIsObject(type != JSVAL_TYPE_OBJECT);
             frame.pushThis();
         }
 
         JS_ASSERT(thisFe->isType(JSVAL_TYPE_OBJECT));
     }
--- a/js/src/methodjit/StubCalls.cpp
+++ b/js/src/methodjit/StubCalls.cpp
@@ -2191,16 +2191,29 @@ stubs::Unbrand(VMFrame &f)
     if (!thisv.isObject())
         return;
     JSObject *obj = &thisv.toObject();
     if (obj->isNative())
         obj->unbrand(f.cx);
 }
 
 void JS_FASTCALL
+stubs::UnbrandThis(VMFrame &f)
+{
+    if (!ComputeThis(f.cx, f.fp()))
+        THROW();
+    Value &thisv = f.fp()->thisValue();
+    if (!thisv.isObject())
+        return;
+    JSObject *obj = &thisv.toObject();
+    if (obj->isNative())
+        obj->unbrand(f.cx);
+}
+
+void JS_FASTCALL
 stubs::Pos(VMFrame &f)
 {
     if (!ToNumber(f.cx, &f.regs.sp[-1]))
         THROW();
     if (!f.regs.sp[-1].isInt32())
         TypeScript::MonitorOverflow(f.cx, f.script(), f.pc());
 }
 
--- a/js/src/methodjit/StubCalls.h
+++ b/js/src/methodjit/StubCalls.h
@@ -195,16 +195,17 @@ JSBool JS_FASTCALL IterMore(VMFrame &f);
 void JS_FASTCALL EndIter(VMFrame &f);
 
 JSBool JS_FASTCALL ValueToBoolean(VMFrame &f);
 JSString * JS_FASTCALL TypeOf(VMFrame &f);
 JSBool JS_FASTCALL InstanceOf(VMFrame &f);
 void JS_FASTCALL FastInstanceOf(VMFrame &f);
 void JS_FASTCALL ArgCnt(VMFrame &f);
 void JS_FASTCALL Unbrand(VMFrame &f);
+void JS_FASTCALL UnbrandThis(VMFrame &f);
 
 /*
  * Helper for triggering recompilation should a name read miss a type barrier,
  * produce undefined or -0.
  */
 void JS_FASTCALL TypeBarrierHelper(VMFrame &f, uint32 which);
 void JS_FASTCALL TypeBarrierReturn(VMFrame &f, Value *vp);
 void JS_FASTCALL NegZeroHelper(VMFrame &f);