Bug 1530937 part 8 - Convert some Ion callVMs that already exist in VMFunctionList-inl.h. r=nbp
authorJan de Mooij <jdemooij@mozilla.com>
Wed, 06 Mar 2019 15:56:21 +0000
changeset 520516 73efd5f3bfff6227a6a37da9f9a4aa3ab7e126cf
parent 520515 529da09b7f7e2165081e4a885e056bb2f974c1df
child 520517 e50966a892bdf92398567c99d4ad945b9df8e9f3
push id10862
push userffxbld-merge
push dateMon, 11 Mar 2019 13:01:11 +0000
treeherdermozilla-beta@a2e7f5c935da [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnbp
bugs1530937
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 1530937 part 8 - Convert some Ion callVMs that already exist in VMFunctionList-inl.h. r=nbp Depends on D22278 Differential Revision: https://phabricator.services.mozilla.com/D22279
js/src/jit/CodeGenerator.cpp
js/src/jit/CodeGenerator.h
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -58,16 +58,17 @@
 #include "wasm/WasmGC.h"
 #include "wasm/WasmStubs.h"
 
 #include "builtin/Boolean-inl.h"
 #include "jit/MacroAssembler-inl.h"
 #include "jit/shared/CodeGenerator-shared-inl.h"
 #include "jit/shared/Lowering-shared-inl.h"
 #include "jit/TemplateObject-inl.h"
+#include "jit/VMFunctionList-inl.h"
 #include "vm/Interpreter-inl.h"
 #include "vm/JSScript-inl.h"
 
 using namespace js;
 using namespace js::jit;
 
 using JS::GenericNaN;
 using mozilla::AssertedCast;
@@ -274,37 +275,35 @@ static void StoreAllLiveRegs(MacroAssemb
   HandleRegisterDump<StoreOp>(op, masm, liveRegs, scratch, allRegs.getAny());
 
   masm.pop(scratch);
 }
 #endif  // CHECK_OSIPOINT_REGISTERS
 
 // Before doing any call to Cpp, you should ensure that volatile
 // registers are evicted by the register allocator.
-void CodeGenerator::callVM(const VMFunction& fun, LInstruction* ins,
-                           const Register* dynStack) {
+void CodeGenerator::callVMInternal(const VMFunctionData& fun,
+                                   TrampolinePtr code, LInstruction* ins,
+                                   const Register* dynStack) {
 #ifdef DEBUG
   if (ins->mirRaw()) {
     MOZ_ASSERT(ins->mirRaw()->isInstruction());
     MInstruction* mir = ins->mirRaw()->toInstruction();
     MOZ_ASSERT_IF(mir->needsResumePoint(), mir->resumePoint());
   }
 #endif
 
   // Stack is:
   //    ... frame ...
   //    [args]
 #ifdef DEBUG
   MOZ_ASSERT(pushedArgs_ == fun.explicitArgs);
   pushedArgs_ = 0;
 #endif
 
-  // Get the wrapper of the VM function.
-  TrampolinePtr wrapper = gen->jitRuntime()->getVMWrapper(fun);
-
 #ifdef CHECK_OSIPOINT_REGISTERS
   if (shouldVerifyOsiPointRegs(ins->safepoint())) {
     StoreAllLiveRegs(masm, ins->safepoint()->liveRegs());
   }
 #endif
 
   // Push an exit frame descriptor. If |dynStack| is a valid pointer to a
   // register, then its value is added to the value of the |framePushed()| to
@@ -317,29 +316,47 @@ void CodeGenerator::callVM(const VMFunct
   } else {
     masm.pushStaticFrameDescriptor(FrameType::IonJS, ExitFrameLayout::Size());
   }
 
   // Call the wrapper function.  The wrapper is in charge to unwind the stack
   // when returning from the call.  Failures are handled with exceptions based
   // on the return value of the C functions.  To guard the outcome of the
   // returned value, use another LIR instruction.
-  uint32_t callOffset = masm.callJit(wrapper);
+  uint32_t callOffset = masm.callJit(code);
   markSafepointAt(callOffset, ins);
 
   // Remove rest of the frame left on the stack. We remove the return address
   // which is implicitly poped when returning.
   int framePop = sizeof(ExitFrameLayout) - sizeof(void*);
 
   // Pop arguments from framePushed.
   masm.implicitPop(fun.explicitStackSlots() * sizeof(void*) + framePop);
   // Stack is:
   //    ... frame ...
 }
 
+void CodeGenerator::callVMInternal(VMFunctionId id, LInstruction* ins,
+                                   const Register* dynStack) {
+  TrampolinePtr code = gen->jitRuntime()->getVMWrapper(id);
+  callVMInternal(GetVMFunction(id), code, ins, dynStack);
+}
+
+void CodeGenerator::callVM(const VMFunction& fun, LInstruction* ins,
+                           const Register* dynStack) {
+  TrampolinePtr code = gen->jitRuntime()->getVMWrapper(fun);
+  callVMInternal(fun, code, ins, dynStack);
+}
+
+template <typename Fn, Fn fn>
+void CodeGenerator::callVM(LInstruction* ins, const Register* dynStack) {
+  VMFunctionId id = VMFunctionToId<Fn, fn>::id;
+  callVMInternal(id, ins, dynStack);
+}
+
 // ArgSeq store arguments for OutOfLineCallVM.
 //
 // OutOfLineCallVM are created with "oolCallVM" function. The third argument of
 // this function is an instance of a class which provides a "generate" in charge
 // of pushing the argument, with "pushArg", for a VMFunction.
 //
 // Such list of arguments can be created by using the "ArgList" function which
 // creates one instance of "ArgSeq", where the type of the arguments are
@@ -3413,59 +3430,51 @@ void CodeGenerator::visitUnaryCache(LUna
   TypedOrValueRegister input =
       TypedOrValueRegister(ToValue(lir, LUnaryCache::Input));
   ValueOperand output = ToOutValue(lir);
 
   IonUnaryArithIC ic(liveRegs, input, output);
   addIC(lir, allocateIC(ic));
 }
 
-typedef JSFunction* (*MakeDefaultConstructorFn)(JSContext*, HandleScript,
-                                                jsbytecode*, HandleObject);
-static const VMFunction MakeDefaultConstructorInfo =
-    FunctionInfo<MakeDefaultConstructorFn>(js::MakeDefaultConstructor,
-                                           "MakeDefaultConstructor");
-
 void CodeGenerator::visitClassConstructor(LClassConstructor* lir) {
   pushArg(ImmPtr(nullptr));
   pushArg(ImmPtr(lir->mir()->pc()));
   pushArg(ImmGCPtr(current->mir()->info().script()));
-  callVM(MakeDefaultConstructorInfo, lir);
-}
-
-typedef JSObject* (*GetOrCreateModuleMetaObjectFn)(JSContext*, HandleObject);
-static const VMFunction GetOrCreateModuleMetaObjectInfo =
-    FunctionInfo<GetOrCreateModuleMetaObjectFn>(js::GetOrCreateModuleMetaObject,
-                                                "GetOrCreateModuleMetaObject");
+
+  using Fn =
+      JSFunction* (*)(JSContext*, HandleScript, jsbytecode*, HandleObject);
+  callVM<Fn, js::MakeDefaultConstructor>(lir);
+}
 
 void CodeGenerator::visitModuleMetadata(LModuleMetadata* lir) {
   pushArg(ImmPtr(lir->mir()->module()));
-  callVM(GetOrCreateModuleMetaObjectInfo, lir);
-}
-
-typedef JSObject* (*StartDynamicModuleImportFn)(JSContext*, HandleScript,
-                                                HandleValue);
-static const VMFunction StartDynamicModuleImportInfo =
-    FunctionInfo<StartDynamicModuleImportFn>(js::StartDynamicModuleImport,
-                                             "StartDynamicModuleImport");
+
+  using Fn = JSObject* (*)(JSContext*, HandleObject);
+  callVM<Fn, js::GetOrCreateModuleMetaObject>(lir);
+}
 
 void CodeGenerator::visitDynamicImport(LDynamicImport* lir) {
   pushArg(ToValue(lir, LDynamicImport::SpecifierIndex));
   pushArg(ImmGCPtr(current->mir()->info().script()));
-  callVM(StartDynamicModuleImportInfo, lir);
+
+  using Fn = JSObject* (*)(JSContext*, HandleScript, HandleValue);
+  callVM<Fn, js::StartDynamicModuleImport>(lir);
 }
 
 typedef JSObject* (*LambdaFn)(JSContext*, HandleFunction, HandleObject);
 static const VMFunction LambdaInfo =
     FunctionInfo<LambdaFn>(js::Lambda, "Lambda");
 
 void CodeGenerator::visitLambdaForSingleton(LLambdaForSingleton* lir) {
   pushArg(ToRegister(lir->environmentChain()));
   pushArg(ImmGCPtr(lir->mir()->info().funUnsafe()));
-  callVM(LambdaInfo, lir);
+
+  using Fn = JSObject* (*)(JSContext*, HandleFunction, HandleObject);
+  callVM<Fn, js::Lambda>(lir);
 }
 
 void CodeGenerator::visitLambda(LLambda* lir) {
   Register envChain = ToRegister(lir->environmentChain());
   Register output = ToRegister(lir->output());
   Register tempReg = ToRegister(lir->temp());
   const LambdaFunctionInfo& info = lir->mir()->info();
 
@@ -3606,27 +3615,24 @@ void CodeGenerator::emitLambdaInit(Regis
                 Address(output, JSFunction::offsetOfScriptOrLazyScript()));
   masm.storePtr(envChain, Address(output, JSFunction::offsetOfEnvironment()));
   // No post barrier needed because output is guaranteed to be allocated in
   // the nursery.
   masm.storePtr(ImmGCPtr(info.funUnsafe()->displayAtom()),
                 Address(output, JSFunction::offsetOfAtom()));
 }
 
