[INFER] Sync 'this' fe when testing for primitive return in functions which return a value with unknown type, bug 678141.
authorBrian Hackett <bhackett1024@gmail.com>
Fri, 12 Aug 2011 09:18:48 -0700
changeset 77431 409b62513ac6ad4a1c2287376fb59ead21fe7550
parent 77430 0a8195cb7590cc4c803adced8fea4c1f99b34c03
child 77432 07361922fd67f3678cd65f29e9369c54f552a2f7
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)
bugs678141
milestone8.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] Sync 'this' fe when testing for primitive return in functions which return a value with unknown type, bug 678141.
js/src/jit-test/tests/jaeger/bug678141.js
js/src/methodjit/Compiler.cpp
js/src/methodjit/FrameState-inl.h
js/src/methodjit/FrameState.h
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/jaeger/bug678141.js
@@ -0,0 +1,10 @@
+
+c = {}.__proto__[1] = 3;
+(function() {
+    function b(a) {
+        return a
+    }
+    for each(let z in [{}]) {
+        print(new b(z))
+    }
+})()
--- a/js/src/methodjit/Compiler.cpp
+++ b/js/src/methodjit/Compiler.cpp
@@ -779,39 +779,39 @@ mjit::Compiler::generatePrologue()
                                                    StackFrame::OVERFLOW_ARGS |
                                                    StackFrame::HAS_ARGS_OBJ));
             masm.storePtr(ImmPtr((void *) script->function()->nargs),
                           Address(JSFrameReg, StackFrame::offsetOfArgs()));
             hasArgs.linkTo(masm.label(), &masm);
         }
     }
 
+    if (cx->typeInferenceEnabled()) {
+#ifdef DEBUG
+        if (script->hasFunction) {
+            prepareStubCall(Uses(0));
+            INLINE_STUBCALL(stubs::AssertArgumentTypes, REJOIN_NONE);
+        }
+#endif
+        ensureDoubleArguments();
+    }
+
     if (isConstructing) {
         if (!constructThis())
             return Compile_Error;
     }
 
     if (debugMode()) {
         prepareStubCall(Uses(0));
         INLINE_STUBCALL(stubs::ScriptDebugPrologue, REJOIN_RESUME);
     } else if (Probes::callTrackingActive(cx)) {
         prepareStubCall(Uses(0));
         INLINE_STUBCALL(stubs::ScriptProbeOnlyPrologue, REJOIN_RESUME);
     }
 
-    if (cx->typeInferenceEnabled()) {
-#ifdef DEBUG
-        if (script->hasFunction) {
-            prepareStubCall(Uses(0));
-            INLINE_STUBCALL(stubs::AssertArgumentTypes, REJOIN_NONE);
-        }
-#endif
-        ensureDoubleArguments();
-    }
-
     recompileCheckHelper();
 
     if (outerScript->pcCounters) {
         size_t length = ssa.frameLength(ssa.numFrames() - 1);
         pcLengths = (PCLengthEntry *) cx->calloc_(sizeof(pcLengths[0]) * length);
         if (!pcLengths)
             return Compile_Error;
     }
@@ -2943,17 +2943,19 @@ mjit::Compiler::fixPrimitiveReturn(Assem
 
     // If the type is known to be an object, just load the return value as normal.
     if (fe && fe->isTypeKnown() && fe->getKnownType() == JSVAL_TYPE_OBJECT) {
         loadReturnValue(masm, fe);
         return;
     }
 
     // There's a return value, and its type is unknown. Test the type and load
-    // |thisv| if necessary.
+    // |thisv| if necessary. Sync the 'this' entry before doing so, as it may
+    // be stored in registers if we constructed it inline.
+    frame.syncThis();
     loadReturnValue(masm, fe);
     Jump j = masm->testObject(Assembler::Equal, JSReturnReg_Type);
     masm->loadValueAsComponents(thisv, JSReturnReg_Type, JSReturnReg_Data);
     j.linkTo(masm->label(), masm);
 }
 
 // Loads the return value into the scripted ABI register pair, such that JS
 // semantics in constructors are preserved.
--- a/js/src/methodjit/FrameState-inl.h
+++ b/js/src/methodjit/FrameState-inl.h
@@ -1310,34 +1310,37 @@ FrameState::pushThis()
 }
 
 void
 FrameState::learnThisIsObject(bool unsync)
 {
     // If the 'this' object is a copy, this must be an inline frame, in which
     // case we will trigger recompilation if the 'this' entry isn't actually
     // an object (thus, it is OK to modify the backing directly).
-    FrameEntry *fe = a->this_;
-    if (!fe->isTracked())
-        addToTracker(fe);
+    FrameEntry *fe = getThis();
     if (fe->isCopy())
         fe = fe->copyOf();
     learnType(fe, JSVAL_TYPE_OBJECT, unsync);
 }
 
 void
 FrameState::setThis(RegisterID reg)
 {
-    FrameEntry *fe = a->this_;
-    if (!fe->isTracked())
-        addToTracker(fe);
+    FrameEntry *fe = getThis();
     JS_ASSERT(!fe->isCopy());
     learnType(fe, JSVAL_TYPE_OBJECT, reg);
 }
 
+void
+FrameState::syncThis()
+{
+    FrameEntry *fe = getThis();
+    syncFe(fe);
+}
+
 inline void
 FrameState::leaveBlock(uint32 n)
 {
     popn(n);
 }
 
 inline void
 FrameState::enterBlock(uint32 n)
--- a/js/src/methodjit/FrameState.h
+++ b/js/src/methodjit/FrameState.h
@@ -388,16 +388,17 @@ class FrameState
     // Pushes a copy of a slot (formal argument, local variable, or stack slot)
     // onto the operation stack.
     void pushLocal(uint32 n);
     void pushArg(uint32 n);
     void pushCallee();
     void pushThis();
     void pushCopyOf(FrameEntry *fe);
     inline void setThis(RegisterID reg);
+    inline void syncThis();
     inline void learnThisIsObject(bool unsync = true);
 
     inline FrameEntry *getStack(uint32 slot);
     inline FrameEntry *getLocal(uint32 slot);
     inline FrameEntry *getArg(uint32 slot);
     inline FrameEntry *getSlotEntry(uint32 slot);
 
     /*