Bug 1522837 part 10 - Add interpreter fields to BaselineFrame. r=djvj
authorJan de Mooij <jdemooij@mozilla.com>
Sun, 10 Mar 2019 19:43:08 +0000
changeset 524295 cb6108540cef8f493ec19b75517e8d7c70501a59
parent 524290 99b57fdeaf5467fbf323d87d79e3b59cc9e4632f
child 524296 7a376bfac6dea0340625911e8bb02ad30c21d5e8
push id2032
push userffxbld-merge
push dateMon, 13 May 2019 09:36:57 +0000
treeherdermozilla-release@455c1065dcbe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdjvj
bugs1522837
milestone67.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 1522837 part 10 - Add interpreter fields to BaselineFrame. r=djvj Differential Revision: https://phabricator.services.mozilla.com/D18252
js/src/jit/BaselineCompiler.cpp
js/src/jit/BaselineCompiler.h
js/src/jit/BaselineFrame.cpp
js/src/jit/BaselineFrame.h
js/src/jit/BaselineFrameInfo.h
js/src/jit/JSJitFrameIter.cpp
--- a/js/src/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -373,37 +373,17 @@ MethodStatus BaselineCompiler::compile()
 
 template <>
 void BaselineCompilerCodeGen::loadScript(Register dest) {
   masm.movePtr(ImmGCPtr(handler.script()), dest);
 }
 
 template <>
 void BaselineInterpreterCodeGen::loadScript(Register dest) {
-  // TODO(bug 1522394): consider adding interpreterScript to BaselineFrame once
-  // we are able to run benchmarks.
-
-  masm.loadPtr(frame.addressOfCalleeToken(), dest);
-
-  Label notFunction, done;
-  masm.branchTestPtr(Assembler::NonZero, dest, Imm32(CalleeTokenScriptBit),
-                     &notFunction);
-  {
-    // CalleeToken_Function or CalleeToken_FunctionConstructing.
-    masm.andPtr(Imm32(uint32_t(CalleeTokenMask)), dest);
-    masm.loadPtr(Address(dest, JSFunction::offsetOfScript()), dest);
-    masm.jump(&done);
-  }
-  masm.bind(&notFunction);
-  {
-    // CalleeToken_Script.
-    masm.andPtr(Imm32(uint32_t(CalleeTokenMask)), dest);
-  }
-
-  masm.bind(&done);
+  masm.loadPtr(frame.addressOfInterpreterScript(), dest);
 }
 
 template <>
 void BaselineCompilerCodeGen::emitInitializeLocals() {
   // Initialize all locals to |undefined|. Lexical bindings are temporal
   // dead zoned in bytecode.
 
   size_t n = frame.nlocals();
@@ -528,17 +508,20 @@ bool BaselineCompilerCodeGen::emitNextIC
     return false;
   }
 
   return true;
 }
 
 template <>
 bool BaselineInterpreterCodeGen::emitNextIC() {
-  MOZ_CRASH("NYI: interpreter emitNextIC");
+  masm.loadPtr(frame.addressOfInterpreterICEntry(), ICStubReg);
+  masm.loadPtr(Address(ICStubReg, ICEntry::offsetOfFirstStub()), ICStubReg);
+  masm.call(Address(ICStubReg, ICStub::offsetOfStubCode()));
+  return true;
 }
 
 template <typename Handler>
 void BaselineCodeGen<Handler>::prepareVMCall() {
   pushedBeforeCall_ = masm.framePushed();
 #ifdef DEBUG
   inCall_ = true;
 #endif
@@ -795,35 +778,33 @@ void BaselineInterpreterCodeGen::loadGlo
   Register scratch = dest.scratchReg();
   loadGlobalLexicalEnvironment(scratch);
   static constexpr size_t SlotOffset =
       LexicalEnvironmentObject::offsetOfThisValueOrScopeSlot();
   masm.loadValue(Address(scratch, SlotOffset), dest);
 }
 
 template <>