-typedef bool (*SetFunNameFn)(JSContext*, HandleFunction, HandleValue,
-                             FunctionPrefixKind);
-static const VMFunction SetFunNameInfo =
-    FunctionInfo<SetFunNameFn>(js::SetFunctionName, "SetFunName");
-
 void CodeGenerator::visitSetFunName(LSetFunName* lir) {
   pushArg(Imm32(lir->mir()->prefixKind()));
   pushArg(ToValue(lir, LSetFunName::NameValue));
   pushArg(ToRegister(lir->fun()));
 
-  callVM(SetFunNameInfo, lir);
+  using Fn =
+      bool (*)(JSContext*, HandleFunction, HandleValue, FunctionPrefixKind);
+  callVM<Fn, js::SetFunctionName>(lir);
 }
 
 void CodeGenerator::visitOsiPoint(LOsiPoint* lir) {
   // Note: markOsiPoint ensures enough space exists between the last
   // LOsiPoint and this one to patch adjacent call instructions.
 
   MOZ_ASSERT(masm.framePushed() == frameSize());
 
@@ -5898,65 +5904,54 @@ void CodeGenerator::visitCheckOverRecurs
 
   // Conditional forward (unlikely) branch to failure.
   const void* limitAddr = gen->runtime->addressOfJitStackLimit();
   masm.branchStackPtrRhs(Assembler::AboveOrEqual, AbsoluteAddress(limitAddr),
                          ool->entry());
   masm.bind(ool->rejoin());
 }
 
