Bug 759289 - Use JM for functions called from a JM IC. r=dvander
authorJan de Mooij <jdemooij@mozilla.com>
Fri, 01 Jun 2012 14:39:23 +0200
changeset 113134 c4ba8fc5a1d0c52f91da1e6dccd119212de02edc
parent 113133 16141b0a3d124b4312a014b20924b33b9cefae6f
child 113135 56ba58a77e8f11cff724a9ddb50839a0c5663e2c
push id239
push userakeybl@mozilla.com
push dateThu, 03 Jan 2013 21:54:43 +0000
treeherdermozilla-release@3a7b66445659 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdvander
bugs759289
milestone15.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
Bug 759289 - Use JM for functions called from a JM IC. r=dvander
js/src/jsinterp.cpp
js/src/methodjit/Compiler.cpp
js/src/methodjit/InvokeHelpers.cpp
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -2590,34 +2590,16 @@ BEGIN_CASE(JSOP_FUNCALL)
 
     if (!regs.fp()->functionPrologue(cx))
         goto error;
 
     RESET_USE_METHODJIT();
 
     bool newType = cx->typeInferenceEnabled() && UseNewType(cx, script, regs.pc);
 
-#ifdef JS_METHODJIT
-    if (!newType && cx->methodJitEnabled) {
-        /* Try to ensure methods are method JIT'd.  */
-        mjit::CompileStatus status = mjit::CanMethodJIT(cx, script, script->code,
-                                                        construct,
-                                                        mjit::CompileRequest_Interpreter);
-        if (status == mjit::Compile_Error)
-            goto error;
-        if (status == mjit::Compile_Okay) {
-            mjit::JaegerStatus status = mjit::JaegerShot(cx, true);
-            CHECK_PARTIAL_METHODJIT(status);
-            interpReturnOK = mjit::JaegerStatusToSuccess(status);
-            CHECK_INTERRUPT_HANDLER();
-            goto jit_return;
-        }
-    }
-#endif
-
 #ifdef JS_ION
     if (!newType && ion::IsEnabled(cx)) {
         ion::MethodStatus status = ion::CanEnter(cx, script, regs.fp(), newType);
         if (status == ion::Method_Error)
             goto error;
         if (status == ion::Method_Compiled) {
             ion::IonExecStatus exec = ion::Cannon(cx, regs.fp());
             CHECK_INTERRUPT_HANDLER();
@@ -2627,16 +2609,34 @@ BEGIN_CASE(JSOP_FUNCALL)
                 DO_OP();
             }
             interpReturnOK = (exec == ion::IonExec_Error) ? false : true;
             goto jit_return;
         }
     }
 #endif
 
+#ifdef JS_METHODJIT
+    if (!newType && cx->methodJitEnabled) {
+        /* Try to ensure methods are method JIT'd.  */
+        mjit::CompileStatus status = mjit::CanMethodJIT(cx, script, script->code,
+                                                        construct,
+                                                        mjit::CompileRequest_Interpreter);
+        if (status == mjit::Compile_Error)
+            goto error;
+        if (status == mjit::Compile_Okay) {
+            mjit::JaegerStatus status = mjit::JaegerShot(cx, true);
+            CHECK_PARTIAL_METHODJIT(status);
+            interpReturnOK = mjit::JaegerStatusToSuccess(status);
+            CHECK_INTERRUPT_HANDLER();
+            goto jit_return;
+        }
+    }
+#endif
+
     if (!ScriptPrologue(cx, regs.fp(), newType))
         goto error;
 
     if (cx->compartment->debugMode()) {
         switch (ScriptDebugPrologue(cx, regs.fp())) {
           case JSTRAP_CONTINUE:
             break;
           case JSTRAP_RETURN:
--- a/js/src/methodjit/Compiler.cpp
+++ b/js/src/methodjit/Compiler.cpp
@@ -901,22 +901,26 @@ MakeJITScript(JSContext *cx, JSScript *s
         CrossChunkEdge &edge = jitEdges[i];
         edge.shimLabel = shimCode + (size_t) edge.shimLabel;
     }
 
     return jit;
 }
 
 static inline bool
-IonGetsFirstChance(JSContext *cx, JSScript *script)
+IonGetsFirstChance(JSContext *cx, JSScript *script, CompileRequest request)
 {
 #ifdef JS_ION
     if (!ion::IsEnabled(cx))
         return false;
 
+    // If we're called from JM, use JM to avoid slow JM -> Ion calls.
+    if (request == CompileRequest_JIT)
+        return false;
+
     // If there's no way this script is going to be Ion compiled, let JM take over.
     if (!script->canIonCompile())
         return false;
 
     // If we cannot enter Ion because bailouts are expected, let JM take over.
     if (script->hasIonScript() && script->ion->bailoutExpected())
         return false;
 
@@ -928,17 +932,17 @@ IonGetsFirstChance(JSContext *cx, JSScri
 CompileStatus
 mjit::CanMethodJIT(JSContext *cx, JSScript *script, jsbytecode *pc,
                    bool construct, CompileRequest request)
 {
   restart:
     if (!cx->methodJitEnabled)
         return Compile_Abort;
 
-    if (IonGetsFirstChance(cx, script))
+    if (IonGetsFirstChance(cx, script, request))
         return Compile_Skipped;
 
     if (script->hasJITInfo()) {
         JSScript::JITScriptHandle *jith = script->jitHandle(construct, cx->compartment->needsBarrier());
         if (jith->isUnjittable())
             return Compile_Abort;
     }
 
--- a/js/src/methodjit/InvokeHelpers.cpp
+++ b/js/src/methodjit/InvokeHelpers.cpp
@@ -267,17 +267,17 @@ UncachedInlineCall(VMFrame &f, InitialFr
 
     bool newType = construct && cx->typeInferenceEnabled() &&
         types::UseNewType(cx, f.script(), f.pc());
 
     if (!types::TypeMonitorCall(cx, args, construct))
         return false;
 
     /* Try to compile if not already compiled. */
-    CompileStatus status = CanMethodJIT(cx, newscript, newscript->code, construct, CompileRequest_Interpreter);
+    CompileStatus status = CanMethodJIT(cx, newscript, newscript->code, construct, CompileRequest_JIT);
     if (status == Compile_Error) {
         /* A runtime exception was thrown, get out. */
         return false;
     }
     if (status == Compile_Abort)
         *unjittable = true;
 
     /*