-void BaselineCompilerCodeGen::pushScriptArg(Register scratch) {
+void BaselineCompilerCodeGen::pushScriptArg() {
   pushArg(ImmGCPtr(handler.script()));
 }
 
 template <>
-void BaselineInterpreterCodeGen::pushScriptArg(Register scratch) {
-  loadScript(scratch);
-  pushArg(scratch);
+void BaselineInterpreterCodeGen::pushScriptArg() {
+  pushArg(frame.addressOfInterpreterScript());
 }
 
 template <>
 void BaselineCompilerCodeGen::pushBytecodePCArg() {
   pushArg(ImmPtr(handler.pc()));
 }
 
 template <>
 void BaselineInterpreterCodeGen::pushBytecodePCArg() {
-  // This will be something like pushArg(Address(...));
-  MOZ_CRASH("NYI: interpreter pushBytecodePCArg");
+  pushArg(frame.addressOfInterpreterPC());
 }
 
 template <>
 void BaselineCompilerCodeGen::pushScriptNameArg() {
   pushArg(ImmGCPtr(handler.script()->getName(handler.pc())));
 }
 
 template <>
@@ -978,17 +959,17 @@ bool BaselineCompilerCodeGen::initEnviro
     }
   } else if (!handler.module()) {
     // EnvironmentChain pointer in BaselineFrame has already been initialized
     // in prologue, but we need to check for redeclaration errors in global and
     // eval scripts.
 
     prepareVMCall();
 
-    pushScriptArg(R2.scratchReg());
+    pushScriptArg();
     masm.loadPtr(frame.addressOfEnvironmentChain(), R0.scratchReg());
     pushArg(R0.scratchReg());
 
     using Fn = bool (*)(JSContext*, HandleObject, HandleScript);
     if (!callVMNonOp<Fn, js::CheckGlobalOrEvalDeclarationConflicts>(phase)) {
       return false;
     }
   }
@@ -2083,17 +2064,17 @@ bool BaselineCodeGen<Handler>::emit_JSOP
   if (JSObject* obj = handler.maybeNoCloneSingletonObject()) {
     frame.push(ObjectValue(*obj));
     return true;
   }
 
   prepareVMCall();
 
   pushBytecodePCArg();
-  pushScriptArg(R2.scratchReg());
+  pushScriptArg();
 
   using Fn = JSObject* (*)(JSContext*, HandleScript, jsbytecode*);
   if (!callVM<Fn, SingletonObjectLiteralOperation>()) {
     return false;
   }
 
   // Box and push return value.
   masm.tagValue(JSVAL_TYPE_OBJECT, ReturnReg, R0);