-typedef bool (*DefVarFn)(JSContext*, HandleObject, HandleScript, jsbytecode*);
-static const VMFunction DefVarInfo =
-    FunctionInfo<DefVarFn>(DefVarOperation, "DefVarOperation");
-
 void CodeGenerator::visitDefVar(LDefVar* lir) {
   Register envChain = ToRegister(lir->environmentChain());
 
   JSScript* script = current->mir()->info().script();
   jsbytecode* pc = lir->mir()->resumePoint()->pc();
 
   pushArg(ImmPtr(pc));        // jsbytecode*
   pushArg(ImmGCPtr(script));  // JSScript*
   pushArg(envChain);          // JSObject*
 
-  callVM(DefVarInfo, lir);
-}
-
-typedef bool (*DefLexicalFn)(JSContext*, HandleObject, HandleScript,
-                             jsbytecode*);
-static const VMFunction DefLexicalInfo =
-    FunctionInfo<DefLexicalFn>(DefLexicalOperation, "DefLexicalOperation");
+  using Fn = bool (*)(JSContext*, HandleObject, HandleScript, jsbytecode*);
+  callVM<Fn, DefVarOperation>(lir);
+}
 
 void CodeGenerator::visitDefLexical(LDefLexical* lir) {
   Register envChain = ToRegister(lir->environmentChain());
 
   JSScript* script = current->mir()->info().script();
   jsbytecode* pc = lir->mir()->resumePoint()->pc();
 
   pushArg(ImmPtr(pc));        // jsbytecode*
   pushArg(ImmGCPtr(script));  // JSScript*
   pushArg(envChain);          // JSObject*
 
-  callVM(DefLexicalInfo, lir);
-}
-
-typedef bool (*DefFunOperationFn)(JSContext*, HandleScript, HandleObject,
-                                  HandleFunction);
-static const VMFunction DefFunOperationInfo =
-    FunctionInfo<DefFunOperationFn>(DefFunOperation, "DefFunOperation");
+  using Fn = bool (*)(JSContext*, HandleObject, HandleScript, jsbytecode*);
+  callVM<Fn, DefLexicalOperation>(lir);
+}
 
 void CodeGenerator::visitDefFun(LDefFun* lir) {
   Register envChain = ToRegister(lir->environmentChain());
 
   Register fun = ToRegister(lir->fun());
   pushArg(fun);
   pushArg(envChain);
   pushArg(ImmGCPtr(current->mir()->info().script()));
 
-  callVM(DefFunOperationInfo, lir);
+  using Fn = bool (*)(JSContext*, HandleScript, HandleObject, HandleFunction);
+  callVM<Fn, DefFunOperation>(lir);
 }
 
 typedef bool (*CheckOverRecursedFn)(JSContext*);
 static const VMFunction CheckOverRecursedInfo =
     FunctionInfo<CheckOverRecursedFn>(CheckOverRecursed, "CheckOverRecursed");
 
 void CodeGenerator::visitCheckOverRecursedFailure(
     CheckOverRecursedFailure* ool) {
@@ -7160,64 +7155,52 @@ void CodeGenerator::visitInitElem(LInitE
   pushArg(ToValue(lir, LInitElem::ValueIndex));
   pushArg(ToValue(lir, LInitElem::IdIndex));
   pushArg(objReg);
   pushArg(ImmPtr(lir->mir()->resumePoint()->pc()));
 
   callVM(InitElemInfo, lir);
 }
 
-typedef bool (*InitElemGetterSetterFn)(JSContext*, jsbytecode*, HandleObject,
-                                       HandleValue, HandleObject);
-static const VMFunction InitElemGetterSetterInfo =
-    FunctionInfo<InitElemGetterSetterFn>(InitElemGetterSetterOperation,
-                                         "InitElemGetterSetterOperation");
-
 void CodeGenerator::visitInitElemGetterSetter(LInitElemGetterSetter* lir) {
   Register obj = ToRegister(lir->object());
   Register value = ToRegister(lir->value());
 
   pushArg(value);
   pushArg(ToValue(lir, LInitElemGetterSetter::IdIndex));
   pushArg(obj);
   pushArg(ImmPtr(lir->mir()->resumePoint()->pc()));
 
-  callVM(InitElemGetterSetterInfo, lir);
-}
-
-typedef bool (*MutatePrototypeFn)(JSContext* cx, HandlePlainObject obj,
-                                  HandleValue value);
-static const VMFunction MutatePrototypeInfo =
-    FunctionInfo<MutatePrototypeFn>(MutatePrototype, "MutatePrototype");
+  using Fn = bool (*)(JSContext*, jsbytecode*, HandleObject, HandleValue,
+                      HandleObject);
+  callVM<Fn, InitElemGetterSetterOperation>(lir);
+}
 
 void CodeGenerator::visitMutateProto(LMutateProto* lir) {
   Register objReg = ToRegister(lir->getObject());
 
   pushArg(ToValue(lir, LMutateProto::ValueIndex));
   pushArg(objReg);
 
-  callVM(MutatePrototypeInfo, lir);
-}
-
-typedef bool (*InitPropGetterSetterFn)(JSContext*, jsbytecode*, HandleObject,
-                                       HandlePropertyName, HandleObject);
-static const VMFunction InitPropGetterSetterInfo =
-    FunctionInfo<InitPropGetterSetterFn>(InitPropGetterSetterOperation,
-                                         "InitPropGetterSetterOperation");
+  using Fn = bool (*)(JSContext * cx, HandlePlainObject obj, HandleValue value);
+  callVM<Fn, MutatePrototype>(lir);
+}
 
 void CodeGenerator::visitInitPropGetterSetter(LInitPropGetterSetter* lir) {
   Register obj = ToRegister(lir->object());
   Register value = ToRegister(lir->value());
 
   pushArg(value);
   pushArg(ImmGCPtr(lir->mir()->name()));
   pushArg(obj);
   pushArg(ImmPtr(lir->mir()->resumePoint()->pc()));
 
-  callVM(InitPropGetterSetterInfo, lir);
+  using Fn = bool (*)(JSContext*, jsbytecode*, HandleObject, HandlePropertyName,
+                      HandleObject);
+  callVM<Fn, InitPropGetterSetterOperation>(lir);
 }
 
 typedef bool (*CreateThisFn)(JSContext* cx, HandleObject callee,
                              HandleObject newTarget, MutableHandleValue rval);
 static const VMFunction CreateThisInfoCodeGen =
     FunctionInfo<CreateThisFn>(CreateThis, "CreateThis");
 
 void CodeGenerator::visitCreateThis(LCreateThis* lir) {
@@ -7436,25 +7419,23 @@ void CodeGenerator::visitComputeThis(LCo
   OutOfLineCode* ool = oolCallVM(BoxNonStrictThisInfo, lir, ArgList(value),
                                  StoreValueTo(output));
 
   masm.branchTestObject(Assembler::NotEqual, value, ool->entry());
   masm.moveValue(value, output);
   masm.bind(ool->rejoin());
 }
 
-typedef bool (*ImplicitThisFn)(JSContext*, HandleObject, HandlePropertyName,
-                               MutableHandleValue);
-static const VMFunction ImplicitThisInfo = FunctionInfo<ImplicitThisFn>(
-    ImplicitThisOperation, "ImplicitThisOperation");
-
 void CodeGenerator::visitImplicitThis(LImplicitThis* lir) {
   pushArg(ImmGCPtr(lir->mir()->name()));
   pushArg(ToRegister(lir->env()));
-  callVM(ImplicitThisInfo, lir);
+
+  using Fn = bool (*)(JSContext*, HandleObject, HandlePropertyName,
+                      MutableHandleValue);
+  callVM<Fn, ImplicitThisOperation>(lir);
 }
 
 void CodeGenerator::visitArrowNewTarget(LArrowNewTarget* lir) {
   Register callee = ToRegister(lir->callee());
   ValueOperand output = ToOutValue(lir);
   masm.loadValue(
       Address(callee, FunctionExtended::offsetOfArrowNewTargetSlot()), output);
 }
@@ -11497,23 +11478,21 @@ void CodeGenerator::visitOutOfLineUnboxF
     masm.branchTestInt32(Assembler::NotEqual, value, &bail);
     bailoutFrom(&bail, ins->snapshot());
   }
   masm.int32ValueToFloatingPoint(value, ToFloatRegister(ins->output()),
                                  ins->type());
   masm.jump(ool->rejoin());
 }
 
