Bug 1566332 part 5 - Remove support for C++ interpreter -> Baseline JIT OSR, always enter Baseline Interpreter. r=tcampbell
authorJan de Mooij <jdemooij@mozilla.com>
Sat, 20 Jul 2019 08:56:52 +0000
changeset 483623 db5038b9b3d3b3d8d8296b7ee5f978cc1efec8ac
parent 483622 56b33927fd49e11b5f31a8789f1410b540676e51
child 483624 bab3a664928e8ef726025292c47a82b0a3eece56
push id113734
push usernbeleuzu@mozilla.com
push dateSat, 20 Jul 2019 21:45:35 +0000
treeherdermozilla-inbound@db5038b9b3d3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstcampbell
bugs1566332
milestone70.0a1
first release with
nightly linux32
db5038b9b3d3 / 70.0a1 / 20190720214009 / files
nightly linux64
db5038b9b3d3 / 70.0a1 / 20190720214009 / files
nightly mac
db5038b9b3d3 / 70.0a1 / 20190720214009 / files
nightly win32
db5038b9b3d3 / 70.0a1 / 20190720214009 / files
nightly win64
db5038b9b3d3 / 70.0a1 / 20190720214009 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1566332 part 5 - Remove support for C++ interpreter -> Baseline JIT OSR, always enter Baseline Interpreter. r=tcampbell If the script already has a BaselineScript or the Interpreter/JIT thresholds are the same, we will immediately switch to Baseline JIT code at the same LOOPENTRY op. This should be unlikely for most loops and the extra overhead for this case is negligible. Differential Revision: https://phabricator.services.mozilla.com/D38280
js/src/jit/BaselineFrame.cpp
js/src/jit/BaselineJIT.cpp
js/src/jit/BaselineJIT.h
js/src/vm/Interpreter.cpp
--- a/js/src/jit/BaselineFrame.cpp
+++ b/js/src/jit/BaselineFrame.cpp
@@ -135,46 +135,34 @@ bool BaselineFrame::initForOsr(Interpret
 
   JSContext* cx =
       fp->script()->runtimeFromMainThread()->mainContextFromOwnThread();
 
   Activation* interpActivation = cx->activation()->prev();
   jsbytecode* pc = interpActivation->asInterpreter()->regs().pc;
   MOZ_ASSERT(fp->script()->containsPC(pc));
 
-  if (!fp->script()->hasBaselineScript()) {
-    // If we don't have a BaselineScript, we are doing OSR into the Baseline
-    // Interpreter. Initialize Baseline Interpreter fields. We can get the pc
-    // from the C++ interpreter's activation, we just have to skip the
-    // JitActivation.
-    flags_ |= BaselineFrame::RUNNING_IN_INTERPRETER;
-    interpreterScript_ = fp->script();
-    setInterpreterPC(pc);
-  }
+  // We are doing OSR into the Baseline Interpreter. We can get the pc from the
+  // C++ interpreter's activation, we just have to skip the JitActivation.
+  flags_ |= BaselineFrame::RUNNING_IN_INTERPRETER;
+  interpreterScript_ = fp->script();
+  setInterpreterPC(pc);
 
   frameSize_ = BaselineFrame::FramePointerOffset + BaselineFrame::Size() +
                numStackValues * sizeof(Value);
 
   MOZ_ASSERT(numValueSlots() == numStackValues);
 
   for (uint32_t i = 0; i < numStackValues; i++) {
     *valueSlot(i) = fp->slots()[i];
   }
 
   if (fp->isDebuggee()) {
     // For debuggee frames, update any Debugger.Frame objects for the
     // InterpreterFrame to point to the BaselineFrame.
-
-    // The caller pushed a fake (nullptr) return address, so ScriptFrameIter
-    // can't use it to determine the frame's bytecode pc. Set an override pc so
-    // frame iteration can use that.
-    setOverridePc(pc);
-
     if (!Debugger::handleBaselineOsr(cx, fp, this)) {
       return false;
     }
-
-    clearOverridePc();
     setIsDebuggee();
   }
 
   return true;
 }
--- a/js/src/jit/BaselineJIT.cpp
+++ b/js/src/jit/BaselineJIT.cpp
@@ -126,40 +126,28 @@ static JitExecStatus EnterBaseline(JSCon
 
   // Release temporary buffer used for OSR into Ion.
   cx->freeOsrTempData();
 
   MOZ_ASSERT_IF(data.result.isMagic(), data.result.isMagic(JS_ION_ERROR));
   return data.result.isMagic() ? JitExec_Error : JitExec_Ok;
 }
 