@@ -2113,17 +2094,17 @@ bool BaselineCompilerCodeGen::emit_JSOP_
   return true;
 }
 
 template <>
 bool BaselineInterpreterCodeGen::emit_JSOP_CALLSITEOBJ() {
   prepareVMCall();
 
   pushBytecodePCArg();
-  pushScriptArg(R2.scratchReg());
+  pushScriptArg();
 
   using Fn = ArrayObject* (*)(JSContext*, HandleScript, jsbytecode*);
   if (!callVM<Fn, ProcessCallSiteObjOperation>()) {
     return false;
   }
 
   // Box and push return value.
   masm.tagValue(JSVAL_TYPE_OBJECT, ReturnReg, R0);
@@ -2460,17 +2441,17 @@ bool BaselineCompilerCodeGen::emit_JSOP_
   return true;
 }
 
 template <>
 bool BaselineInterpreterCodeGen::emit_JSOP_NEWARRAY_COPYONWRITE() {
   prepareVMCall();
 
   pushBytecodePCArg();
-  pushScriptArg(R2.scratchReg());
+  pushScriptArg();
 
   using Fn = ArrayObject* (*)(JSContext*, HandleScript, jsbytecode*);
   if (!callVM<Fn, NewArrayCopyOnWriteOperation>()) {
     return false;
   }
 
   // Box and push return value.
   masm.tagValue(JSVAL_TYPE_OBJECT, ReturnReg, R0);
@@ -3288,17 +3269,17 @@ template <>
 bool BaselineInterpreterCodeGen::emit_JSOP_GETIMPORT() {
   frame.syncStack(0);
 
   masm.loadPtr(frame.addressOfEnvironmentChain(), R0.scratchReg());
 
   prepareVMCall();
 
   pushBytecodePCArg();
-  pushScriptArg(R2.scratchReg());
+  pushScriptArg();
   pushArg(R0.scratchReg());
 
   using Fn = bool (*)(JSContext*, HandleObject, HandleScript, jsbytecode*,
                       MutableHandleValue);
   if (!callVM<Fn, GetImportOperation>()) {
     return false;
   }
 
@@ -3327,32 +3308,32 @@ template <typename Handler>
 bool BaselineCodeGen<Handler>::emit_JSOP_SETINTRINSIC() {
   frame.syncStack(0);
   masm.loadValue(frame.addressOfStackValue(-1), R0);
 
   prepareVMCall();
 
   pushArg(R0);
   pushBytecodePCArg();
-  pushScriptArg(R2.scratchReg());
+  pushScriptArg();
 
   using Fn = bool (*)(JSContext*, JSScript*, jsbytecode*, HandleValue);
   return callVM<Fn, SetIntrinsicOperation>();
 }
 
 template <typename Handler>
 bool BaselineCodeGen<Handler>::emit_JSOP_DEFVAR() {
   frame.syncStack(0);
 
   masm.loadPtr(frame.addressOfEnvironmentChain(), R0.scratchReg());
 
   prepareVMCall();
 
   pushBytecodePCArg();
-  pushScriptArg(R2.scratchReg());
+  pushScriptArg();
   pushArg(R0.scratchReg());
 
   using Fn = bool (*)(JSContext*, HandleObject, HandleScript, jsbytecode*);
   return callVM<Fn, DefVarOperation>();
 }
 
 template <typename Handler>
 bool BaselineCodeGen<Handler>::emitDefLexical(JSOp op) {
@@ -3360,17 +3341,17 @@ bool BaselineCodeGen<Handler>::emitDefLe
 
   frame.syncStack(0);
 
   masm.loadPtr(frame.addressOfEnvironmentChain(), R0.scratchReg());
 
   prepareVMCall();
 
   pushBytecodePCArg();
-  pushScriptArg(R2.scratchReg());
+  pushScriptArg();
   pushArg(R0.scratchReg());
 
   using Fn = bool (*)(JSContext*, HandleObject, HandleScript, jsbytecode*);
   return callVM<Fn, DefLexicalOperation>();
 }
 
 template <typename Handler>
 bool BaselineCodeGen<Handler>::emit_JSOP_DEFCONST() {
@@ -3387,17 +3368,17 @@ bool BaselineCodeGen<Handler>::emit_JSOP
   frame.popRegsAndSync(1);
   masm.unboxObject(R0, R0.scratchReg());
   masm.loadPtr(frame.addressOfEnvironmentChain(), R1.scratchReg());
 
   prepareVMCall();
 
   pushArg(R0.scratchReg());
   pushArg(R1.scratchReg());
-  pushScriptArg(R2.scratchReg());
+  pushScriptArg();
 
   using Fn = bool (*)(JSContext*, HandleScript, HandleObject, HandleFunction);
   return callVM<Fn, DefFunOperation>();
 }
 
 template <typename Handler>
 bool BaselineCodeGen<Handler>::emitInitPropGetterSetter() {
   // Keep values on the stack for the decompiler.
@@ -5528,17 +5509,17 @@ bool BaselineCodeGen<Handler>::emit_JSOP
 template <typename Handler>
 bool BaselineCodeGen<Handler>::emit_JSOP_CLASSCONSTRUCTOR() {
   frame.syncStack(0);
 
   // Pass nullptr as prototype to MakeDefaultConstructor
   prepareVMCall();
   pushArg(ImmPtr(nullptr));
   pushBytecodePCArg();
-  pushScriptArg(R2.scratchReg());
+  pushScriptArg();
 
   using Fn =
       JSFunction* (*)(JSContext*, HandleScript, jsbytecode*, HandleObject);
   if (!callVM<Fn, js::MakeDefaultConstructor>()) {
     return false;
   }
 
   masm.tagValue(JSVAL_TYPE_OBJECT, ReturnReg, R0);
@@ -5550,17 +5531,17 @@ template <typename Handler>
 bool BaselineCodeGen<Handler>::emit_JSOP_DERIVEDCONSTRUCTOR() {
   frame.popRegsAndSync(1);
 
   masm.unboxObject(R0, R0.scratchReg());
 
   prepareVMCall();
   pushArg(R0.scratchReg());
   pushBytecodePCArg();
-  pushScriptArg(R2.scratchReg());
+  pushScriptArg();
 
   using Fn =
       JSFunction* (*)(JSContext*, HandleScript, jsbytecode*, HandleObject);
   if (!callVM<Fn, js::MakeDefaultConstructor>()) {
     return false;
   }
 
   masm.tagValue(JSVAL_TYPE_OBJECT, ReturnReg, R0);
@@ -5590,17 +5571,17 @@ bool BaselineCompilerCodeGen::emit_JSOP_
   frame.push(R0);
   return true;
 }
 
 template <>
 bool BaselineInterpreterCodeGen::emit_JSOP_IMPORTMETA() {
   prepareVMCall();
 
-  pushScriptArg(R2.scratchReg());
+  pushScriptArg();
 
   using Fn = JSObject* (*)(JSContext*, HandleScript);
   if (!callVM<Fn, ImportMetaOperation>()) {
     return false;
   }
 
   masm.tagValue(JSVAL_TYPE_OBJECT, ReturnReg, R0);
   frame.push(R0);
@@ -5609,17 +5590,17 @@ bool BaselineInterpreterCodeGen::emit_JS
 
 template <typename Handler>
 bool BaselineCodeGen<Handler>::emit_JSOP_DYNAMIC_IMPORT() {
   // Put specifier value in R0.
   frame.popRegsAndSync(1);
 
   prepareVMCall();
   pushArg(R0);
-  pushScriptArg(R2.scratchReg());
+  pushScriptArg();
 
   using Fn = JSObject* (*)(JSContext*, HandleScript, HandleValue);
   if (!callVM<Fn, js::StartDynamicModuleImport>()) {
     return false;
   }
 
   masm.tagValue(JSVAL_TYPE_OBJECT, ReturnReg, R0);
   frame.push(R0);
--- a/js/src/jit/BaselineCompiler.h
+++ b/js/src/jit/BaselineCompiler.h
@@ -299,17 +299,17 @@ class BaselineCodeGen {
   explicit BaselineCodeGen(JSContext* cx, HandlerArgs&&... args);
 
   template <typename T>
   void pushArg(const T& t) {
     masm.Push(t);
   }
 
   // Pushes the current script as argument for a VM function.
-  void pushScriptArg(Register scratch);
+  void pushScriptArg();
 
   // Pushes the bytecode pc as argument for a VM function.
   void pushBytecodePCArg();
 
   // Pushes a name/object/scope associated with the current bytecode op (and
   // stored in the script) as argument for a VM function.
   enum class ScriptObjectType { RegExp, Function };
   void pushScriptObjectArg(ScriptObjectType type);
--- a/js/src/jit/BaselineFrame.cpp
+++ b/js/src/jit/BaselineFrame.cpp
@@ -50,16 +50,20 @@ void BaselineFrame::trace(JSTracer* trc,
   if (isEvalFrame() && script()->isDirectEvalInFunction()) {
     TraceRoot(trc, evalNewTargetAddress(), "baseline-evalNewTarget");
   }
 
   if (hasArgsObj()) {
     TraceRoot(trc, &argsObj_, "baseline-args-obj");
   }
 
+  if (runningInInterpreter()) {
+    TraceRoot(trc, &interpreterScript_, "baseline-interpreterScript");
+  }
+
   // Trace locals and stack values.
   JSScript* script = this->script();
   size_t nfixed = script->nfixed();
   jsbytecode* pc;
   frameIterator.baselineScriptAndPc(nullptr, &pc);
   size_t nlivefixed = script->calculateLiveFixed(pc);
 
   // NB: It is possible that numValueSlots() could be zero, even if nfixed is
--- a/js/src/jit/BaselineFrame.h
+++ b/js/src/jit/BaselineFrame.h
@@ -9,32 +9,36 @@
 
 #include "jit/JitFrames.h"
 #include "vm/Stack.h"
 
 namespace js {
 namespace jit {
 
 struct BaselineDebugModeOSRInfo;
+class ICEntry;
 
 // The stack looks like this, fp is the frame pointer:
 //
 // fp+y   arguments
 // fp+x   JitFrameLayout (frame header)
 // fp  => saved frame pointer
 // fp-x   BaselineFrame
 //        locals
 //        stack values
 
 class BaselineFrame {
  public:
   enum Flags : uint32_t {
     // The frame has a valid return value. See also InterpreterFrame::HAS_RVAL.
     HAS_RVAL = 1 << 0,
 
+    // The frame is running in the Baseline interpreter instead of JIT.
+    RUNNING_IN_INTERPRETER = 1 << 1,
+
     // An initial environment has been pushed on the environment chain for
     // function frames that need a CallObject or eval frames that need a
     // VarEnvironmentObject.
     HAS_INITIAL_ENV = 1 << 2,
 
     // Frame has an arguments object, argsObj_.
     HAS_ARGS_OBJ = 1 << 4,
 
@@ -72,33 +76,43 @@ class BaselineFrame {
 
     // If set, we're handling an exception for this frame. This is set for
     // debug mode OSR sanity checking when it handles corner cases which
     // only arise during exception handling.
     HANDLING_EXCEPTION = 1 << 12,
   };
 
  protected:  // Silence Clang warning about unused private fields.
+  // The fields below are only valid if RUNNING_IN_INTERPRETER.
+  JSScript* interpreterScript_;
+  jsbytecode* interpreterPC_;
+  ICEntry* interpreterICEntry_;
+
+  JSObject* envChain_;        // Environment chain (always initialized).
+  ArgumentsObject* argsObj_;  // If HAS_ARGS_OBJ, the arguments object.
+
   // We need to split the Value into 2 fields of 32 bits, otherwise the C++
   // compiler may add some padding between the fields.
-
   union {
     struct {
       uint32_t loScratchValue_;
       uint32_t hiScratchValue_;
     };
     BaselineDebugModeOSRInfo* debugModeOSRInfo_;
   };
+
+  uint32_t flags_;
+  uint32_t frameSize_;
   uint32_t loReturnValue_;  // If HAS_RVAL, the frame's return value.
   uint32_t hiReturnValue_;
-  uint32_t frameSize_;
-  JSObject* envChain_;        // Environment chain (always initialized).
-  ArgumentsObject* argsObj_;  // If HAS_ARGS_OBJ, the arguments object.
   uint32_t overrideOffset_;   // If HAS_OVERRIDE_PC, the bytecode offset.
-  uint32_t flags_;
+#if JS_BITS_PER_WORD == 32
+  // Ensure frame is 8-byte aligned, see static_assert below.
+  uint32_t padding_;
+#endif
 
  public:
   // Distance between the frame pointer and the frame header (return address).
   // This is the old frame pointer saved in the prologue.
   static const uint32_t FramePointerOffset = sizeof(void*);
 
   MOZ_MUST_USE bool initForOsr(InterpreterFrame* fp, uint32_t numStackValues);
 
@@ -207,16 +221,28 @@ class BaselineFrame {
     if (isConstructing()) {
       return *(Value*)(reinterpret_cast<const uint8_t*>(this) +
                        BaselineFrame::Size() +
                        offsetOfArg(Max(numFormalArgs(), numActualArgs())));
     }
     return UndefinedValue();
   }
 
+  bool runningInInterpreter() const { return flags_ & RUNNING_IN_INTERPRETER; }
+
+  JSScript* interpreterScript() const {
+    MOZ_ASSERT(runningInInterpreter());
+    return interpreterScript_;
+  }
+
+  jsbytecode* interpreterPC() const {
+    MOZ_ASSERT(runningInInterpreter());
+    return interpreterPC_;
+  }
+
   bool hasReturnValue() const { return flags_ & HAS_RVAL; }
   MutableHandleValue returnValue() {
     if (!hasReturnValue()) {
       addressOfReturnValue()->setUndefined();
     }
     return MutableHandleValue::fromMarkedLocation(addressOfReturnValue());
   }
   void setReturnValue(const Value& v) {
@@ -372,21 +398,31 @@ class BaselineFrame {
     return -int(Size()) + offsetof(BaselineFrame, argsObj_);
   }
   static int reverseOffsetOfFlags() {
     return -int(Size()) + offsetof(BaselineFrame, flags_);
   }
   static int reverseOffsetOfReturnValue() {
     return -int(Size()) + offsetof(BaselineFrame, loReturnValue_);
   }
+  static int reverseOffsetOfInterpreterScript() {
+    return -int(Size()) + offsetof(BaselineFrame, interpreterScript_);
+  }
+  static int reverseOffsetOfInterpreterPC() {
+    return -int(Size()) + offsetof(BaselineFrame, interpreterPC_);
+  }
+  static int reverseOffsetOfInterpreterICEntry() {
+    return -int(Size()) + offsetof(BaselineFrame, interpreterICEntry_);
+  }
   static int reverseOffsetOfLocal(size_t index) {
     return -int(Size()) - (index + 1) * sizeof(Value);
   }
 };
 
 // Ensure the frame is 8-byte aligned (required on ARM).
-JS_STATIC_ASSERT(((sizeof(BaselineFrame) + BaselineFrame::FramePointerOffset) %
-                  8) == 0);
+static_assert(((sizeof(BaselineFrame) + BaselineFrame::FramePointerOffset) %
+               8) == 0,
+              "frame (including frame pointer) must be 8-byte aligned");
 
 }  // namespace jit
 }  // namespace js
 
 #endif /* jit_BaselineFrame_h */
--- a/js/src/jit/BaselineFrameInfo.h
+++ b/js/src/jit/BaselineFrameInfo.h
@@ -357,22 +357,28 @@ class InterpreterFrameInfo : public Fram
   }
 
   Address addressOfStackValue(int depth) const {
     MOZ_ASSERT(depth < 0);
     return Address(masm.getStackPointer(),
                    masm.framePushed() + size_t(-(depth + 1)) * sizeof(Value));
   }
 
+  BaseIndex addressOfStackValue(Register index, int32_t offset = 0) const {
+    return BaseIndex(masm.getStackPointer(), index, ValueScale, offset);
+  }
+
   void popRegsAndSync(uint32_t uses);
 
   void pop() { popn(1); }
 
   void popn(uint32_t n) { masm.addToStackPtr(Imm32(n * sizeof(Value))); }
 
+  void popn(Register reg) { masm.addToStackPtr(reg); }
+
   void popValue(ValueOperand dest) { masm.popValue(dest); }
 
   void push(const ValueOperand& val,
             JSValueType knownType = JSVAL_TYPE_UNKNOWN) {
     masm.pushValue(val);
   }
   void push(const Value& val) { masm.pushValue(val); }
 
@@ -380,14 +386,27 @@ class InterpreterFrameInfo : public Fram
   void pushEvalNewTarget() { masm.pushValue(addressOfEvalNewTarget()); }
   void pushScratchValue() { masm.pushValue(addressOfScratchValue()); }
 
   void storeStackValue(int32_t depth, const Address& dest,
                        const ValueOperand& scratch) {
     masm.loadValue(addressOfStackValue(depth), scratch);
     masm.storeValue(scratch, dest);
   }
+
+  Address addressOfInterpreterScript() const {
+    return Address(BaselineFrameReg,
+                   BaselineFrame::reverseOffsetOfInterpreterScript());
+  }
+  Address addressOfInterpreterPC() const {
+    return Address(BaselineFrameReg,
+                   BaselineFrame::reverseOffsetOfInterpreterPC());
+  }
+  Address addressOfInterpreterICEntry() const {
+    return Address(BaselineFrameReg,
+                   BaselineFrame::reverseOffsetOfInterpreterICEntry());
+  }
 };
 
 }  // namespace jit
 }  // namespace js
 
 #endif /* jit_BaselineFrameInfo_h */
--- a/js/src/jit/JSJitFrameIter.cpp
+++ b/js/src/jit/JSJitFrameIter.cpp
@@ -116,16 +116,22 @@ void JSJitFrameIter::baselineScriptAndPc
   MOZ_ASSERT(isBaselineJS());
   JSScript* script = this->script();
   if (scriptRes) {
     *scriptRes = script;
   }
 
   MOZ_ASSERT(pcRes);
 
+  if (baselineFrame()->runningInInterpreter()) {
+    MOZ_ASSERT(baselineFrame()->interpreterScript() == script);
+    *pcRes = baselineFrame()->interpreterPC();
+    return;
+  }
+
   // Use the frame's override pc, if we have one. This should only happen
   // when we're in FinishBailoutToBaseline, handling an exception or toggling
   // debug mode.
   if (jsbytecode* overridePc = baselineFrame()->maybeOverridePc()) {
     *pcRes = overridePc;
     return;
   }