Bug 1508962 part 2 - Implement emitDebugInstrumentation to abstract emitting debugging-specific code. r=djvj
authorJan de Mooij <jdemooij@mozilla.com>
Thu, 29 Nov 2018 22:44:44 +0000
changeset 505306 e0b75c94bc06140a53af4e9bc1a6c738b62d5793
parent 505305 77764799fba3b6f29fb7b5ce15e4ba73f263832f
child 505307 c315f5473734de31c574cb650c67a98916f9f64b
push id10290
push userffxbld-merge
push dateMon, 03 Dec 2018 16:23:23 +0000
treeherdermozilla-beta@700bed2445e6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdjvj
bugs1508962
milestone65.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 1508962 part 2 - Implement emitDebugInstrumentation to abstract emitting debugging-specific code. r=djvj Differential Revision: https://phabricator.services.mozilla.com/D12523
js/src/jit/BaselineCompiler.cpp
js/src/jit/BaselineCompiler.h
--- a/js/src/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -35,40 +35,51 @@
 #include "vm/JSScript-inl.h"
 #include "vm/NativeObject-inl.h"
 #include "vm/TypeInference-inl.h"
 
 using namespace js;
 using namespace js::jit;
 
 using mozilla::AssertedCast;
-
-template <typename Handler>
-BaselineCodeGen<Handler>::BaselineCodeGen(JSContext* cx, TempAllocator& alloc, JSScript* script)
-  : handler(),
+using mozilla::Maybe;
+
+BaselineCompilerHandler::BaselineCompilerHandler(JSScript* script)
+  : compileDebugInstrumentation_(script->isDebuggee())
+{
+}
+
+BaselineInterpreterHandler::BaselineInterpreterHandler()
+{
+}
+
+template <typename Handler>
+template <typename... HandlerArgs>
+BaselineCodeGen<Handler>::BaselineCodeGen(JSContext* cx, TempAllocator& alloc, JSScript* script,
+                                          HandlerArgs&&... args)
+  : handler(std::forward<HandlerArgs>(args)...),
     cx(cx),
     script(script),
     pc(script->code()),
     ionCompileable_(jit::IsIonEnabled(cx) && CanIonCompileScript(cx, script)),
-    compileDebugInstrumentation_(script->isDebuggee()),
     alloc_(alloc),
     analysis_(alloc, script),
     frame(script, masm),
     traceLoggerToggleOffsets_(cx),
     icEntryIndex_(0),
     pushedBeforeCall_(0),
 #ifdef DEBUG
     inCall_(false),
 #endif
     modifiesArguments_(false)
 {
 }
 
 BaselineCompiler::BaselineCompiler(JSContext* cx, TempAllocator& alloc, JSScript* script)