-JitExecStatus jit::EnterBaselineAtBranch(JSContext* cx, InterpreterFrame* fp,
-                                         jsbytecode* pc) {
+JitExecStatus jit::EnterBaselineInterpreterAtBranch(JSContext* cx,
+                                                    InterpreterFrame* fp,
+                                                    jsbytecode* pc) {
   MOZ_ASSERT(JSOp(*pc) == JSOP_LOOPENTRY);
 
   EnterJitData data(cx);
 
-  if (fp->script()->hasBaselineScript()) {
-    BaselineScript* baseline = fp->script()->baselineScript();
-    PCMappingSlotInfo slotInfo;
-    data.jitcode = baseline->nativeCodeForPC(fp->script(), pc, &slotInfo);
-    MOZ_ASSERT(slotInfo.isStackSynced());
-
-    // Skip debug breakpoint/trap handler, the interpreter already handled it
-    // for the current op.
-    if (fp->isDebuggee()) {
-      MOZ_RELEASE_ASSERT(baseline->hasDebugInstrumentation());
-      data.jitcode += MacroAssembler::ToggledCallSize(data.jitcode);
-    }
-  } else {
-    // As above, use the entry point that skips the debug trap.
-    const BaselineInterpreter& interp =
-        cx->runtime()->jitRuntime()->baselineInterpreter();
-    data.jitcode = interp.interpretOpNoDebugTrapAddr().value;
-  }
+  // Use the entry point that skips the debug trap because the C++ interpreter
+  // already handled this for the current op.
+  const BaselineInterpreter& interp =
+      cx->runtime()->jitRuntime()->baselineInterpreter();
+  data.jitcode = interp.interpretOpNoDebugTrapAddr().value;
 
   // Note: keep this in sync with SetEnterJitData.
 
   data.osrFrame = fp;
   data.osrNumStackValues =
       fp->script()->nfixed() + cx->interpreterRegs().stackDepth();
 
   RootedValue newTarget(cx);
@@ -330,17 +318,17 @@ bool jit::CanBaselineInterpretScript(JSS
     // stack frames.
     return false;
   }
 
   return true;
 }
 
 static MethodStatus CanEnterBaselineInterpreter(JSContext* cx,
-                                                HandleScript script) {
+                                                JSScript* script) {
   MOZ_ASSERT(IsBaselineInterpreterEnabled());
 
   if (script->jitScript()) {
     return Method_Compiled;
   }
 
   if (!CanBaselineInterpretScript(script)) {
     return Method_CantCompile;
@@ -359,40 +347,25 @@ static MethodStatus CanEnterBaselineInte
   AutoKeepJitScripts keepJitScript(cx);
   if (!script->ensureHasJitScript(cx, keepJitScript)) {
     return Method_Error;
   }
 
   return Method_Compiled;
 }
 
-template <BaselineTier Tier>
-MethodStatus jit::CanEnterBaselineAtBranch(JSContext* cx,
-                                           InterpreterFrame* fp) {
+MethodStatus jit::CanEnterBaselineInterpreterAtBranch(JSContext* cx,
+                                                      InterpreterFrame* fp) {
   if (!CheckFrame(fp)) {
     return Method_CantCompile;
   }
 
-  RootedScript script(cx, fp->script());
-  switch (Tier) {
-    case BaselineTier::Interpreter:
-      return CanEnterBaselineInterpreter(cx, script);
-
-    case BaselineTier::Compiler:
-      return CanEnterBaselineJIT(cx, script, fp);
-  }
-
-  MOZ_CRASH("Unexpected tier");
+  return CanEnterBaselineInterpreter(cx, fp->script());
 }
 
-template MethodStatus jit::CanEnterBaselineAtBranch<BaselineTier::Interpreter>(
-    JSContext* cx, InterpreterFrame* fp);
-template MethodStatus jit::CanEnterBaselineAtBranch<BaselineTier::Compiler>(
-    JSContext* cx, InterpreterFrame* fp);
-
 template <BaselineTier Tier>
 MethodStatus jit::CanEnterBaselineMethod(JSContext* cx, RunState& state) {
   if (state.isInvoke()) {
     InvokeState& invoke = *state.asInvoke();
     if (invoke.args().length() > BASELINE_MAX_ARGS_LENGTH) {
       JitSpew(JitSpew_BaselineAbort, "Too many arguments (%u)",
               invoke.args().length());
       return Method_CantCompile;
@@ -445,18 +418,17 @@ bool jit::BaselineCompileFromBaselineInt
     case Method_Compiled: {
       if (*pc == JSOP_LOOPENTRY) {
         PCMappingSlotInfo slotInfo;
         BaselineScript* baselineScript = script->baselineScript();
         *res = baselineScript->nativeCodeForPC(script, pc, &slotInfo);
         MOZ_ASSERT(slotInfo.isStackSynced());
         if (frame->isDebuggee()) {
           // Skip the debug trap emitted by emitInterpreterLoop because the
-          // Baseline Interpreter already handled it for the current op. This
-          // matches EnterBaseline.
+          // Baseline Interpreter already handled it for the current op.
           MOZ_RELEASE_ASSERT(baselineScript->hasDebugInstrumentation());
           *res += MacroAssembler::ToggledCallSize(*res);
         }
       } else {
         *res = script->baselineScript()->warmUpCheckPrologueAddr();
       }
       frame->prepareForBaselineInterpreterToJitOSR();
       return true;
--- a/js/src/jit/BaselineJIT.h
+++ b/js/src/jit/BaselineJIT.h
@@ -541,21 +541,22 @@ inline bool IsBaselineJitEnabled() {
   return IsBaselineInterpreterEnabled() && JitOptions.baselineJit;
 }
 
 enum class BaselineTier { Interpreter, Compiler };
 
 template <BaselineTier Tier>
 MethodStatus CanEnterBaselineMethod(JSContext* cx, RunState& state);
 
-template <BaselineTier Tier>
-MethodStatus CanEnterBaselineAtBranch(JSContext* cx, InterpreterFrame* fp);
+MethodStatus CanEnterBaselineInterpreterAtBranch(JSContext* cx,
+                                                 InterpreterFrame* fp);
 
-JitExecStatus EnterBaselineAtBranch(JSContext* cx, InterpreterFrame* fp,
-                                    jsbytecode* pc);
+JitExecStatus EnterBaselineInterpreterAtBranch(JSContext* cx,
+                                               InterpreterFrame* fp,
+                                               jsbytecode* pc);
 
 bool CanBaselineInterpretScript(JSScript* script);
 
 // Called by the Baseline Interpreter to compile a script for the Baseline JIT.
 // |res| is set to the native code address in the BaselineScript to jump to, or
 // nullptr if we were unable to compile this script.
 bool BaselineCompileFromBaselineInterpreter(JSContext* cx, BaselineFrame* frame,
                                             uint8_t** res);
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -1967,37 +1967,33 @@ static MOZ_NEVER_INLINE JS_HAZ_JSNATIVE_
       ADVANCE_AND_DISPATCH(JSOP_JUMPTARGET_LENGTH);
     }
 
     CASE(JSOP_LABEL)
     END_CASE(JSOP_LABEL)
 
     CASE(JSOP_LOOPENTRY) {
       COUNT_COVERAGE();
-      // Attempt on-stack replacement with Baseline code.
+      // Attempt on-stack replacement into the Baseline Interpreter.
       if (jit::IsBaselineInterpreterEnabled()) {
         script->incWarmUpCounter();
 
-        using Tier = jit::BaselineTier;
-        bool tryBaselineInterpreter = !script->hasBaselineScript();
         jit::MethodStatus status =
-            tryBaselineInterpreter
-                ? jit::CanEnterBaselineAtBranch<Tier::Interpreter>(cx,
-                                                                   REGS.fp())
-                : jit::CanEnterBaselineAtBranch<Tier::Compiler>(cx, REGS.fp());
+            jit::CanEnterBaselineInterpreterAtBranch(cx, REGS.fp());
         if (status == jit::Method_Error) {
           goto error;
         }
         if (status == jit::Method_Compiled) {
           bool wasProfiler = REGS.fp()->hasPushedGeckoProfilerFrame();
 
           jit::JitExecStatus maybeOsr;
           {
             GeckoProfilerBaselineOSRMarker osr(cx, wasProfiler);
-            maybeOsr = jit::EnterBaselineAtBranch(cx, REGS.fp(), REGS.pc);
+            maybeOsr =
+                jit::EnterBaselineInterpreterAtBranch(cx, REGS.fp(), REGS.pc);
           }
 
           // We failed to call into baseline at all, so treat as an error.
           if (maybeOsr == jit::JitExec_Aborted) {
             goto error;
           }
 
           interpReturnOK = (maybeOsr == jit::JitExec_Ok);