-typedef JSObject* (*BindVarFn)(JSContext*, JSObject*);
-static const VMFunction BindVarInfo =
-    FunctionInfo<BindVarFn>(BindVarOperation, "BindVarOperation");
-
 void CodeGenerator::visitCallBindVar(LCallBindVar* lir) {
   pushArg(ToRegister(lir->environmentChain()));
-  callVM(BindVarInfo, lir);
+
+  using Fn = JSObject* (*)(JSContext*, JSObject*);
+  callVM<Fn, BindVarOperation>(lir);
 }
 
 typedef bool (*GetPropertyFn)(JSContext*, HandleValue, HandlePropertyName,
                               MutableHandleValue);
 static const VMFunction GetPropertyInfo =
     FunctionInfo<GetPropertyFn>(GetProperty, "GetProperty");
 
 void CodeGenerator::visitCallGetProperty(LCallGetProperty* lir) {
@@ -11906,23 +11885,21 @@ void CodeGenerator::visitSetPropertyCach
                                                   ins->mir()->value()->type());
 
   addSetPropertyCache(ins, liveRegs, objReg, temp, tempDouble, tempF32, id,
                       value, ins->mir()->strict(),
                       ins->mir()->needsPostBarrier(),
                       ins->mir()->needsTypeBarrier(), ins->mir()->guardHoles());
 }
 