-  : BaselineCodeGen(cx, alloc, script),
+  : BaselineCodeGen(cx, alloc, script, script),
     pcMappingEntries_(),
     profilerPushToggleOffset_(),
     profilerEnterFrameToggleOffset_(),
     profilerExitFrameToggleOffset_(),
     traceLoggerScriptTextIdOffset_()
 {
 #ifdef JS_CODEGEN_NONE
     MOZ_CRASH();
@@ -303,17 +314,17 @@ BaselineCompiler::compile()
 
     // The last entry in the last index found, and is used to avoid binary
     // searches for the sought entry when queries are in linear order.
     bytecodeMap[script->nTypeSets()] = 0;
 
     // Compute yield/await native resume addresses.
     baselineScript->computeResumeNativeOffsets(script);
 
-    if (compileDebugInstrumentation_) {
+    if (compileDebugInstrumentation()) {
         baselineScript->setHasDebugInstrumentation();
     }
 
     // Always register a native => bytecode mapping entry, since profiler can be
     // turned on with baseline jitcode on stack, and baseline jitcode cannot be invalidated.
     {
         JitSpew(JitSpew_Profiling, "Added JitcodeGlobalEntry for baseline script %s:%u:%u (%p)",
                     script->filename(), script->lineno(), script->column(), baselineScript.get());
@@ -751,34 +762,34 @@ BaselineCompiler::emitStackCheck()
 
     masm.bind(&skipCall);
     return true;
 }
 
 void
 BaselineCompiler::emitIsDebuggeeCheck()
 {
-    if (compileDebugInstrumentation_) {
+    if (compileDebugInstrumentation()) {
         masm.Push(BaselineFrameReg);
         masm.setupUnalignedABICall(R0.scratchReg());
         masm.loadBaselineFramePtr(BaselineFrameReg, R0.scratchReg());
         masm.passABIArg(R0.scratchReg());
         masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, jit::FrameIsDebuggeeCheck));
         masm.Pop(BaselineFrameReg);
     }
 }
 
 typedef bool (*DebugPrologueFn)(JSContext*, BaselineFrame*, jsbytecode*, bool*);
 static const VMFunction DebugPrologueInfo =
     FunctionInfo<DebugPrologueFn>(jit::DebugPrologue, "DebugPrologue");
 
 bool
 BaselineCompiler::emitDebugPrologue()
 {
-    if (compileDebugInstrumentation_) {
+    if (compileDebugInstrumentation()) {
         // Load pointer to BaselineFrame in R0.
         masm.loadBaselineFramePtr(BaselineFrameReg, R0.scratchReg());
 
         prepareVMCall();
         pushArg(ImmPtr(pc));
         pushArg(R0.scratchReg());
         if (!callVM(DebugPrologueInfo)) {
             return false;
@@ -990,17 +1001,17 @@ BaselineCompiler::emitArgumentTypeChecks
     }
 
     return true;
 }
 
 bool
 BaselineCompiler::emitDebugTrap()
 {
-    MOZ_ASSERT(compileDebugInstrumentation_);
+    MOZ_ASSERT(compileDebugInstrumentation());
     MOZ_ASSERT(frame.numUnsyncedSlots() == 0);
 
     bool enabled = script->stepModeEnabled() || script->hasBreakpointsAt(pc);
 
 #if defined(JS_CODEGEN_ARM64)
     // Flush any pending constant pools to prevent incorrect
     // PCMappingEntry offsets. See Bug 1446819.
     masm.flush();
@@ -1173,17 +1184,17 @@ BaselineCompiler::emitBody()
             continue;
         }
 
         if (info->jumpTarget) {
             // Fully sync the stack if there are incoming jumps.
             frame.syncStack(0);
             frame.setStackDepth(info->stackDepth);
             masm.bind(labelOf(pc));
-        } else if (MOZ_UNLIKELY(compileDebugInstrumentation_)) {
+        } else if (MOZ_UNLIKELY(compileDebugInstrumentation())) {
             // Also fully sync the stack if the debugger is enabled.
             frame.syncStack(0);
         } else {
             // At the beginning of any op, at most the top 2 stack-values are unsynced.
             if (frame.stackDepth() > 2) {
                 frame.syncStack(2);
             }
         }
@@ -1199,17 +1210,17 @@ BaselineCompiler::emitBody()
             emittedOps = 0;
         }
         if (MOZ_UNLIKELY(!addPCMappingEntry(addIndexEntry))) {
             ReportOutOfMemory(cx);
             return Method_Error;
         }
 
         // Emit traps for breakpoints and step mode.
-        if (MOZ_UNLIKELY(compileDebugInstrumentation_) && !emitDebugTrap()) {
+        if (MOZ_UNLIKELY(compileDebugInstrumentation()) && !emitDebugTrap()) {
             return Method_Error;
         }
 
         switch (op) {
           // ===== NOT Yet Implemented =====
           case JSOP_FORCEINTERPRETER:
             // Intentionally not implemented.
           case JSOP_SETINTRINSIC:
@@ -4129,16 +4140,67 @@ BaselineCodeGen<Handler>::emit_JSOP_RETS
     Register scratch2 = R0.scratchReg();
     LoadBaselineScriptResumeEntries(masm, script, scratch1, scratch2);
     masm.unboxInt32(R1, scratch2);
     masm.loadPtr(BaseIndex(scratch1, scratch2, ScaleFromElemWidth(sizeof(uintptr_t))), scratch1);
     masm.jump(scratch1);
     return true;
 }
 
+template <>
+template <typename F1, typename F2>
+MOZ_MUST_USE bool
+BaselineCompilerCodeGen::emitDebugInstrumentation(const F1& ifDebuggee,
+                                                  const Maybe<F2>& ifNotDebuggee)
+{
+    // The JIT calls either ifDebuggee or (if present) ifNotDebuggee, because it
+    // knows statically whether we're compiling with debug instrumentation.
+
+    if (handler.compileDebugInstrumentation()) {
+        return ifDebuggee();
+    }
+
+    if (ifNotDebuggee) {
+        return (*ifNotDebuggee)();
+    }
+
+    return true;
+}
+
+template <>
+template <typename F1, typename F2>
+MOZ_MUST_USE bool
+BaselineInterpreterCodeGen::emitDebugInstrumentation(const F1& ifDebuggee,
+                                                     const Maybe<F2>& ifNotDebuggee)
+{
+    // The interpreter emits both ifDebuggee and (if present) ifNotDebuggee
+    // paths, with a branch based on the frame's DEBUGGEE flag.
+
+    Label isNotDebuggee, done;
+    masm.branchTest32(Assembler::Zero, frame.addressOfFlags(),
+                      Imm32(BaselineFrame::DEBUGGEE), &isNotDebuggee);
+
+    if (!ifDebuggee()) {
+        return false;
+    }
+
+    if (ifNotDebuggee) {
+        masm.jump(&done);
+    }
+
+    masm.bind(&isNotDebuggee);
+
+    if (ifNotDebuggee && !(*ifNotDebuggee)()) {
+        return false;
+    }
+
+    masm.bind(&done);
+    return true;
+}
+
 typedef bool (*PushLexicalEnvFn)(JSContext*, BaselineFrame*, Handle<LexicalScope*>);
 static const VMFunction PushLexicalEnvInfo =
     FunctionInfo<PushLexicalEnvFn>(jit::PushLexicalEnv, "PushLexicalEnv");
 
 template <typename Handler>
 bool
 BaselineCodeGen<Handler>::emit_JSOP_PUSHLEXICALENV()
 {
@@ -4166,24 +4228,26 @@ static const VMFunction DebugLeaveThenPo
 template <typename Handler>
 bool
 BaselineCodeGen<Handler>::emit_JSOP_POPLEXICALENV()
 {
     prepareVMCall();
 
     masm.loadBaselineFramePtr(BaselineFrameReg, R0.scratchReg());
 
-    if (compileDebugInstrumentation_) {
+    auto ifDebuggee = [this]() {
         pushArg(ImmPtr(pc));
         pushArg(R0.scratchReg());
         return callVM(DebugLeaveThenPopLexicalEnvInfo);
-    }
-
-    pushArg(R0.scratchReg());
-    return callVM(PopLexicalEnvInfo);
+    };
+    auto ifNotDebuggee = [this]() {
+        pushArg(R0.scratchReg());
+        return callVM(PopLexicalEnvInfo);
+    };
+    return emitDebugInstrumentation(ifDebuggee, mozilla::Some(ifNotDebuggee));
 }
 
 typedef bool (*FreshenLexicalEnvFn)(JSContext*, BaselineFrame*);
 static const VMFunction FreshenLexicalEnvInfo =
     FunctionInfo<FreshenLexicalEnvFn>(jit::FreshenLexicalEnv, "FreshenLexicalEnv");
 
 typedef bool (*DebugLeaveThenFreshenLexicalEnvFn)(JSContext*, BaselineFrame*, jsbytecode*);
 static const VMFunction DebugLeaveThenFreshenLexicalEnvInfo =
@@ -4193,24 +4257,26 @@ static const VMFunction DebugLeaveThenFr
 template <typename Handler>
 bool
 BaselineCodeGen<Handler>::emit_JSOP_FRESHENLEXICALENV()
 {
     prepareVMCall();
 
     masm.loadBaselineFramePtr(BaselineFrameReg, R0.scratchReg());
 
-    if (compileDebugInstrumentation_) {
+    auto ifDebuggee = [this]() {
         pushArg(ImmPtr(pc));
         pushArg(R0.scratchReg());
         return callVM(DebugLeaveThenFreshenLexicalEnvInfo);
-    }
-
-    pushArg(R0.scratchReg());
-    return callVM(FreshenLexicalEnvInfo);
+    };
+    auto ifNotDebuggee = [this]() {
+        pushArg(R0.scratchReg());
+        return callVM(FreshenLexicalEnvInfo);
+    };
+    return emitDebugInstrumentation(ifDebuggee, mozilla::Some(ifNotDebuggee));
 }
 
 
 typedef bool (*RecreateLexicalEnvFn)(JSContext*, BaselineFrame*);
 static const VMFunction RecreateLexicalEnvInfo =
     FunctionInfo<RecreateLexicalEnvFn>(jit::RecreateLexicalEnv, "RecreateLexicalEnv");
 
 typedef bool (*DebugLeaveThenRecreateLexicalEnvFn)(JSContext*, BaselineFrame*, jsbytecode*);
@@ -4221,44 +4287,44 @@ static const VMFunction DebugLeaveThenRe
 template <typename Handler>
 bool
 BaselineCodeGen<Handler>::emit_JSOP_RECREATELEXICALENV()
 {
     prepareVMCall();
 
     masm.loadBaselineFramePtr(BaselineFrameReg, R0.scratchReg());
 
-    if (compileDebugInstrumentation_) {
+    auto ifDebuggee = [this]() {
         pushArg(ImmPtr(pc));
         pushArg(R0.scratchReg());
         return callVM(DebugLeaveThenRecreateLexicalEnvInfo);
-    }
-
-    pushArg(R0.scratchReg());
-    return callVM(RecreateLexicalEnvInfo);
+    };
+    auto ifNotDebuggee = [this]() {
+        pushArg(R0.scratchReg());
+        return callVM(RecreateLexicalEnvInfo);
+    };
+    return emitDebugInstrumentation(ifDebuggee, mozilla::Some(ifNotDebuggee));
 }
 
 typedef bool (*DebugLeaveLexicalEnvFn)(JSContext*, BaselineFrame*, jsbytecode*);
 static const VMFunction DebugLeaveLexicalEnvInfo =
     FunctionInfo<DebugLeaveLexicalEnvFn>(jit::DebugLeaveLexicalEnv, "DebugLeaveLexicalEnv");
 
 template <typename Handler>
 bool
 BaselineCodeGen<Handler>::emit_JSOP_DEBUGLEAVELEXICALENV()
 {
-    if (!compileDebugInstrumentation_) {
-        return true;
-    }
-
-    prepareVMCall();
-    masm.loadBaselineFramePtr(BaselineFrameReg, R0.scratchReg());
-    pushArg(ImmPtr(pc));
-    pushArg(R0.scratchReg());
-
-    return callVM(DebugLeaveLexicalEnvInfo);
+    auto ifDebuggee = [this]() {
+        prepareVMCall();
+        masm.loadBaselineFramePtr(BaselineFrameReg, R0.scratchReg());
+        pushArg(ImmPtr(pc));
+        pushArg(R0.scratchReg());
+        return callVM(DebugLeaveLexicalEnvInfo);
+    };
+    return emitDebugInstrumentation(ifDebuggee);
 }
 
 typedef bool (*PushVarEnvFn)(JSContext*, BaselineFrame*, HandleScope);
 static const VMFunction PushVarEnvInfo =
     FunctionInfo<PushVarEnvFn>(jit::PushVarEnv, "PushVarEnv");
 
 template <typename Handler>
 bool
@@ -4380,17 +4446,17 @@ typedef bool (*DebugEpilogueFn)(JSContex
 static const VMFunction DebugEpilogueInfo =
     FunctionInfo<DebugEpilogueFn>(jit::DebugEpilogueOnBaselineReturn,
                                   "DebugEpilogueOnBaselineReturn");
 
 template <typename Handler>
 bool
 BaselineCodeGen<Handler>::emitReturn()
 {
-    if (compileDebugInstrumentation_) {
+    auto ifDebuggee = [this]() {
         // Move return value into the frame's rval slot.
         masm.storeValue(JSReturnOperand, frame.addressOfReturnValue());
         masm.or32(Imm32(BaselineFrame::HAS_RVAL), frame.addressOfFlags());
 
         // Load BaselineFrame pointer in R0.
         frame.syncStack(0);
         masm.loadBaselineFramePtr(BaselineFrameReg, R0.scratchReg());
 
@@ -4400,16 +4466,20 @@ BaselineCodeGen<Handler>::emitReturn()
         if (!callVM(DebugEpilogueInfo)) {
             return false;
         }
 
         // Fix up the RetAddrEntry appended by callVM for on-stack recompilation.
         retAddrEntries_.back().setKind(RetAddrEntry::Kind::DebugEpilogue);
 
         masm.loadValue(frame.addressOfReturnValue(), JSReturnOperand);
+        return true;
+    };
+    if (!emitDebugInstrumentation(ifDebuggee)) {
+        return false;
     }
 
     // Only emit the jump if this JSOP_RETRVAL is not the last instruction.
     // Not needed for last instruction, because last instruction flows
     // into return label.
     if (pc + GetBytecodeLength(pc) < script->codeEnd()) {
         masm.jump(&return_);
     }
@@ -5150,39 +5220,38 @@ BaselineCodeGen<Handler>::emit_JSOP_AWAI
 typedef bool (*DebugAfterYieldFn)(JSContext*, BaselineFrame*, jsbytecode*, bool*);
 static const VMFunction DebugAfterYieldInfo =
     FunctionInfo<DebugAfterYieldFn>(jit::DebugAfterYield, "DebugAfterYield");
 
 template <typename Handler>
 bool
 BaselineCodeGen<Handler>::emit_JSOP_DEBUGAFTERYIELD()
 {
-    if (!compileDebugInstrumentation_) {
+    auto ifDebuggee = [this]() {
+        frame.assertSyncedStack();
+        masm.loadBaselineFramePtr(BaselineFrameReg, R0.scratchReg());
+        prepareVMCall();
+        pushArg(ImmPtr(pc));
+        pushArg(R0.scratchReg());
+        if (!callVM(DebugAfterYieldInfo)) {
+            return false;
+        }
+
+        retAddrEntries_.back().setKind(RetAddrEntry::Kind::DebugAfterYield);
+
+        Label done;
+        masm.branchTest32(Assembler::Zero, ReturnReg, ReturnReg, &done);
+        {
+            masm.loadValue(frame.addressOfReturnValue(), JSReturnOperand);
+            masm.jump(&return_);
+        }
+        masm.bind(&done);
         return true;
-    }
-
-    frame.assertSyncedStack();
-    masm.loadBaselineFramePtr(BaselineFrameReg, R0.scratchReg());
-    prepareVMCall();
-    pushArg(ImmPtr(pc));
-    pushArg(R0.scratchReg());
-    if (!callVM(DebugAfterYieldInfo)) {
-        return false;
-    }
-
-    retAddrEntries_.back().setKind(RetAddrEntry::Kind::DebugAfterYield);
-
-    Label done;
-    masm.branchTest32(Assembler::Zero, ReturnReg, ReturnReg, &done);
-    {
-        masm.loadValue(frame.addressOfReturnValue(), JSReturnOperand);
-        masm.jump(&return_);
-    }
-    masm.bind(&done);
-    return true;
+    };
+    return emitDebugInstrumentation(ifDebuggee);
 }
 
 typedef bool (*FinalSuspendFn)(JSContext*, HandleObject, jsbytecode*);
 static const VMFunction FinalSuspendInfo =
     FunctionInfo<FinalSuspendFn>(jit::FinalSuspend, "FinalSuspend");
 
 template <typename Handler>
 bool
--- a/js/src/jit/BaselineCompiler.h
+++ b/js/src/jit/BaselineCompiler.h
@@ -259,17 +259,16 @@ class BaselineCodeGen
   protected:
     Handler handler;
 
     JSContext* cx;
     JSScript* script;
     jsbytecode* pc;
     StackMacroAssembler masm;
     bool ionCompileable_;
-    bool compileDebugInstrumentation_;
 
     TempAllocator& alloc_;
     BytecodeAnalysis analysis_;
     FrameInfo frame;
 
     js::Vector<RetAddrEntry, 16, SystemAllocPolicy> retAddrEntries_;
     js::Vector<CodeOffset> traceLoggerToggleOffsets_;
 
@@ -283,17 +282,19 @@ class BaselineCodeGen
     uint32_t pushedBeforeCall_;
 #ifdef DEBUG
     bool inCall_;
 #endif
 
     // Whether any on stack arguments are modified.
     bool modifiesArguments_;
 
-    BaselineCodeGen(JSContext* cx, TempAllocator& alloc, JSScript* script);
+    template <typename... HandlerArgs>
+    BaselineCodeGen(JSContext* cx, TempAllocator& alloc, JSScript* script,
+                    HandlerArgs&&... args);
 
     Label* labelOf(jsbytecode* pc) {
         return &labels_[script->pcToOffset(pc)];
     }
 
     MOZ_MUST_USE bool appendRetAddrEntry(RetAddrEntry::Kind kind, uint32_t retOffset) {
         if (!retAddrEntries_.emplaceBack(script->pcToOffset(pc), kind, CodeOffset(retOffset))) {
             ReportOutOfMemory(cx);
@@ -327,16 +328,27 @@ class BaselineCodeGen
     bool callVMNonOp(const VMFunction& fun, CallVMPhase phase=POST_INITIALIZE) {
         if (!callVM(fun, phase)) {
             return false;
         }
         retAddrEntries_.back().setKind(RetAddrEntry::Kind::NonOpCallVM);
         return true;
     }
 
+    // ifDebuggee should be a function emitting code for when the script is a
+    // debuggee script. ifNotDebuggee (if present) is called to emit code for
+    // non-debuggee scripts.
+    template <typename F1, typename F2>
+    MOZ_MUST_USE bool emitDebugInstrumentation(const F1& ifDebuggee,
+                                               const mozilla::Maybe<F2>& ifNotDebuggee);
+    template <typename F>
+    MOZ_MUST_USE bool emitDebugInstrumentation(const F& ifDebuggee) {
+        return emitDebugInstrumentation(ifDebuggee, mozilla::Maybe<F>());
+    }
+
     MOZ_MUST_USE bool emitCheckThis(ValueOperand val, bool reinit=false);
     void emitLoadReturnValue(ValueOperand val);
 
     MOZ_MUST_USE bool emitNextIC();
     MOZ_MUST_USE bool emitInterruptCheck();
     MOZ_MUST_USE bool emitWarmUpCounterIncrement(bool allowOsr=true);
     MOZ_MUST_USE bool emitTraceLoggerResume(Register script, AllocatableGeneralRegisterSet& regs);
 
@@ -379,20 +391,32 @@ class BaselineCodeGen
     Address getEnvironmentCoordinateAddress(Register reg);
 
     void getThisEnvironmentCallee(Register reg);
 };
 
 // Interface used by BaselineCodeGen for BaselineCompiler.
 class BaselineCompilerHandler
 {
+    bool compileDebugInstrumentation_;
+
   public:
+    explicit BaselineCompilerHandler(JSScript* script);
+
+    void setCompileDebugInstrumentation() {
+        compileDebugInstrumentation_ = true;
+    }
+    bool compileDebugInstrumentation() const {
+        return compileDebugInstrumentation_;
+    }
 };
 
-class BaselineCompiler final : private BaselineCodeGen<BaselineCompilerHandler>
+using BaselineCompilerCodeGen = BaselineCodeGen<BaselineCompilerHandler>;
+
+class BaselineCompiler final : private BaselineCompilerCodeGen
 {
     // Stores the native code offset for a bytecode pc.
     struct PCMappingEntry
     {
         uint32_t pcOffset;
         uint32_t nativeOffset;
         PCMappingSlotInfo slotInfo;
 
@@ -429,18 +453,21 @@ class BaselineCompiler final : private B
     }
 
   public:
     BaselineCompiler(JSContext* cx, TempAllocator& alloc, JSScript* script);
     MOZ_MUST_USE bool init();
 
     MethodStatus compile();
 
+    bool compileDebugInstrumentation() const {
+        return handler.compileDebugInstrumentation();
+    }
     void setCompileDebugInstrumentation() {
-        compileDebugInstrumentation_ = true;
+        handler.setCompileDebugInstrumentation();
     }
 
   private:
     PCMappingSlotInfo getStackTopSlotInfo() {
         MOZ_ASSERT(frame.numUnsyncedSlots() <= 2);
         switch (frame.numUnsyncedSlots()) {
           case 0:
             return PCMappingSlotInfo::MakeSlotInfo();
@@ -478,19 +505,22 @@ class BaselineCompiler final : private B
 
     MOZ_MUST_USE bool addPCMappingEntry(bool addIndexEntry);
 };
 
 // Interface used by BaselineCodeGen for BaselineInterpreterGenerator.
 class BaselineInterpreterHandler
 {
   public:
+    explicit BaselineInterpreterHandler();
 };
 
-class BaselineInterpreterGenerator final : private BaselineCodeGen<BaselineInterpreterHandler>
+using BaselineInterpreterCodeGen = BaselineCodeGen<BaselineInterpreterHandler>;
+
+class BaselineInterpreterGenerator final : private BaselineInterpreterCodeGen
 {
   public:
 };
 
 extern const VMFunction NewArrayCopyOnWriteInfo;
 extern const VMFunction ImplicitThisInfo;
 
 } // namespace jit