[INFER] Remove hack for telling apart fastcalls and native calls when recompiling, bug 619433.
authorBrian Hackett <bhackett1024@gmail.com>
Mon, 07 Mar 2011 16:26:52 -0800
changeset 74727 9b576fe9baede54e1a1374c50b8cf9f772cf57b5
parent 74726 1dab51bde3f124d8503acf14c7b9320abf3bca8d
child 74728 0edb03210dacc201f7a6e5fecf1a0a9935fe22b6
push id2
push userbsmedberg@mozilla.com
push dateFri, 19 Aug 2011 14:38:13 +0000
bugs619433
milestone2.0b12pre
[INFER] Remove hack for telling apart fastcalls and native calls when recompiling, bug 619433.
js/src/methodjit/MethodJIT.h
js/src/methodjit/MonoIC.cpp
js/src/methodjit/Retcon.cpp
--- a/js/src/methodjit/MethodJIT.h
+++ b/js/src/methodjit/MethodJIT.h
@@ -73,16 +73,23 @@ struct VMFrame
 
     VMFrame      *previous;
     void         *scratch;
     JSFrameRegs  regs;
     JSContext    *cx;
     Value        *stackLimit;
     JSStackFrame *entryfp;
 
+/*
+ * Value stored in the 'scratch' field when making a native call. This is used
+ * by the recompiler and this value must not be written in other cases
+ * (i.e. scratch must be used to store a pointer, not an integer.
+ */
+#define NATIVE_CALL_SCRATCH_VALUE (void *) 0x1
+
 #if defined(JS_CPU_X86)
     void *savedEBX;
     void *savedEDI;
     void *savedESI;
     void *savedEBP;
     void *savedEIP;
 
 # ifdef JS_NO_FASTCALL
--- a/js/src/methodjit/MonoIC.cpp
+++ b/js/src/methodjit/MonoIC.cpp
@@ -897,37 +897,38 @@ class CallCompiler : public BaseCompiler
         if (callingNew) {
             Value v;
             v.setMagicWithObjectOrNullPayload(NULL);
             masm.storeValue(v, Address(vpReg, sizeof(Value)));
         }
 
         if (cx->typeInferenceEnabled()) {
             /*
-             * Look under the ABI abstraction and NULL out the slot used for the
-             * return address in a FASTCALL. This is seriously nasty but we need it
-             * to distinguish fast calls from native calls should we trigger a
-             * recompilation inside the native.
+             * Write the NATIVE_SCRATCH_VALUE to the 'scratch' field of the
+             * VMFrame, so the recompiler can tell this was a native call.
+             * Natives use a different stack address to store the return
+             * value than FASTCALLs, and without additional information we
+             * cannot tell which one is active on a VMFrame.
              */
-#if defined(JS_CPU_X86) && !defined(JS_NO_FASTCALL)
-            masm.storePtr(ImmPtr(NULL), FrameAddress(-4));
-#else
-            JS_NOT_REACHED("FIXME");
-#endif
+            masm.storePtr(ImmPtr(NATIVE_CALL_SCRATCH_VALUE),
+                          FrameAddress(offsetof(VMFrame, scratch)));
         }
 
         masm.setupABICall(Registers::NormalCall, 3);
         masm.storeArg(2, vpReg);
         if (ic.frameSize.isStatic())
             masm.storeArg(1, Imm32(ic.frameSize.staticArgc()));
         else
             masm.storeArg(1, argcReg.reg());
         masm.storeArg(0, cxReg);
         masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, fun->u.n.native), false);
 
+        if (cx->typeInferenceEnabled())
+            masm.storePtr(ImmPtr(NULL), FrameAddress(offsetof(VMFrame, scratch)));
+
         Jump hasException = masm.branchTest32(Assembler::Zero, Registers::ReturnReg,
                                               Registers::ReturnReg);
         
 
         Jump done = masm.jump();
 
         /* Move JaegerThrowpoline into register for very far jump on x64. */
         hasException.linkTo(masm.label(), &masm);
--- a/js/src/methodjit/Retcon.cpp
+++ b/js/src/methodjit/Retcon.cpp
@@ -283,38 +283,32 @@ Recompiler::recompile()
             } else if (script->jitNormal && script->jitNormal->isValidCode(*addr)) {
                 if (!normalPatches.append(findPatch(script->jitNormal, addr)))
                     return false;
             }
 
             next = fp;
         }
 
-        // These return address checks will not pass when we were called from a native.
-        // Native calls are not through the FASTCALL ABI, and use a different return
-        // address from f->returnAddressLocation(). We make sure when calling a native that
-        // the FASTCALL return address is overwritten with NULL, and that it won't
-        // be used by the native itself. Otherwise we will read an uninitialized
-        // value here (probably the return address for a previous FASTCALL).
         void **addr = f->returnAddressLocation();
-        if (script->jitCtor && script->jitCtor->isValidCode(*addr)) {
-            if (!ctorPatches.append(findPatch(script->jitCtor, addr)))
-                return false;
-        } else if (script->jitNormal && script->jitNormal->isValidCode(*addr)) {
-            if (!normalPatches.append(findPatch(script->jitNormal, addr)))
-                return false;
-        } else if (f->fp()->script() == script) {
+        if (f->fp()->script() == script && f->scratch == NATIVE_CALL_SCRATCH_VALUE) {
             // Native call.
             if (f->fp()->isConstructing()) {
                 if (!ctorNatives.append(stealNative(script->jitCtor, f->fp()->pc(cx, NULL))))
                     return false;
             } else {
                 if (!normalNatives.append(stealNative(script->jitNormal, f->fp()->pc(cx, NULL))))
                     return false;
             }
+        } else if (script->jitCtor && script->jitCtor->isValidCode(*addr)) {
+            if (!ctorPatches.append(findPatch(script->jitCtor, addr)))
+                return false;
+        } else if (script->jitNormal && script->jitNormal->isValidCode(*addr)) {
+            if (!normalPatches.append(findPatch(script->jitNormal, addr)))
+                return false;
         }
     }
 
     Vector<CallSite> normalSites(cx);
     Vector<CallSite> ctorSites(cx);
     uint32 normalRecompilations;
     uint32 ctorRecompilations;