-typedef bool (*ThrowFn)(JSContext*, HandleValue);
-static const VMFunction ThrowInfoCodeGen =
-    FunctionInfo<ThrowFn>(js::ThrowOperation, "ThrowOperation");
-
 void CodeGenerator::visitThrow(LThrow* lir) {
   pushArg(ToValue(lir, LThrow::Value));
-  callVM(ThrowInfoCodeGen, lir);
+
+  using Fn = bool (*)(JSContext*, HandleValue);
+  callVM<Fn, js::ThrowOperation>(lir);
 }
 
 typedef bool (*BitNotFn)(JSContext*, MutableHandleValue, MutableHandleValue);
 static const VMFunction BitNotInfo = FunctionInfo<BitNotFn>(BitNot, "BitNot");
 
 void CodeGenerator::visitBitNotV(LBitNotV* lir) {
   pushArg(ToValue(lir, LBitNotV::Input));
   callVM(BitNotInfo, lir);
@@ -12163,24 +12140,22 @@ void CodeGenerator::visitOutOfLineTypeOf
   masm.passABIArg(output);
   masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, jit::TypeOfObject));
   masm.storeCallPointerResult(output);
   restoreVolatile(output);
 
   masm.jump(ool->rejoin());
 }
 
-typedef JSObject* (*ToAsyncIterFn)(JSContext*, HandleObject, HandleValue);
-static const VMFunction ToAsyncIterInfo =
-    FunctionInfo<ToAsyncIterFn>(js::CreateAsyncFromSyncIterator, "ToAsyncIter");
-
 void CodeGenerator::visitToAsyncIter(LToAsyncIter* lir) {
   pushArg(ToValue(lir, LToAsyncIter::NextMethodIndex));
   pushArg(ToRegister(lir->iterator()));
-  callVM(ToAsyncIterInfo, lir);
+
+  using Fn = JSObject* (*)(JSContext*, HandleObject, HandleValue);
+  callVM<Fn, js::CreateAsyncFromSyncIterator>(lir);
 }
 
 typedef bool (*ToIdFn)(JSContext*, HandleValue, MutableHandleValue);
 static const VMFunction ToIdInfo =
     FunctionInfo<ToIdFn>(ToIdOperation, "ToIdOperation");
 
 void CodeGenerator::visitToIdV(LToIdV* lir) {
   Label notInt32;
@@ -13892,25 +13867,22 @@ void CodeGenerator::visitRecompileCheck(
 void CodeGenerator::visitLexicalCheck(LLexicalCheck* ins) {
   ValueOperand inputValue = ToValue(ins, LLexicalCheck::Input);
   Label bail;
   masm.branchTestMagicValue(Assembler::Equal, inputValue,
                             JS_UNINITIALIZED_LEXICAL, &bail);
   bailoutFrom(&bail, ins->snapshot());
 }
 
-typedef bool (*ThrowRuntimeLexicalErrorFn)(JSContext*, unsigned);
-static const VMFunction ThrowRuntimeLexicalErrorInfo =
-    FunctionInfo<ThrowRuntimeLexicalErrorFn>(ThrowRuntimeLexicalError,
-                                             "ThrowRuntimeLexicalError");
-
 void CodeGenerator::visitThrowRuntimeLexicalError(
     LThrowRuntimeLexicalError* ins) {
   pushArg(Imm32(ins->mir()->errorNumber()));
-  callVM(ThrowRuntimeLexicalErrorInfo, ins);
+
+  using Fn = bool (*)(JSContext*, unsigned);
+  callVM<Fn, jit::ThrowRuntimeLexicalError>(ins);
 }
 
 typedef bool (*GlobalNameConflictsCheckFromIonFn)(JSContext*, HandleScript);
 static const VMFunction GlobalNameConflictsCheckFromIonInfo =
     FunctionInfo<GlobalNameConflictsCheckFromIonFn>(
         GlobalNameConflictsCheckFromIon, "GlobalNameConflictsCheckFromIon");
 
 void CodeGenerator::visitGlobalNameConflictsCheck(
@@ -13999,40 +13971,33 @@ void CodeGenerator::visitCheckIsObj(LChe
 
   OutOfLineCode* ool =
       oolCallVM(ThrowCheckIsObjectInfo, ins,
                 ArgList(Imm32(ins->mir()->checkKind())), StoreNothing());
   masm.branchTestObject(Assembler::NotEqual, checkValue, ool->entry());
   masm.bind(ool->rejoin());
 }
 
-typedef bool (*ThrowObjCoercibleFn)(JSContext*, HandleValue);
-static const VMFunction ThrowObjectCoercibleInfo =
-    FunctionInfo<ThrowObjCoercibleFn>(ThrowObjectCoercible,
-                                      "ThrowObjectCoercible");
-
 void CodeGenerator::visitCheckObjCoercible(LCheckObjCoercible* ins) {
   ValueOperand checkValue = ToValue(ins, LCheckObjCoercible::CheckValue);
   Label fail, done;
   masm.branchTestNull(Assembler::Equal, checkValue, &fail);
   masm.branchTestUndefined(Assembler::NotEqual, checkValue, &done);
   masm.bind(&fail);
   pushArg(checkValue);
-  callVM(ThrowObjectCoercibleInfo, ins);
+  using Fn = bool (*)(JSContext*, HandleValue);
+  callVM<Fn, ThrowObjectCoercible>(ins);
   masm.bind(&done);
 }
 
-typedef bool (*CheckSelfHostedFn)(JSContext*, HandleValue);
-static const VMFunction CheckSelfHostedInfo = FunctionInfo<CheckSelfHostedFn>(
-    js::Debug_CheckSelfHosted, "Debug_CheckSelfHosted");
-
 void CodeGenerator::visitDebugCheckSelfHosted(LDebugCheckSelfHosted* ins) {
   ValueOperand checkValue = ToValue(ins, LDebugCheckSelfHosted::CheckValue);
   pushArg(checkValue);
-  callVM(CheckSelfHostedInfo, ins);
+  using Fn = bool (*)(JSContext*, HandleValue);
+  callVM<Fn, js::Debug_CheckSelfHosted>(ins);
 }
 
 void CodeGenerator::visitRandom(LRandom* ins) {
   using mozilla::non_crypto::XorShift128PlusRNG;
 
   FloatRegister output = ToFloatRegister(ins->output());
   Register tempReg = ToRegister(ins->temp0());
 
--- a/js/src/jit/CodeGenerator.h
+++ b/js/src/jit/CodeGenerator.h
@@ -71,19 +71,27 @@ class CodeGenerator final : public CodeG
                                           MIRType type);
 
 #ifdef CHECK_OSIPOINT_REGISTERS
   void resetOsiPointRegs(LSafepoint* safepoint);
   bool shouldVerifyOsiPointRegs(LSafepoint* safepoint);
   void verifyOsiPointRegs(LSafepoint* safepoint);
 #endif
 
-  void callVM(const VMFunction& f, LInstruction* ins,
+  void callVMInternal(const VMFunctionData& fun, TrampolinePtr code,
+                      LInstruction* ins, const Register* dynStack);
+  void callVMInternal(VMFunctionId id, LInstruction* ins,
+                      const Register* dynStack);
+
+  void callVM(const VMFunction& fun, LInstruction* ins,
               const Register* dynStack = nullptr);
 
+  template <typename Fn, Fn fn>
+  void callVM(LInstruction* ins, const Register* dynStack = nullptr);
+
   template <class ArgSeq, class StoreOutputTo>
   inline OutOfLineCode* oolCallVM(const VMFunction& fun, LInstruction* ins,
                                   const ArgSeq& args, const StoreOutputTo& out);
 
  public:
   CodeGenerator(MIRGenerator* gen, LIRGraph* graph,
                 MacroAssembler* masm = nullptr);
   ~CodeGenerator();