Bug 1530937 part 13 - Convert Ion oolCallVMs and remove old CodeGenerator callVM overload. r=nbp
authorJan de Mooij <jdemooij@mozilla.com>
Mon, 11 Mar 2019 13:30:29 +0000
changeset 521408 16b947cb279a
parent 521407 7592f919079f
child 521409 7d64886307e5
push id10866
push usernerli@mozilla.com
push dateTue, 12 Mar 2019 18:59:09 +0000
treeherdermozilla-beta@445c24a51727 [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 13 - Convert Ion oolCallVMs and remove old CodeGenerator callVM overload. r=nbp Differential Revision: https://phabricator.services.mozilla.com/D22946
js/src/builtin/Array.cpp
js/src/builtin/Array.h
js/src/jit/CodeGenerator.cpp
js/src/jit/CodeGenerator.h
js/src/jit/VMFunctionList-inl.h
js/src/jit/VMFunctions.cpp
js/src/jit/VMFunctions.h
--- a/js/src/builtin/Array.cpp
+++ b/js/src/builtin/Array.cpp
@@ -89,16 +89,20 @@ bool JS::IsArray(JSContext* cx, HandleOb
                               JSMSG_PROXY_REVOKED);
     return false;
   }
 
   *isArray = answer == IsArrayAnswer::Array;
   return true;
 }
 
+bool js::IsArrayFromJit(JSContext* cx, HandleObject obj, bool* isArray) {
+  return JS::IsArray(cx, obj, isArray);
+}
+
 // ES2017 7.1.15 ToLength, but clamped to the [0,2^32-2] range.
 static bool ToLengthClamped(JSContext* cx, HandleValue v, uint32_t* out) {
   if (v.isInt32()) {
     int32_t i = v.toInt32();
     *out = i < 0 ? 0 : i;
     return true;
   }
   double d;
--- a/js/src/builtin/Array.h
+++ b/js/src/builtin/Array.h
@@ -182,16 +182,19 @@ extern bool ArrayConstructor(JSContext* 
 // Like Array constructor, but doesn't perform GetPrototypeFromConstructor.
 extern bool array_construct(JSContext* cx, unsigned argc, Value* vp);
 
 extern bool IsCrossRealmArrayConstructor(JSContext* cx, const Value& v,
                                          bool* result);
 
 extern bool ObjectMayHaveExtraIndexedProperties(JSObject* obj);
 
+// JS::IsArray has multiple overloads, use js::IsArrayFromJit to disambiguate.
+extern bool IsArrayFromJit(JSContext* cx, HandleObject obj, bool* isArray);
+
 class MOZ_NON_TEMPORARY_CLASS ArraySpeciesLookup final {
   /*
    * An ArraySpeciesLookup holds the following:
    *
    *  Array.prototype (arrayProto_)
    *      To ensure that the incoming array has the standard proto.
    *
    *  Array.prototype's shape (arrayProtoShape_)
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -275,19 +275,21 @@ 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::callVMInternal(const VMFunctionData& fun,
-                                   TrampolinePtr code, LInstruction* ins,
+void CodeGenerator::callVMInternal(VMFunctionId id, LInstruction* ins,
                                    const Register* dynStack) {
+  TrampolinePtr code = gen->jitRuntime()->getVMWrapper(id);
+  const VMFunctionData& fun = GetVMFunction(id);
+
 #ifdef DEBUG
   if (ins->mirRaw()) {
     MOZ_ASSERT(ins->mirRaw()->isInstruction());
     MInstruction* mir = ins->mirRaw()->toInstruction();
     MOZ_ASSERT_IF(mir->needsResumePoint(), mir->resumePoint());
   }
 #endif
 
@@ -329,28 +331,16 @@ void CodeGenerator::callVMInternal(const
   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.
 //
@@ -475,63 +465,65 @@ class StoreValueTo_ {
   }
 };
 
 template <typename Output>
 StoreValueTo_<Output> StoreValueTo(const Output& out) {
   return StoreValueTo_<Output>(out);
 }
 
-template <class ArgSeq, class StoreOutputTo>
+template <typename Fn, Fn fn, class ArgSeq, class StoreOutputTo>
 class OutOfLineCallVM : public OutOfLineCodeBase<CodeGenerator> {
  private:
   LInstruction* lir_;
-  const VMFunction& fun_;
   ArgSeq args_;
   StoreOutputTo out_;
 
  public:
-  OutOfLineCallVM(LInstruction* lir, const VMFunction& fun, const ArgSeq& args,
+  OutOfLineCallVM(LInstruction* lir, const ArgSeq& args,
                   const StoreOutputTo& out)
-      : lir_(lir), fun_(fun), args_(args), out_(out) {}
+      : lir_(lir), args_(args), out_(out) {}
 
   void accept(CodeGenerator* codegen) override {
     codegen->visitOutOfLineCallVM(this);
   }
 
   LInstruction* lir() const { return lir_; }
-  const VMFunction& function() const { return fun_; }
   const ArgSeq& args() const { return args_; }
   const StoreOutputTo& out() const { return out_; }
 };
 
-template <class ArgSeq, class StoreOutputTo>
-OutOfLineCode* CodeGenerator::oolCallVM(const VMFunction& fun,
-                                        LInstruction* lir, const ArgSeq& args,
+template <typename Fn, Fn fn, class ArgSeq, class StoreOutputTo>
+OutOfLineCode* CodeGenerator::oolCallVM(LInstruction* lir, const ArgSeq& args,
                                         const StoreOutputTo& out) {
   MOZ_ASSERT(lir->mirRaw());
   MOZ_ASSERT(lir->mirRaw()->isInstruction());
+
+#ifdef DEBUG
+  VMFunctionId id = VMFunctionToId<Fn, fn>::id;
+  const VMFunctionData& fun = GetVMFunction(id);
   MOZ_ASSERT(fun.explicitArgs == args.numArgs);
   MOZ_ASSERT(fun.returnsData() !=
              (mozilla::IsSame<StoreOutputTo, StoreNothing>::value));
-
-  OutOfLineCode* ool =
-      new (alloc()) OutOfLineCallVM<ArgSeq, StoreOutputTo>(lir, fun, args, out);
+#endif
+
+  OutOfLineCode* ool = new (alloc())
+      OutOfLineCallVM<Fn, fn, ArgSeq, StoreOutputTo>(lir, args, out);
   addOutOfLineCode(ool, lir->mirRaw()->toInstruction());
   return ool;
 }
 
-template <class ArgSeq, class StoreOutputTo>
+template <typename Fn, Fn fn, class ArgSeq, class StoreOutputTo>
 void CodeGenerator::visitOutOfLineCallVM(
-    OutOfLineCallVM<ArgSeq, StoreOutputTo>* ool) {
+    OutOfLineCallVM<Fn, fn, ArgSeq, StoreOutputTo>* ool) {
   LInstruction* lir = ool->lir();
 
   saveLive(lir);
   ool->args().generate(this);
-  callVM(ool->function(), lir);
+  callVM<Fn, fn>(lir);
   ool->out().generate(this);
   restoreLiveIgnore(lir, ool->out().clobbered());
   masm.jump(ool->rejoin());
 }
 
 class OutOfLineICFallback : public OutOfLineCodeBase<CodeGenerator> {
  private:
   LInstruction* lir_;
@@ -862,20 +854,16 @@ CodeGenerator::CodeGenerator(MIRGenerato
                              MacroAssembler* masm)
     : CodeGeneratorSpecific(gen, graph, masm),
       ionScriptLabels_(gen->alloc()),
       scriptCounts_(nullptr),
       realmStubsToReadBarrier_(0) {}
 
 CodeGenerator::~CodeGenerator() { js_delete(scriptCounts_); }
 
-typedef bool (*StringToNumberFn)(JSContext*, JSString*, double*);
-static const VMFunction StringToNumberInfo =
-    FunctionInfo<StringToNumberFn>(StringToNumber, "StringToNumber");
-
 void CodeGenerator::visitValueToInt32(LValueToInt32* lir) {
   ValueOperand operand = ToValue(lir, LValueToInt32::Input);
   Register output = ToRegister(lir->output());
   FloatRegister temp = ToFloatRegister(lir->tempFloat());
 
   MDefinition* input;
   if (lir->mode() == LValueToInt32::NORMAL) {
     input = lir->mirNormal()->input();
@@ -889,19 +877,19 @@ void CodeGenerator::visitValueToInt32(LV
 
     // We can only handle strings in truncation contexts, like bitwise
     // operations.
     Label* stringEntry;
     Label* stringRejoin;
     Register stringReg;
     if (input->mightBeType(MIRType::String)) {
       stringReg = ToRegister(lir->temp());
-      OutOfLineCode* oolString =
-          oolCallVM(StringToNumberInfo, lir, ArgList(stringReg),
-                    StoreFloatRegisterTo(temp));
+      using Fn = bool (*)(JSContext*, JSString*, double*);
+      OutOfLineCode* oolString = oolCallVM<Fn, StringToNumber>(
+          lir, ArgList(stringReg), StoreFloatRegisterTo(temp));
       stringEntry = oolString->entry();
       stringRejoin = oolString->rejoin();
     } else {
       stringReg = InvalidReg;
       stringEntry = nullptr;
       stringRejoin = nullptr;
     }
 
@@ -1549,61 +1537,52 @@ void CodeGenerator::emitIntToString(Regi
                                     Label* ool) {
   masm.boundsCheck32PowerOfTwo(input, StaticStrings::INT_STATIC_LIMIT, ool);
 
   // Fast path for small integers.
   masm.movePtr(ImmPtr(&gen->runtime->staticStrings().intStaticTable), output);
   masm.loadPtr(BaseIndex(output, input, ScalePointer), output);
 }
 
-typedef JSFlatString* (*IntToStringFn)(JSContext*, int);
-static const VMFunction IntToStringInfo =
-    FunctionInfo<IntToStringFn>(Int32ToString<CanGC>, "Int32ToString");
-
 void CodeGenerator::visitIntToString(LIntToString* lir) {
   Register input = ToRegister(lir->input());
   Register output = ToRegister(lir->output());
 
-  OutOfLineCode* ool =
-      oolCallVM(IntToStringInfo, lir, ArgList(input), StoreRegisterTo(output));
+  using Fn = JSFlatString* (*)(JSContext*, int);
+  OutOfLineCode* ool = oolCallVM<Fn, Int32ToString<CanGC>>(
+      lir, ArgList(input), StoreRegisterTo(output));
 
   emitIntToString(input, output, ool->entry());
 
   masm.bind(ool->rejoin());
 }
 
-typedef JSString* (*DoubleToStringFn)(JSContext*, double);
-static const VMFunction DoubleToStringInfo =
-    FunctionInfo<DoubleToStringFn>(NumberToString<CanGC>, "NumberToString");
-
 void CodeGenerator::visitDoubleToString(LDoubleToString* lir) {
   FloatRegister input = ToFloatRegister(lir->input());
   Register temp = ToRegister(lir->tempInt());
   Register output = ToRegister(lir->output());
 
-  OutOfLineCode* ool = oolCallVM(DoubleToStringInfo, lir, ArgList(input),
-                                 StoreRegisterTo(output));
+  using Fn = JSString* (*)(JSContext*, double);
+  OutOfLineCode* ool = oolCallVM<Fn, NumberToString<CanGC>>(
+      lir, ArgList(input), StoreRegisterTo(output));
 
   // Try double to integer conversion and run integer to string code.
   masm.convertDoubleToInt32(input, temp, ool->entry(), true);
   emitIntToString(temp, output, ool->entry());
 
   masm.bind(ool->rejoin());
 }
 
-typedef JSString* (*PrimitiveToStringFn)(JSContext*, HandleValue);
-static const VMFunction PrimitiveToStringInfo =
-    FunctionInfo<PrimitiveToStringFn>(ToStringSlow, "ToStringSlow");
-
 void CodeGenerator::visitValueToString(LValueToString* lir) {
   ValueOperand input = ToValue(lir, LValueToString::Input);
   Register output = ToRegister(lir->output());
 
-  OutOfLineCode* ool = oolCallVM(PrimitiveToStringInfo, lir, ArgList(input),
-                                 StoreRegisterTo(output));
+  using Fn = JSString* (*)(JSContext*, HandleValue);
+  OutOfLineCode* ool = oolCallVM<Fn, ToStringSlow<CanGC>>(
+      lir, ArgList(input), StoreRegisterTo(output));
 
   Label done;
   Register tag = masm.extractTag(input, output);
   const JSAtomState& names = gen->runtime->names();
 
   // String
   if (lir->mir()->input()->mightBeType(MIRType::String)) {
     Label notString;
@@ -1689,39 +1668,37 @@ void CodeGenerator::visitValueToString(L
 #ifdef DEBUG
   masm.assumeUnreachable("Unexpected type for MValueToString.");
 #endif
 
   masm.bind(&done);
   masm.bind(ool->rejoin());
 }
 
-typedef JSObject* (*ToObjectFn)(JSContext*, HandleValue, bool);
-static const VMFunction ToObjectInfo =
-    FunctionInfo<ToObjectFn>(ToObjectSlow, "ToObjectSlow");
-
 void CodeGenerator::visitValueToObject(LValueToObject* lir) {
   ValueOperand input = ToValue(lir, LValueToObject::Input);
   Register output = ToRegister(lir->output());
 
-  OutOfLineCode* ool = oolCallVM(ToObjectInfo, lir, ArgList(input, Imm32(0)),
-                                 StoreRegisterTo(output));
+  using Fn = JSObject* (*)(JSContext*, HandleValue, bool);
+  OutOfLineCode* ool = oolCallVM<Fn, ToObjectSlow>(
+      lir, ArgList(input, Imm32(0)), StoreRegisterTo(output));
 
   masm.branchTestObject(Assembler::NotEqual, input, ool->entry());
   masm.unboxObject(input, output);
 
   masm.bind(ool->rejoin());
 }
 
 void CodeGenerator::visitValueToObjectOrNull(LValueToObjectOrNull* lir) {
   ValueOperand input = ToValue(lir, LValueToObjectOrNull::Input);
   Register output = ToRegister(lir->output());
 
-  OutOfLineCode* ool = oolCallVM(ToObjectInfo, lir, ArgList(input, Imm32(0)),
-                                 StoreRegisterTo(output));
+  using Fn = JSObject* (*)(JSContext*, HandleValue, bool);
+  OutOfLineCode* ool = oolCallVM<Fn, ToObjectSlow>(
+      lir, ArgList(input, Imm32(0)), StoreRegisterTo(output));
 
   Label isObject;
   masm.branchTestObject(Assembler::Equal, input, &isObject);
   masm.branchTestNull(Assembler::NotEqual, input, ool->entry());
 
   masm.movePtr(ImmWord(0), output);
   masm.jump(ool->rejoin());
 
@@ -1801,28 +1778,24 @@ static void EmitPostWriteBarrierS(MacroA
   masm.loadStoreBuffer(prev, storebuffer);
   masm.branchPtr(Assembler::Equal, storebuffer, ImmWord(0), &exit);
   EmitStoreBufferMutation(masm, holder, offset, storebuffer, liveVolatiles,
                           JSString::removeCellAddressFromStoreBuffer);
 
   masm.bind(&exit);
 }
 
-typedef JSObject* (*CloneRegExpObjectFn)(JSContext*, Handle<RegExpObject*>);
-static const VMFunction CloneRegExpObjectInfo =
-    FunctionInfo<CloneRegExpObjectFn>(CloneRegExpObject, "CloneRegExpObject");
-
 void CodeGenerator::visitRegExp(LRegExp* lir) {
   Register output = ToRegister(lir->output());
   Register temp = ToRegister(lir->temp());
   JSObject* source = lir->mir()->source();
 
-  OutOfLineCode* ool =
-      oolCallVM(CloneRegExpObjectInfo, lir, ArgList(ImmGCPtr(source)),
-                StoreRegisterTo(output));
+  using Fn = JSObject* (*)(JSContext*, Handle<RegExpObject*>);
+  OutOfLineCode* ool = oolCallVM<Fn, CloneRegExpObject>(
+      lir, ArgList(ImmGCPtr(source)), StoreRegisterTo(output));
   if (lir->mir()->hasShared()) {
     TemplateObject templateObject(source);
     masm.createGCObject(output, temp, templateObject, gc::DefaultHeap,
                         ool->entry());
   } else {
     masm.jump(ool->entry());
   }
   masm.bind(ool->rejoin());
@@ -2766,17 +2739,17 @@ void CodeGenerator::visitOutOfLineRegExp
 
   pushArg(temp);
   pushArg(lastIndex);
   pushArg(input);
   pushArg(regexp);
 
   // We are not using oolCallVM because we are in a Call, and that live
   // registers are already saved by the the register allocator.
-  using Fn = bool (*)(JSContext * cx, HandleObject regexp, HandleString input,
+  using Fn = bool (*)(JSContext*, HandleObject regexp, HandleString input,
                       int32_t lastIndex, MatchPairs * pairs,
                       MutableHandleValue output);
   callVM<Fn, RegExpMatcherRaw>(lir);
 
   masm.jump(ool->rejoin());
 }
 
 void CodeGenerator::visitRegExpMatcher(LRegExpMatcher* lir) {
@@ -3251,30 +3224,26 @@ static void FindFirstDollarIndex(MacroAs
   masm.add32(Imm32(1), output);
   masm.branch32(Assembler::NotEqual, output, len, &start);
 
   masm.move32(Imm32(-1), output);
 
   masm.bind(&done);
 }
 
-typedef bool (*GetFirstDollarIndexRawFn)(JSContext*, JSString*, int32_t*);
-static const VMFunction GetFirstDollarIndexRawInfo =
-    FunctionInfo<GetFirstDollarIndexRawFn>(GetFirstDollarIndexRaw,
-                                           "GetFirstDollarIndexRaw");
-
 void CodeGenerator::visitGetFirstDollarIndex(LGetFirstDollarIndex* ins) {
   Register str = ToRegister(ins->str());
   Register output = ToRegister(ins->output());
   Register temp0 = ToRegister(ins->temp0());
   Register temp1 = ToRegister(ins->temp1());
   Register len = ToRegister(ins->temp2());
 
-  OutOfLineCode* ool = oolCallVM(GetFirstDollarIndexRawInfo, ins, ArgList(str),
-                                 StoreRegisterTo(output));
+  using Fn = bool (*)(JSContext*, JSString*, int32_t*);
+  OutOfLineCode* ool = oolCallVM<Fn, GetFirstDollarIndexRaw>(
+      ins, ArgList(str), StoreRegisterTo(output));
 
   masm.branchIfRope(str, ool->entry());
   masm.loadStringLength(str, len);
 
   Label isLatin1, done;
   masm.branchLatin1String(str, &isLatin1);
   {
     FindFirstDollarIndex(masm, str, len, temp0, temp1, output,
@@ -3402,37 +3371,34 @@ void CodeGenerator::visitModuleMetadata(
 void CodeGenerator::visitDynamicImport(LDynamicImport* lir) {
   pushArg(ToValue(lir, LDynamicImport::SpecifierIndex));
   pushArg(ImmGCPtr(current->mir()->info().script()));
 
   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()));
 
   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();
 
-  OutOfLineCode* ool =
-      oolCallVM(LambdaInfo, lir, ArgList(ImmGCPtr(info.funUnsafe()), envChain),
-                StoreRegisterTo(output));
+  using Fn = JSObject* (*)(JSContext*, HandleFunction, HandleObject);
+  OutOfLineCode* ool = oolCallVM<Fn, js::Lambda>(
+      lir, ArgList(ImmGCPtr(info.funUnsafe()), envChain),
+      StoreRegisterTo(output));
 
   MOZ_ASSERT(!info.singletonType);
 
   TemplateObject templateObject(info.funUnsafe());
   masm.createGCObject(output, tempReg, templateObject, gc::DefaultHeap,
                       ool->entry());
 
   emitLambdaInit(output, envChain, info);
@@ -3609,20 +3575,16 @@ void CodeGenerator::visitOsiPoint(LOsiPo
 }
 
 void CodeGenerator::visitPhi(LPhi* lir) {
   MOZ_CRASH("Unexpected LPhi in CodeGenerator");
 }
 
 void CodeGenerator::visitGoto(LGoto* lir) { jumpToBlock(lir->target()); }
 
-typedef bool (*InterruptCheckFn)(JSContext*);
-static const VMFunction InterruptCheckInfo =
-    FunctionInfo<InterruptCheckFn>(InterruptCheck, "InterruptCheck");
-
 void CodeGenerator::visitTableSwitch(LTableSwitch* ins) {
   MTableSwitch* mir = ins->mir();
   Label* defaultcase = skipTrivialBlocks(mir->getDefault())->lir()->label();
   const LAllocation* temp;
 
   if (mir->getOperand(0)->type() != MIRType::Int32) {
     temp = ins->tempInt()->output();
 
@@ -4170,28 +4132,23 @@ void CodeGenerator::visitSetPropertyPoly
   emitSetPropertyPolymorphic(ins, obj, temp1, temp2, value.ref());
 }
 
 void CodeGenerator::visitElements(LElements* lir) {
   Address elements(ToRegister(lir->object()), NativeObject::offsetOfElements());
   masm.loadPtr(elements, ToRegister(lir->output()));
 }
 
-typedef void (*ConvertElementsToDoublesFn)(JSContext*, uintptr_t);
-static const VMFunction ConvertElementsToDoublesInfo =
-    FunctionInfo<ConvertElementsToDoublesFn>(
-        ObjectElements::ConvertElementsToDoubles,
-        "ObjectElements::ConvertElementsToDoubles");
-
 void CodeGenerator::visitConvertElementsToDoubles(
     LConvertElementsToDoubles* lir) {
   Register elements = ToRegister(lir->elements());
 
-  OutOfLineCode* ool = oolCallVM(ConvertElementsToDoublesInfo, lir,
-                                 ArgList(elements), StoreNothing());
+  using Fn = void (*)(JSContext*, uintptr_t);
+  OutOfLineCode* ool = oolCallVM<Fn, ObjectElements::ConvertElementsToDoubles>(
+      lir, ArgList(elements), StoreNothing());
 
   Address convertedAddress(elements, ObjectElements::offsetOfFlags());
   Imm32 bit(ObjectElements::CONVERT_DOUBLE_ELEMENTS);
   masm.branchTest32(Assembler::Zero, convertedAddress, bit, ool->entry());
   masm.bind(ool->rejoin());
 }
 
 void CodeGenerator::visitMaybeToDoubleElement(LMaybeToDoubleElement* lir) {
@@ -4213,28 +4170,24 @@ void CodeGenerator::visitMaybeToDoubleEl
 
   masm.bind(&convert);
   masm.convertInt32ToDouble(value, temp);
   masm.boxDouble(temp, out, temp);
 
   masm.bind(&done);
 }
 
-typedef bool (*CopyElementsForWriteFn)(JSContext*, NativeObject*);
-static const VMFunction CopyElementsForWriteInfo =
-    FunctionInfo<CopyElementsForWriteFn>(NativeObject::CopyElementsForWrite,
-                                         "NativeObject::CopyElementsForWrite");
-
 void CodeGenerator::visitMaybeCopyElementsForWrite(
     LMaybeCopyElementsForWrite* lir) {
   Register object = ToRegister(lir->object());
   Register temp = ToRegister(lir->temp());
 
-  OutOfLineCode* ool =
-      oolCallVM(CopyElementsForWriteInfo, lir, ArgList(object), StoreNothing());
+  using Fn = bool (*)(JSContext*, NativeObject*);
+  OutOfLineCode* ool = oolCallVM<Fn, NativeObject::CopyElementsForWrite>(
+      lir, ArgList(object), StoreNothing());
 
   if (lir->mir()->checkNative()) {
     masm.branchIfNonNativeObj(object, temp, ool->rejoin());
   }
 
   masm.loadPtr(Address(object, NativeObject::offsetOfElements()), temp);
   masm.branchTest32(Assembler::NonZero,
                     Address(temp, ObjectElements::offsetOfFlags()),
@@ -4255,27 +4208,23 @@ void CodeGenerator::visitHomeObject(LHom
   Label isObject;
   masm.branchTestObject(Assembler::Equal, homeObject, &isObject);
   masm.assumeUnreachable("[[HomeObject]] must be Object");
   masm.bind(&isObject);
 #endif
   masm.unboxObject(homeObject, ToRegister(lir->output()));
 }
 
-typedef JSObject* (*HomeObjectSuperBaseFn)(JSContext*, HandleObject);
-static const VMFunction HomeObjectSuperBaseInfo =
-    FunctionInfo<HomeObjectSuperBaseFn>(HomeObjectSuperBase,
-                                        "HomeObjectSuperBase");
-
 void CodeGenerator::visitHomeObjectSuperBase(LHomeObjectSuperBase* lir) {
   Register homeObject = ToRegister(lir->homeObject());
   Register output = ToRegister(lir->output());
 
-  OutOfLineCode* ool = oolCallVM(HomeObjectSuperBaseInfo, lir,
-                                 ArgList(homeObject), StoreRegisterTo(output));
+  using Fn = JSObject* (*)(JSContext*, HandleObject);
+  OutOfLineCode* ool = oolCallVM<Fn, HomeObjectSuperBase>(
+      lir, ArgList(homeObject), StoreRegisterTo(output));
 
   masm.loadObjProto(homeObject, output);
   masm.branchPtr(Assembler::BelowOrEqual, output, ImmWord(1), ool->entry());
   masm.bind(ool->rejoin());
 }
 
 void CodeGenerator::visitNewLexicalEnvironmentObject(
     LNewLexicalEnvironmentObject* lir) {
@@ -4374,18 +4323,19 @@ void CodeGenerator::visitToNumeric(LToNu
   ValueOperand operand = ToValue(lir, LToNumeric::Input);
   ValueOperand output = ToOutValue(lir);
   bool maybeInt32 = lir->mir()->mightBeType(MIRType::Int32);
   bool maybeDouble = lir->mir()->mightBeType(MIRType::Double);
   bool maybeNumber = maybeInt32 || maybeDouble;
   bool maybeBigInt = lir->mir()->mightBeType(MIRType::BigInt);
   int checks = int(maybeNumber) + int(maybeBigInt);
 
+  using Fn = bool (*)(JSContext*, HandleValue, MutableHandleValue);
   OutOfLineCode* ool =
-      oolCallVM(ToNumericInfo, lir, ArgList(operand), StoreValueTo(output));
+      oolCallVM<Fn, DoToNumeric>(lir, ArgList(operand), StoreValueTo(output));
 
   if (checks == 0) {
     masm.jump(ool->entry());
   } else {
     Label done;
     using Condition = Assembler::Condition;
     constexpr Condition Equal = Assembler::Equal;
     constexpr Condition NotEqual = Assembler::NotEqual;
@@ -6533,59 +6483,47 @@ void CodeGenerator::visitNewArray(LNewAr
   masm.bind(ool->rejoin());
 }
 
 void CodeGenerator::visitOutOfLineNewArray(OutOfLineNewArray* ool) {
   visitNewArrayCallVM(ool->lir());
   masm.jump(ool->rejoin());
 }
 
-typedef ArrayObject* (*NewArrayCopyOnWriteFn)(JSContext*, HandleArrayObject,
-                                              gc::InitialHeap);
-static const VMFunction NewArrayCopyOnWriteInfo =
-    FunctionInfo<NewArrayCopyOnWriteFn>(js::NewDenseCopyOnWriteArray,
-                                        "NewDenseCopyOnWriteArray");
-
 void CodeGenerator::visitNewArrayCopyOnWrite(LNewArrayCopyOnWrite* lir) {
   Register objReg = ToRegister(lir->output());
   Register tempReg = ToRegister(lir->temp());
   ArrayObject* templateObject = lir->mir()->templateObject();
   gc::InitialHeap initialHeap = lir->mir()->initialHeap();
 
   // If we have a template object, we can inline call object creation.
-  OutOfLineCode* ool =
-      oolCallVM(NewArrayCopyOnWriteInfo, lir,
-                ArgList(ImmGCPtr(templateObject), Imm32(initialHeap)),
-                StoreRegisterTo(objReg));
+  using Fn = ArrayObject* (*)(JSContext*, HandleArrayObject, gc::InitialHeap);
+  OutOfLineCode* ool = oolCallVM<Fn, js::NewDenseCopyOnWriteArray>(
+      lir, ArgList(ImmGCPtr(templateObject), Imm32(initialHeap)),
+      StoreRegisterTo(objReg));
 
   TemplateObject templateObj(templateObject);
   templateObj.setDenseElementsAreCopyOnWrite();
   masm.createGCObject(objReg, tempReg, templateObj, initialHeap, ool->entry());
 
   masm.bind(ool->rejoin());
 }
 
-typedef ArrayObject* (*ArrayConstructorOneArgFn)(JSContext*, HandleObjectGroup,
-                                                 int32_t length);
-static const VMFunction ArrayConstructorOneArgInfo =
-    FunctionInfo<ArrayConstructorOneArgFn>(ArrayConstructorOneArg,
-                                           "ArrayConstructorOneArg");
-
 void CodeGenerator::visitNewArrayDynamicLength(LNewArrayDynamicLength* lir) {
   Register lengthReg = ToRegister(lir->length());
   Register objReg = ToRegister(lir->output());
   Register tempReg = ToRegister(lir->temp());
 
   JSObject* templateObject = lir->mir()->templateObject();
   gc::InitialHeap initialHeap = lir->mir()->initialHeap();
 
-  OutOfLineCode* ool =
-      oolCallVM(ArrayConstructorOneArgInfo, lir,
-                ArgList(ImmGCPtr(templateObject->group()), lengthReg),
-                StoreRegisterTo(objReg));
+  using Fn = ArrayObject* (*)(JSContext*, HandleObjectGroup, int32_t length);
+  OutOfLineCode* ool = oolCallVM<Fn, ArrayConstructorOneArg>(
+      lir, ArgList(ImmGCPtr(templateObject->group()), lengthReg),
+      StoreRegisterTo(objReg));
 
   bool canInline = true;
   size_t inlineLength = 0;
   if (templateObject->as<ArrayObject>().hasFixedElements()) {
     size_t numSlots =
         gc::GetGCKindSlots(templateObject->asTenured().getAllocKind());
     inlineLength = numSlots - ObjectElements::VALUES_PER_HEADER;
   } else {
@@ -6610,87 +6548,67 @@ void CodeGenerator::visitNewArrayDynamic
     masm.store32(lengthReg, Address(objReg, lengthOffset));
   } else {
     masm.jump(ool->entry());
   }
 
   masm.bind(ool->rejoin());
 }
 
-typedef ArrayIteratorObject* (*NewArrayIteratorObjectFn)(JSContext*,
-                                                         NewObjectKind);
-static const VMFunction NewArrayIteratorObjectInfo =
-    FunctionInfo<NewArrayIteratorObjectFn>(NewArrayIteratorObject,
-                                           "NewArrayIteratorObject");
-
-typedef StringIteratorObject* (*NewStringIteratorObjectFn)(JSContext*,
-                                                           NewObjectKind);
-static const VMFunction NewStringIteratorObjectInfo =
-    FunctionInfo<NewStringIteratorObjectFn>(NewStringIteratorObject,
-                                            "NewStringIteratorObject");
-
-typedef RegExpStringIteratorObject* (*NewRegExpStringIteratorObjectFn)(
-    JSContext*, NewObjectKind);
-
-static const VMFunction NewRegExpStringIteratorObjectInfo =
-    FunctionInfo<NewRegExpStringIteratorObjectFn>(
-        NewRegExpStringIteratorObject, "NewRegExpStringIteratorObject");
-
 void CodeGenerator::visitNewIterator(LNewIterator* lir) {
   Register objReg = ToRegister(lir->output());
   Register tempReg = ToRegister(lir->temp());
 
   OutOfLineCode* ool;
   switch (lir->mir()->type()) {
-    case MNewIterator::ArrayIterator:
-      ool = oolCallVM(NewArrayIteratorObjectInfo, lir,
-                      ArgList(Imm32(GenericObject)), StoreRegisterTo(objReg));
-      break;
-    case MNewIterator::StringIterator:
-      ool = oolCallVM(NewStringIteratorObjectInfo, lir,
-                      ArgList(Imm32(GenericObject)), StoreRegisterTo(objReg));
-      break;
-    case MNewIterator::RegExpStringIterator:
-      ool = oolCallVM(NewRegExpStringIteratorObjectInfo, lir,
-                      ArgList(Imm32(GenericObject)), StoreRegisterTo(objReg));
-      break;
+    case MNewIterator::ArrayIterator: {
+      using Fn = ArrayIteratorObject* (*)(JSContext*, NewObjectKind);
+      ool = oolCallVM<Fn, NewArrayIteratorObject>(
+          lir, ArgList(Imm32(GenericObject)), StoreRegisterTo(objReg));
+      break;
+    }
+    case MNewIterator::StringIterator: {
+      using Fn = StringIteratorObject* (*)(JSContext*, NewObjectKind);
+      ool = oolCallVM<Fn, NewStringIteratorObject>(
+          lir, ArgList(Imm32(GenericObject)), StoreRegisterTo(objReg));
+      break;
+    }
+    case MNewIterator::RegExpStringIterator: {
+      using Fn = RegExpStringIteratorObject* (*)(JSContext*, NewObjectKind);
+      ool = oolCallVM<Fn, NewRegExpStringIteratorObject>(
+          lir, ArgList(Imm32(GenericObject)), StoreRegisterTo(objReg));
+      break;
+    }
     default:
       MOZ_CRASH("unexpected iterator type");
   }
 
   TemplateObject templateObject(lir->mir()->templateObject());
   masm.createGCObject(objReg, tempReg, templateObject, gc::DefaultHeap,
                       ool->entry());
 
   masm.bind(ool->rejoin());
 }
 
-typedef TypedArrayObject* (*TypedArrayConstructorOneArgFn)(JSContext*,
-                                                           HandleObject,
-                                                           int32_t length);
-static const VMFunction TypedArrayConstructorOneArgInfo =
-    FunctionInfo<TypedArrayConstructorOneArgFn>(
-        NewTypedArrayWithTemplateAndLength,
-        "NewTypedArrayWithTemplateAndLength");
-
 void CodeGenerator::visitNewTypedArray(LNewTypedArray* lir) {
   Register objReg = ToRegister(lir->output());
   Register tempReg = ToRegister(lir->temp1());
   Register lengthReg = ToRegister(lir->temp2());
   LiveRegisterSet liveRegs = lir->safepoint()->liveRegs();
 
   JSObject* templateObject = lir->mir()->templateObject();
   gc::InitialHeap initialHeap = lir->mir()->initialHeap();
 
   TypedArrayObject* ttemplate = &templateObject->as<TypedArrayObject>();
   uint32_t n = ttemplate->length();
 
-  OutOfLineCode* ool = oolCallVM(TypedArrayConstructorOneArgInfo, lir,
-                                 ArgList(ImmGCPtr(templateObject), Imm32(n)),
-                                 StoreRegisterTo(objReg));
+  using Fn = TypedArrayObject* (*)(JSContext*, HandleObject, int32_t length);
+  OutOfLineCode* ool = oolCallVM<Fn, NewTypedArrayWithTemplateAndLength>(
+      lir, ArgList(ImmGCPtr(templateObject), Imm32(n)),
+      StoreRegisterTo(objReg));
 
   TemplateObject templateObj(templateObject);
   masm.createGCObject(objReg, tempReg, templateObj, initialHeap, ool->entry());
 
   masm.initTypedArraySlots(objReg, tempReg, lengthReg, liveRegs, ool->entry(),
                            ttemplate, MacroAssembler::TypedArrayLength::Fixed);
 
   masm.bind(ool->rejoin());
@@ -6703,19 +6621,20 @@ void CodeGenerator::visitNewTypedArrayDy
   Register tempReg = ToRegister(lir->temp());
   LiveRegisterSet liveRegs = lir->safepoint()->liveRegs();
 
   JSObject* templateObject = lir->mir()->templateObject();
   gc::InitialHeap initialHeap = lir->mir()->initialHeap();
 
   TypedArrayObject* ttemplate = &templateObject->as<TypedArrayObject>();
 
-  OutOfLineCode* ool = oolCallVM(TypedArrayConstructorOneArgInfo, lir,
-                                 ArgList(ImmGCPtr(templateObject), lengthReg),
-                                 StoreRegisterTo(objReg));
+  using Fn = TypedArrayObject* (*)(JSContext*, HandleObject, int32_t length);
+  OutOfLineCode* ool = oolCallVM<Fn, NewTypedArrayWithTemplateAndLength>(
+      lir, ArgList(ImmGCPtr(templateObject), lengthReg),
+      StoreRegisterTo(objReg));
 
   TemplateObject templateObj(templateObject);
   masm.createGCObject(objReg, tempReg, templateObj, initialHeap, ool->entry());
 
   masm.initTypedArraySlots(objReg, tempReg, lengthReg, liveRegs, ool->entry(),
                            ttemplate,
                            MacroAssembler::TypedArrayLength::Dynamic);
 
@@ -6913,105 +6832,87 @@ void CodeGenerator::visitNewObject(LNewO
   masm.bind(ool->rejoin());
 }
 
 void CodeGenerator::visitOutOfLineNewObject(OutOfLineNewObject* ool) {
   visitNewObjectVMCall(ool->lir());
   masm.jump(ool->rejoin());
 }
 
-typedef InlineTypedObject* (*NewTypedObjectFn)(JSContext*,
-                                               Handle<InlineTypedObject*>,
-                                               gc::InitialHeap);
-static const VMFunction NewTypedObjectInfo = FunctionInfo<NewTypedObjectFn>(
-    InlineTypedObject::createCopy, "InlineTypedObject::createCopy");
-
 void CodeGenerator::visitNewTypedObject(LNewTypedObject* lir) {
   Register object = ToRegister(lir->output());
   Register temp = ToRegister(lir->temp());
   InlineTypedObject* templateObject = lir->mir()->templateObject();
   gc::InitialHeap initialHeap = lir->mir()->initialHeap();
 
-  OutOfLineCode* ool =
-      oolCallVM(NewTypedObjectInfo, lir,
-                ArgList(ImmGCPtr(templateObject), Imm32(initialHeap)),
-                StoreRegisterTo(object));
+  using Fn = InlineTypedObject* (*)(JSContext*, Handle<InlineTypedObject*>,
+                                    gc::InitialHeap);
+  OutOfLineCode* ool = oolCallVM<Fn, InlineTypedObject::createCopy>(
+      lir, ArgList(ImmGCPtr(templateObject), Imm32(initialHeap)),
+      StoreRegisterTo(object));
 
   TemplateObject templateObj(templateObject);
   masm.createGCObject(object, temp, templateObj, initialHeap, ool->entry());
 
   masm.bind(ool->rejoin());
 }
 
-typedef js::NamedLambdaObject* (*NewNamedLambdaObjectFn)(JSContext*,
-                                                         HandleFunction,
-                                                         gc::InitialHeap);
-static const VMFunction NewNamedLambdaObjectInfo =
-    FunctionInfo<NewNamedLambdaObjectFn>(
-        NamedLambdaObject::createTemplateObject,
-        "NamedLambdaObject::createTemplateObject");
-
 void CodeGenerator::visitNewNamedLambdaObject(LNewNamedLambdaObject* lir) {
   Register objReg = ToRegister(lir->output());
   Register tempReg = ToRegister(lir->temp());
   const CompileInfo& info = lir->mir()->block()->info();
 
   // If we have a template object, we can inline call object creation.
-  OutOfLineCode* ool =
-      oolCallVM(NewNamedLambdaObjectInfo, lir,
-                ArgList(ImmGCPtr(info.funMaybeLazy()), Imm32(gc::DefaultHeap)),
-                StoreRegisterTo(objReg));
+  using Fn =
+      js::NamedLambdaObject* (*)(JSContext*, HandleFunction, gc::InitialHeap);
+  OutOfLineCode* ool = oolCallVM<Fn, NamedLambdaObject::createTemplateObject>(
+      lir, ArgList(ImmGCPtr(info.funMaybeLazy()), Imm32(gc::DefaultHeap)),
+      StoreRegisterTo(objReg));
 
   TemplateObject templateObject(lir->mir()->templateObj());
 
   bool initContents = ShouldInitFixedSlots(lir, templateObject);
   masm.createGCObject(objReg, tempReg, templateObject, gc::DefaultHeap,
                       ool->entry(), initContents);
 
   masm.bind(ool->rejoin());
 }
 
-typedef JSObject* (*NewCallObjectFn)(JSContext*, HandleShape,
-                                     HandleObjectGroup);
-static const VMFunction NewCallObjectInfo =
-    FunctionInfo<NewCallObjectFn>(NewCallObject, "NewCallObject");
-
 void CodeGenerator::visitNewCallObject(LNewCallObject* lir) {
   Register objReg = ToRegister(lir->output());
   Register tempReg = ToRegister(lir->temp());
 
   CallObject* templateObj = lir->mir()->templateObject();
 
-  OutOfLineCode* ool = oolCallVM(NewCallObjectInfo, lir,
-                                 ArgList(ImmGCPtr(templateObj->lastProperty()),
-                                         ImmGCPtr(templateObj->group())),
-                                 StoreRegisterTo(objReg));
+  using Fn = JSObject* (*)(JSContext*, HandleShape, HandleObjectGroup);
+  OutOfLineCode* ool = oolCallVM<Fn, NewCallObject>(
+      lir,
+      ArgList(ImmGCPtr(templateObj->lastProperty()),
+              ImmGCPtr(templateObj->group())),
+      StoreRegisterTo(objReg));
 
   // Inline call object creation, using the OOL path only for tricky cases.
   TemplateObject templateObject(templateObj);
   bool initContents = ShouldInitFixedSlots(lir, templateObject);
   masm.createGCObject(objReg, tempReg, templateObject, gc::DefaultHeap,
                       ool->entry(), initContents);
 
   masm.bind(ool->rejoin());
 }
 
-typedef JSObject* (*NewStringObjectFn)(JSContext*, HandleString);
-static const VMFunction NewStringObjectInfo =
-    FunctionInfo<NewStringObjectFn>(NewStringObject, "NewStringObject");
-
 void CodeGenerator::visitNewStringObject(LNewStringObject* lir) {
   Register input = ToRegister(lir->input());
   Register output = ToRegister(lir->output());
   Register temp = ToRegister(lir->temp());
 
   StringObject* templateObj = lir->mir()->templateObj();
 
-  OutOfLineCode* ool = oolCallVM(NewStringObjectInfo, lir, ArgList(input),
-                                 StoreRegisterTo(output));
+  using Fn = JSObject* (*)(JSContext*, HandleString);
+  OutOfLineCode* ool = oolCallVM<Fn, NewStringObject>(lir, ArgList(input),
+                                                      StoreRegisterTo(output));
 
   TemplateObject templateObject(templateObj);
   masm.createGCObject(output, temp, templateObject, gc::DefaultHeap,
                       ool->entry());
 
   masm.loadStringLength(input, temp);
 
   masm.storeValue(JSVAL_TYPE_STRING, input,
@@ -7120,29 +7021,24 @@ void CodeGenerator::visitCreateThisWithP
   }
 
   using Fn = JSObject* (*)(JSContext * cx, HandleFunction callee,
                            HandleObject newTarget, HandleObject proto,
                            NewObjectKind newKind);
   callVM<Fn, CreateThisForFunctionWithProto>(lir);
 }
 
-typedef JSObject* (*CreateThisWithTemplateFn)(JSContext*, HandleObject);
-static const VMFunction CreateThisWithTemplateInfo =
-    FunctionInfo<CreateThisWithTemplateFn>(CreateThisWithTemplate,
-                                           "CreateThisWithTemplate");
-
 void CodeGenerator::visitCreateThisWithTemplate(LCreateThisWithTemplate* lir) {
   JSObject* templateObject = lir->mir()->templateObject();
   Register objReg = ToRegister(lir->output());
   Register tempReg = ToRegister(lir->temp());
 
-  OutOfLineCode* ool =
-      oolCallVM(CreateThisWithTemplateInfo, lir,
-                ArgList(ImmGCPtr(templateObject)), StoreRegisterTo(objReg));
+  using Fn = JSObject* (*)(JSContext*, HandleObject);
+  OutOfLineCode* ool = oolCallVM<Fn, CreateThisWithTemplate>(
+      lir, ArgList(ImmGCPtr(templateObject)), StoreRegisterTo(objReg));
 
   // Allocate. If the FreeList is empty, call to VM, which may GC.
   TemplateObject templateObj(templateObject);
   bool initContents =
       !templateObj.isPlainObject() || ShouldInitFixedSlots(lir, templateObj);
   masm.createGCObject(objReg, tempReg, templateObj, lir->mir()->initialHeap(),
                       ool->entry(), initContents);
 
@@ -7264,26 +7160,23 @@ void CodeGenerator::visitReturnFromCtor(
   Register payload = masm.extractObject(value, output);
   if (payload != output) {
     masm.movePtr(payload, output);
   }
 
   masm.bind(&end);
 }
 
-typedef bool (*BoxNonStrictThisFn)(JSContext*, HandleValue, MutableHandleValue);
-static const VMFunction BoxNonStrictThisInfo =
-    FunctionInfo<BoxNonStrictThisFn>(BoxNonStrictThis, "BoxNonStrictThis");
-
 void CodeGenerator::visitComputeThis(LComputeThis* lir) {
   ValueOperand value = ToValue(lir, LComputeThis::ValueIndex);
   ValueOperand output = ToOutValue(lir);
 
-  OutOfLineCode* ool = oolCallVM(BoxNonStrictThisInfo, lir, ArgList(value),
-                                 StoreValueTo(output));
+  using Fn = bool (*)(JSContext*, HandleValue, MutableHandleValue);
+  OutOfLineCode* ool = oolCallVM<Fn, BoxNonStrictThis>(lir, ArgList(value),
+                                                       StoreValueTo(output));
 
   masm.branchTestObject(Assembler::NotEqual, value, ool->entry());
   masm.moveValue(value, output);
   masm.bind(ool->rejoin());
 }
 
 void CodeGenerator::visitImplicitThis(LImplicitThis* lir) {
   pushArg(ImmGCPtr(lir->mir()->name()));
@@ -8207,23 +8100,24 @@ void CodeGenerator::visitBinaryV(LBinary
 }
 
 void CodeGenerator::emitCompareS(LInstruction* lir, JSOp op, Register left,
                                  Register right, Register output) {
   MOZ_ASSERT(lir->isCompareS() || lir->isCompareStrictS());
 
   OutOfLineCode* ool = nullptr;
 
+  using Fn = bool (*)(JSContext*, HandleString, HandleString, bool*);
   if (op == JSOP_EQ || op == JSOP_STRICTEQ) {
-    ool = oolCallVM(StringsEqualInfo, lir, ArgList(left, right),
-                    StoreRegisterTo(output));
+    ool = oolCallVM<Fn, jit::StringsEqual<true>>(lir, ArgList(left, right),
+                                                 StoreRegisterTo(output));
   } else {
     MOZ_ASSERT(op == JSOP_NE || op == JSOP_STRICTNE);
-    ool = oolCallVM(StringsNotEqualInfo, lir, ArgList(left, right),
-                    StoreRegisterTo(output));
+    ool = oolCallVM<Fn, jit::StringsEqual<false>>(lir, ArgList(left, right),
+                                                  StoreRegisterTo(output));
   }
 
   masm.compareStrings(op, left, right, output, ool->entry());
 
   masm.bind(ool->rejoin());
 }
 
 void CodeGenerator::visitCompareStrictS(LCompareStrictS* lir) {
@@ -8657,18 +8551,19 @@ void CodeGenerator::visitSameValueVM(LSa
   pushArg(ToValue(lir, LSameValueVM::LhsInput));
 
   using Fn = bool (*)(JSContext*, HandleValue, HandleValue, bool*);
   callVM<Fn, js::SameValue>(lir);
 }
 
 void CodeGenerator::emitConcat(LInstruction* lir, Register lhs, Register rhs,
                                Register output) {
-  OutOfLineCode* ool = oolCallVM(ConcatStringsInfo, lir, ArgList(lhs, rhs),
-                                 StoreRegisterTo(output));
+  using Fn = JSString* (*)(JSContext*, HandleString, HandleString);
+  OutOfLineCode* ool = oolCallVM<Fn, ConcatStrings<CanGC>>(
+      lir, ArgList(lhs, rhs), StoreRegisterTo(output));
 
   const JitRealm* jitRealm = gen->realm->jitRealm();
   JitCode* stringConcatStub =
       jitRealm->stringConcatStubNoBarrier(&realmStubsToReadBarrier_);
   masm.call(stringConcatStub);
   masm.branchTestPtr(Assembler::Zero, output, output, ool->entry());
 
   masm.bind(ool->rejoin());
@@ -8824,21 +8719,16 @@ static void ConcatInlineString(MacroAsse
   copyChars(rhs);
 
   // Null-terminate.
   masm.storeChar(Imm32(0), Address(temp2, 0), encoding);
 
   masm.ret();
 }
 
-typedef JSString* (*SubstringKernelFn)(JSContext* cx, HandleString str,
-                                       int32_t begin, int32_t len);
-static const VMFunction SubstringKernelInfo =
-    FunctionInfo<SubstringKernelFn>(SubstringKernel, "SubstringKernel");
-
 void CodeGenerator::visitSubstr(LSubstr* lir) {
   Register string = ToRegister(lir->string());
   Register begin = ToRegister(lir->begin());
   Register length = ToRegister(lir->length());
   Register output = ToRegister(lir->output());
   Register temp = ToRegister(lir->temp());
   Register temp3 = ToRegister(lir->temp3());
 
@@ -8851,19 +8741,20 @@ void CodeGenerator::visitSubstr(LSubstr*
 
   Label isLatin1, notInline, nonZero, isInlinedLatin1;
 
   // For every edge case use the C++ variant.
   // Note: we also use this upon allocation failure in newGCString and
   // newGCFatInlineString. To squeeze out even more performance those failures
   // can be handled by allocate in ool code and returning to jit code to fill
   // in all data.
-  OutOfLineCode* ool =
-      oolCallVM(SubstringKernelInfo, lir, ArgList(string, begin, length),
-                StoreRegisterTo(output));
+  using Fn = JSString* (*)(JSContext * cx, HandleString str, int32_t begin,
+                           int32_t len);
+  OutOfLineCode* ool = oolCallVM<Fn, SubstringKernel>(
+      lir, ArgList(string, begin, length), StoreRegisterTo(output));
   Label* slowPath = ool->entry();
   Label* done = ool->rejoin();
 
   // Zero length, return emptystring.
   masm.branchTest32(Assembler::NonZero, length, length, &nonZero);
   const JSAtomState& names = gen->runtime->names();
   masm.movePtr(ImmGCPtr(names.empty), output);
   masm.jump(done);
@@ -9214,69 +9105,58 @@ bool JitRuntime::generateTLEventVM(Macro
 
     masm.Pop(loggerReg);
   }
 #endif
 
   return true;
 }
 
-typedef bool (*CharCodeAtFn)(JSContext*, HandleString, int32_t, uint32_t*);
-static const VMFunction CharCodeAtInfo =
-    FunctionInfo<CharCodeAtFn>(jit::CharCodeAt, "CharCodeAt");
-
 void CodeGenerator::visitCharCodeAt(LCharCodeAt* lir) {
   Register str = ToRegister(lir->str());
   Register index = ToRegister(lir->index());
   Register output = ToRegister(lir->output());
   Register temp = ToRegister(lir->temp());
 
-  OutOfLineCode* ool = oolCallVM(CharCodeAtInfo, lir, ArgList(str, index),
-                                 StoreRegisterTo(output));
+  using Fn = bool (*)(JSContext*, HandleString, int32_t, uint32_t*);
+  OutOfLineCode* ool = oolCallVM<Fn, jit::CharCodeAt>(lir, ArgList(str, index),
+                                                      StoreRegisterTo(output));
   masm.loadStringChar(str, index, output, temp, ool->entry());
   masm.bind(ool->rejoin());
 }
 
-typedef JSFlatString* (*StringFromCharCodeFn)(JSContext*, int32_t);
-static const VMFunction StringFromCharCodeInfo =
-    FunctionInfo<StringFromCharCodeFn>(jit::StringFromCharCode,
-                                       "StringFromCharCode");
-
 void CodeGenerator::visitFromCharCode(LFromCharCode* lir) {
   Register code = ToRegister(lir->code());
   Register output = ToRegister(lir->output());
 
-  OutOfLineCode* ool = oolCallVM(StringFromCharCodeInfo, lir, ArgList(code),
-                                 StoreRegisterTo(output));
+  using Fn = JSFlatString* (*)(JSContext*, int32_t);
+  OutOfLineCode* ool = oolCallVM<Fn, jit::StringFromCharCode>(
+      lir, ArgList(code), StoreRegisterTo(output));
 
   // OOL path if code >= UNIT_STATIC_LIMIT.
   masm.boundsCheck32PowerOfTwo(code, StaticStrings::UNIT_STATIC_LIMIT,
                                ool->entry());
 
   masm.movePtr(ImmPtr(&gen->runtime->staticStrings().unitStaticTable), output);
   masm.loadPtr(BaseIndex(output, code, ScalePointer), output);
 
   masm.bind(ool->rejoin());
 }
 
-typedef JSString* (*StringFromCodePointFn)(JSContext*, int32_t);
-static const VMFunction StringFromCodePointInfo =
-    FunctionInfo<StringFromCodePointFn>(jit::StringFromCodePoint,
-                                        "StringFromCodePoint");
-
 void CodeGenerator::visitFromCodePoint(LFromCodePoint* lir) {
   Register codePoint = ToRegister(lir->codePoint());
   Register output = ToRegister(lir->output());
   Register temp1 = ToRegister(lir->temp1());
   Register temp2 = ToRegister(lir->temp2());
   LSnapshot* snapshot = lir->snapshot();
 
   // The OOL path is only taken when we can't allocate the inline string.
-  OutOfLineCode* ool = oolCallVM(StringFromCodePointInfo, lir,
-                                 ArgList(codePoint), StoreRegisterTo(output));
+  using Fn = JSString* (*)(JSContext*, int32_t);
+  OutOfLineCode* ool = oolCallVM<Fn, jit::StringFromCodePoint>(
+      lir, ArgList(codePoint), StoreRegisterTo(output));
 
   Label isTwoByte;
   Label* done = ool->rejoin();
 
   static_assert(
       StaticStrings::UNIT_STATIC_LIMIT - 1 == JSString::MAX_LATIN1_CHAR,
       "Latin-1 strings can be loaded from static strings");
   masm.boundsCheck32PowerOfTwo(codePoint, StaticStrings::UNIT_STATIC_LIMIT,
@@ -9998,54 +9878,46 @@ void CodeGenerator::visitStoreUnboxedPoi
     StoreUnboxedPointer(masm, address, type, value, preBarrier);
   } else {
     BaseIndex address(elements, ToRegister(index), ScalePointer,
                       offsetAdjustment);
     StoreUnboxedPointer(masm, address, type, value, preBarrier);
   }
 }
 
-typedef NativeObject* (*ConvertUnboxedObjectToNativeFn)(JSContext*, JSObject*);
-static const VMFunction ConvertUnboxedPlainObjectToNativeInfo =
-    FunctionInfo<ConvertUnboxedObjectToNativeFn>(
-        UnboxedPlainObject::convertToNative,
-        "UnboxedPlainObject::convertToNative");
-
 void CodeGenerator::visitConvertUnboxedObjectToNative(
     LConvertUnboxedObjectToNative* lir) {
   Register object = ToRegister(lir->getOperand(0));
   Register temp = ToTempRegisterOrInvalid(lir->temp());
 
   // The call will return the same object so StoreRegisterTo(object) is safe.
-  OutOfLineCode* ool = oolCallVM(ConvertUnboxedPlainObjectToNativeInfo, lir,
-                                 ArgList(object), StoreRegisterTo(object));
+  using Fn = NativeObject* (*)(JSContext*, JSObject*);
+  OutOfLineCode* ool = oolCallVM<Fn, UnboxedPlainObject::convertToNative>(
+      lir, ArgList(object), StoreRegisterTo(object));
 
   masm.branchTestObjGroup(Assembler::Equal, object, lir->mir()->group(), temp,
                           object, ool->entry());
   masm.bind(ool->rejoin());
 }
 
-typedef bool (*ArrayPopShiftFn)(JSContext*, HandleObject, MutableHandleValue);
-static const VMFunction ArrayPopDenseInfo =
-    FunctionInfo<ArrayPopShiftFn>(jit::ArrayPopDense, "ArrayPopDense");
-static const VMFunction ArrayShiftDenseInfo =
-    FunctionInfo<ArrayPopShiftFn>(jit::ArrayShiftDense, "ArrayShiftDense");
-
 void CodeGenerator::emitArrayPopShift(LInstruction* lir,
                                       const MArrayPopShift* mir, Register obj,
                                       Register elementsTemp,
                                       Register lengthTemp,
                                       TypedOrValueRegister out) {
   OutOfLineCode* ool;
 
+  using Fn = bool (*)(JSContext*, HandleObject, MutableHandleValue);
   if (mir->mode() == MArrayPopShift::Pop) {
-    ool = oolCallVM(ArrayPopDenseInfo, lir, ArgList(obj), StoreValueTo(out));
+    ool =
+        oolCallVM<Fn, jit::ArrayPopDense>(lir, ArgList(obj), StoreValueTo(out));
   } else {
     MOZ_ASSERT(mir->mode() == MArrayPopShift::Shift);
-    ool = oolCallVM(ArrayShiftDenseInfo, lir, ArgList(obj), StoreValueTo(out));
+    ool = oolCallVM<Fn, jit::ArrayShiftDense>(lir, ArgList(obj),
+                                              StoreValueTo(out));
   }
 
   // VM call if a write barrier is necessary.
   masm.branchTestNeedsIncrementalBarrier(Assembler::NonZero, ool->entry());
 
   // Load elements and initializedLength, and VM call if
   // length != initializedLength.
   masm.loadPtr(Address(obj, NativeObject::offsetOfElements()), elementsTemp);
@@ -10136,27 +10008,23 @@ void CodeGenerator::visitArrayPopShiftV(
 void CodeGenerator::visitArrayPopShiftT(LArrayPopShiftT* lir) {
   Register obj = ToRegister(lir->object());
   Register elements = ToRegister(lir->temp0());
   Register length = ToRegister(lir->temp1());
   TypedOrValueRegister out(lir->mir()->type(), ToAnyRegister(lir->output()));
   emitArrayPopShift(lir, lir->mir(), obj, elements, length, out);
 }
 
-typedef bool (*ArrayPushDenseFn)(JSContext*, HandleArrayObject, HandleValue,
-                                 uint32_t*);
-static const VMFunction ArrayPushDenseInfo =
-    FunctionInfo<ArrayPushDenseFn>(jit::ArrayPushDense, "ArrayPushDense");
-
 void CodeGenerator::emitArrayPush(LInstruction* lir, Register obj,
                                   const ConstantOrRegister& value,
                                   Register elementsTemp, Register length,
                                   Register spectreTemp) {
-  OutOfLineCode* ool = oolCallVM(ArrayPushDenseInfo, lir, ArgList(obj, value),
-                                 StoreRegisterTo(length));
+  using Fn = bool (*)(JSContext*, HandleArrayObject, HandleValue, uint32_t*);
+  OutOfLineCode* ool = oolCallVM<Fn, jit::ArrayPushDense>(
+      lir, ArgList(obj, value), StoreRegisterTo(length));
 
   // Load elements and length.
   masm.loadPtr(Address(obj, NativeObject::offsetOfElements()), elementsTemp);
   masm.load32(Address(elementsTemp, ObjectElements::offsetOfLength()), length);
 
   // Guard length == initializedLength.
   Address initLength(elementsTemp, ObjectElements::offsetOfInitializedLength());
   masm.branch32(Assembler::NotEqual, initLength, length, ool->entry());
@@ -11918,28 +11786,25 @@ void CodeGenerator::visitOutOfLineTypeOf
 void CodeGenerator::visitToAsyncIter(LToAsyncIter* lir) {
   pushArg(ToValue(lir, LToAsyncIter::NextMethodIndex));
   pushArg(ToRegister(lir->iterator()));
 
   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;
   FloatRegister temp = ToFloatRegister(lir->tempFloat());
   const ValueOperand out = ToOutValue(lir);
   ValueOperand input = ToValue(lir, LToIdV::Input);
 
-  OutOfLineCode* ool = oolCallVM(
-      ToIdInfo, lir, ArgList(ToValue(lir, LToIdV::Input)), StoreValueTo(out));
+  using Fn = bool (*)(JSContext*, HandleValue, MutableHandleValue);
+  OutOfLineCode* ool = oolCallVM<Fn, ToIdOperation>(
+      lir, ArgList(ToValue(lir, LToIdV::Input)), StoreValueTo(out));
 
   Register tag = masm.extractTag(input, out.scratchReg());
 
   masm.branchTestInt32(Assembler::NotEqual, tag, &notInt32);
   masm.moveValue(input, out);
   masm.jump(ool->rejoin());
 
   masm.bind(&notInt32);
@@ -12524,19 +12389,19 @@ void CodeGenerator::visitClampVToUint8(L
   ValueOperand operand = ToValue(lir, LClampVToUint8::Input);
   FloatRegister tempFloat = ToFloatRegister(lir->tempFloat());
   Register output = ToRegister(lir->output());
   MDefinition* input = lir->mir()->input();
 
   Label* stringEntry;
   Label* stringRejoin;
   if (input->mightBeType(MIRType::String)) {
-    OutOfLineCode* oolString =
-        oolCallVM(StringToNumberInfo, lir, ArgList(output),
-                  StoreFloatRegisterTo(tempFloat));
+    using Fn = bool (*)(JSContext*, JSString*, double*);
+    OutOfLineCode* oolString = oolCallVM<Fn, StringToNumber>(
+        lir, ArgList(output), StoreFloatRegisterTo(tempFloat));
     stringEntry = oolString->entry();
     stringRejoin = oolString->rejoin();
   } else {
     stringEntry = nullptr;
     stringRejoin = nullptr;
   }
 
   Label fails;
@@ -12554,20 +12419,16 @@ void CodeGenerator::visitInCache(LInCach
   Register object = ToRegister(ins->rhs());
   Register output = ToRegister(ins->output());
   Register temp = ToRegister(ins->temp());
 
   IonInIC cache(liveRegs, key, object, output, temp);
   addIC(ins, allocateIC(cache));
 }
 
-typedef bool (*OperatorInIFn)(JSContext*, uint32_t, HandleObject, bool*);
-static const VMFunction OperatorInIInfo =
-    FunctionInfo<OperatorInIFn>(OperatorInI, "OperatorInI");
-
 void CodeGenerator::visitInArray(LInArray* lir) {
   const MInArray* mir = lir->mir();
   Register elements = ToRegister(lir->elements());
   Register initLength = ToRegister(lir->initLength());
   Register output = ToRegister(lir->output());
 
   // When the array is not packed we need to do a hole check in addition to the
   // bounds check.
@@ -12576,19 +12437,20 @@ void CodeGenerator::visitInArray(LInArra
   OutOfLineCode* ool = nullptr;
   Label* failedInitLength = &falseBranch;
 
   if (lir->index()->isConstant()) {
     int32_t index = ToInt32(lir->index());
 
     MOZ_ASSERT_IF(index < 0, mir->needsNegativeIntCheck());
     if (mir->needsNegativeIntCheck()) {
-      ool = oolCallVM(OperatorInIInfo, lir,
-                      ArgList(Imm32(index), ToRegister(lir->object())),
-                      StoreRegisterTo(output));
+      using Fn = bool (*)(JSContext*, uint32_t, HandleObject, bool*);
+      ool = oolCallVM<Fn, OperatorInI>(
+          lir, ArgList(Imm32(index), ToRegister(lir->object())),
+          StoreRegisterTo(output));
       failedInitLength = ool->entry();
     }
 
     masm.branch32(Assembler::BelowOrEqual, initLength, Imm32(index),
                   failedInitLength);
     if (mir->needsHoleCheck()) {
       NativeObject::elementsSizeMustNotOverflow();
       Address address = Address(elements, index * sizeof(Value));
@@ -12606,19 +12468,20 @@ void CodeGenerator::visitInArray(LInArra
     if (mir->needsHoleCheck()) {
       BaseObjectElementIndex address(elements, ToRegister(lir->index()));
       masm.branchTestMagic(Assembler::Equal, address, &falseBranch);
     }
     masm.jump(&trueBranch);
 
     if (mir->needsNegativeIntCheck()) {
       masm.bind(&negativeIntCheck);
-      ool = oolCallVM(OperatorInIInfo, lir,
-                      ArgList(index, ToRegister(lir->object())),
-                      StoreRegisterTo(output));
+      using Fn = bool (*)(JSContext*, uint32_t, HandleObject, bool*);
+      ool = oolCallVM<Fn, OperatorInI>(
+          lir, ArgList(index, ToRegister(lir->object())),
+          StoreRegisterTo(output));
 
       masm.branch32(Assembler::LessThan, index, Imm32(0), ool->entry());
       masm.jump(&falseBranch);
     }
   }
 
   masm.bind(&trueBranch);
   masm.move32(Imm32(1), output);
@@ -12636,20 +12499,16 @@ void CodeGenerator::visitInArray(LInArra
 void CodeGenerator::visitInstanceOfO(LInstanceOfO* ins) {
   emitInstanceOf(ins, ins->mir()->prototypeObject());
 }
 
 void CodeGenerator::visitInstanceOfV(LInstanceOfV* ins) {
   emitInstanceOf(ins, ins->mir()->prototypeObject());
 }
 
-typedef bool (*IsPrototypeOfFn)(JSContext*, HandleObject, JSObject*, bool*);
-static const VMFunction IsPrototypeOfInfo =
-    FunctionInfo<IsPrototypeOfFn>(IsPrototypeOf, "IsPrototypeOf");
-
 void CodeGenerator::emitInstanceOf(LInstruction* ins,
                                    JSObject* prototypeObject) {
   // This path implements fun_hasInstance when the function's prototype is
   // known to be prototypeObject.
 
   Label done;
   Register output = ToRegister(ins->getDef(0));
 
@@ -12699,19 +12558,19 @@ void CodeGenerator::emitInstanceOf(LInst
   }
 
   // Make a VM call if an object with a lazy proto was found on the prototype
   // chain. This currently occurs only for cross compartment wrappers, which
   // we do not expect to be compared with non-wrapper functions from this
   // compartment. Otherwise, we stopped on a nullptr prototype and the output
   // register is already correct.
 
-  OutOfLineCode* ool = oolCallVM(IsPrototypeOfInfo, ins,
-                                 ArgList(ImmGCPtr(prototypeObject), objReg),
-                                 StoreRegisterTo(output));
+  using Fn = bool (*)(JSContext*, HandleObject, JSObject*, bool*);
+  OutOfLineCode* ool = oolCallVM<Fn, IsPrototypeOf>(
+      ins, ArgList(ImmGCPtr(prototypeObject), objReg), StoreRegisterTo(output));
 
   // Regenerate the original lhs object for the VM call.
   Label regenerate, *lazyEntry;
   if (objReg != output) {
     lazyEntry = ool->entry();
   } else {
     masm.bind(&regenerate);
     lazyEntry = &regenerate;
@@ -13054,33 +12913,29 @@ void CodeGenerator::visitOutOfLineIsCall
   masm.setupUnalignedABICall(output);
   masm.passABIArg(object);
   masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, ObjectIsCallable));
   masm.storeCallBoolResult(output);
   restoreVolatile(output);
   masm.jump(ool->rejoin());
 }
 
-typedef bool (*CheckIsCallableFn)(JSContext*, HandleValue, CheckIsCallableKind);
-static const VMFunction CheckIsCallableInfo =
-    FunctionInfo<CheckIsCallableFn>(CheckIsCallable, "CheckIsCallable");
-
 void CodeGenerator::visitCheckIsCallable(LCheckIsCallable* ins) {
   ValueOperand checkValue = ToValue(ins, LCheckIsCallable::CheckValue);
   Register temp = ToRegister(ins->temp());
 
   // OOL code is used in the following 2 cases:
   //   * checkValue is not callable
   //   * checkValue is proxy and it's unknown whether it's callable or not
   // CheckIsCallable checks if passed value is callable, regardless of the
   // cases above.  IsCallable operation is not observable and checking it
   // again doesn't matter.
-  OutOfLineCode* ool = oolCallVM(
-      CheckIsCallableInfo, ins,
-      ArgList(checkValue, Imm32(ins->mir()->checkKind())), StoreNothing());
+  using Fn = bool (*)(JSContext*, HandleValue, CheckIsCallableKind);
+  OutOfLineCode* ool = oolCallVM<Fn, CheckIsCallable>(
+      ins, ArgList(checkValue, Imm32(ins->mir()->checkKind())), StoreNothing());
 
   masm.branchTestObject(Assembler::NotEqual, checkValue, ool->entry());
 
   Register object = masm.extractObject(checkValue, temp);
   emitIsCallableOrConstructor<Callable>(object, temp, ool->entry());
 
   masm.branchTest32(Assembler::Zero, temp, temp, ool->entry());
 
@@ -13120,20 +12975,16 @@ void CodeGenerator::visitOutOfLineIsCons
   masm.setupUnalignedABICall(output);
   masm.passABIArg(object);
   masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, ObjectIsConstructor));
   masm.storeCallBoolResult(output);
   restoreVolatile(output);
   masm.jump(ool->rejoin());
 }
 
-typedef bool (*IsArrayFn)(JSContext*, HandleObject, bool*);
-static const VMFunction IsArrayInfo =
-    FunctionInfo<IsArrayFn>(JS::IsArray, "IsArray");
-
 static void EmitObjectIsArray(MacroAssembler& masm, OutOfLineCode* ool,
                               Register obj, Register output,
                               Label* notArray = nullptr) {
   masm.loadObjClassUnsafe(obj, output);
 
   Label isArray;
   masm.branchPtr(Assembler::Equal, output, ImmPtr(&ArrayObject::class_),
                  &isArray);
@@ -13152,48 +13003,46 @@ static void EmitObjectIsArray(MacroAssem
 
   masm.bind(ool->rejoin());
 }
 
 void CodeGenerator::visitIsArrayO(LIsArrayO* lir) {
   Register object = ToRegister(lir->object());
   Register output = ToRegister(lir->output());
 
-  OutOfLineCode* ool =
-      oolCallVM(IsArrayInfo, lir, ArgList(object), StoreRegisterTo(output));
+  using Fn = bool (*)(JSContext*, HandleObject, bool*);
+  OutOfLineCode* ool = oolCallVM<Fn, js::IsArrayFromJit>(
+      lir, ArgList(object), StoreRegisterTo(output));
   EmitObjectIsArray(masm, ool, object, output);
 }
 
 void CodeGenerator::visitIsArrayV(LIsArrayV* lir) {
   ValueOperand val = ToValue(lir, LIsArrayV::Value);
   Register output = ToRegister(lir->output());
   Register temp = ToRegister(lir->temp());
 
   Label notArray;
   masm.branchTestObject(Assembler::NotEqual, val, &notArray);
   masm.unboxObject(val, temp);
 
-  OutOfLineCode* ool =
-      oolCallVM(IsArrayInfo, lir, ArgList(temp), StoreRegisterTo(output));
+  using Fn = bool (*)(JSContext*, HandleObject, bool*);
+  OutOfLineCode* ool = oolCallVM<Fn, js::IsArrayFromJit>(
+      lir, ArgList(temp), StoreRegisterTo(output));
   EmitObjectIsArray(masm, ool, temp, output, &notArray);
 }
 
-typedef bool (*IsPossiblyWrappedTypedArrayFn)(JSContext*, JSObject*, bool*);
-static const VMFunction IsPossiblyWrappedTypedArrayInfo =
-    FunctionInfo<IsPossiblyWrappedTypedArrayFn>(
-        jit::IsPossiblyWrappedTypedArray, "IsPossiblyWrappedTypedArray");
-
 void CodeGenerator::visitIsTypedArray(LIsTypedArray* lir) {
   Register object = ToRegister(lir->object());
   Register output = ToRegister(lir->output());
 
   OutOfLineCode* ool = nullptr;
   if (lir->mir()->isPossiblyWrapped()) {
-    ool = oolCallVM(IsPossiblyWrappedTypedArrayInfo, lir, ArgList(object),
-                    StoreRegisterTo(output));
+    using Fn = bool (*)(JSContext*, JSObject*, bool*);
+    ool = oolCallVM<Fn, jit::IsPossiblyWrappedTypedArray>(
+        lir, ArgList(object), StoreRegisterTo(output));
   }
 
   Label notTypedArray;
   Label done;
 
   static_assert(Scalar::Int8 == 0, "Int8 is the first typed array class");
   static_assert((Scalar::Uint8Clamped - Scalar::Int8) ==
                     Scalar::MaxTypedArrayViewType - 1,
@@ -13510,18 +13359,19 @@ void CodeGenerator::visitAssertRangeV(LA
     }
   }
 
   masm.assumeUnreachable("Incorrect range for Value.");
   masm.bind(&done);
 }
 
 void CodeGenerator::visitInterruptCheck(LInterruptCheck* lir) {
+  using Fn = bool (*)(JSContext*);
   OutOfLineCode* ool =
-      oolCallVM(InterruptCheckInfo, lir, ArgList(), StoreNothing());
+      oolCallVM<Fn, InterruptCheck>(lir, ArgList(), StoreNothing());
 
   if (lir->mir()->trackRecordReplayProgress()) {
     masm.inc64(
         AbsoluteAddress(mozilla::recordreplay::ExecutionProgressCounter()));
   }
 
   const void* interruptAddr = gen->runtime->addressOfInterruptBits();
   masm.branch32(Assembler::NotEqual, AbsoluteAddress(interruptAddr), Imm32(0),
@@ -13584,32 +13434,26 @@ void CodeGenerator::visitWasmLoadTls(LWa
       masm.load32(Address(ToRegister(ins->tlsPtr()), ins->mir()->offset()),
                   ToRegister(ins->output()));
       break;
     default:
       MOZ_CRASH("MIRType not supported in WasmLoadTls");
   }
 }
 
-typedef bool (*RecompileFn)(JSContext*);
-static const VMFunction RecompileFnInfo =
-    FunctionInfo<RecompileFn>(Recompile, "Recompile");
-
-typedef bool (*ForcedRecompileFn)(JSContext*);
-static const VMFunction ForcedRecompileFnInfo =
-    FunctionInfo<ForcedRecompileFn>(ForcedRecompile, "ForcedRecompile");
-
 void CodeGenerator::visitRecompileCheck(LRecompileCheck* ins) {
   Label done;
   Register tmp = ToRegister(ins->scratch());
   OutOfLineCode* ool;
+
+  using Fn = bool (*)(JSContext*);
   if (ins->mir()->forceRecompilation()) {
-    ool = oolCallVM(ForcedRecompileFnInfo, ins, ArgList(), StoreNothing());
-  } else {
-    ool = oolCallVM(RecompileFnInfo, ins, ArgList(), StoreNothing());
+    ool = oolCallVM<Fn, IonForcedRecompile>(ins, ArgList(), StoreNothing());
+  } else {
+    ool = oolCallVM<Fn, IonRecompile>(ins, ArgList(), StoreNothing());
   }
 
   // Check if warm-up counter is high enough.
   AbsoluteAddress warmUpCount =
       AbsoluteAddress(ins->mir()->script()->addressOfWarmUpCounter());
   if (ins->mir()->increaseWarmUpCounter()) {
     masm.load32(warmUpCount, tmp);
     masm.add32(Imm32(1), tmp);
@@ -13720,27 +13564,22 @@ void CodeGenerator::visitCheckReturn(LCh
   masm.branchTestObject(Assembler::Equal, returnValue, &noChecks);
   masm.branchTestUndefined(Assembler::NotEqual, returnValue, &bail);
   masm.branchTestMagicValue(Assembler::Equal, thisValue,
                             JS_UNINITIALIZED_LEXICAL, &bail);
   bailoutFrom(&bail, ins->snapshot());
   masm.bind(&noChecks);
 }
 
-typedef bool (*ThrowCheckIsObjectFn)(JSContext*, CheckIsObjectKind);
-static const VMFunction ThrowCheckIsObjectInfo =
-    FunctionInfo<ThrowCheckIsObjectFn>(ThrowCheckIsObject,
-                                       "ThrowCheckIsObject");
-
 void CodeGenerator::visitCheckIsObj(LCheckIsObj* ins) {
   ValueOperand checkValue = ToValue(ins, LCheckIsObj::CheckValue);
 
-  OutOfLineCode* ool =
-      oolCallVM(ThrowCheckIsObjectInfo, ins,
-                ArgList(Imm32(ins->mir()->checkKind())), StoreNothing());
+  using Fn = bool (*)(JSContext*, CheckIsObjectKind);
+  OutOfLineCode* ool = oolCallVM<Fn, ThrowCheckIsObject>(
+      ins, ArgList(Imm32(ins->mir()->checkKind())), StoreNothing());
   masm.branchTestObject(Assembler::NotEqual, checkValue, ool->entry());
   masm.bind(ool->rejoin());
 }
 
 void CodeGenerator::visitCheckObjCoercible(LCheckObjCoercible* ins) {
   ValueOperand checkValue = ToValue(ins, LCheckObjCoercible::CheckValue);
   Label fail, done;
   masm.branchTestNull(Assembler::Equal, checkValue, &fail);
@@ -13899,35 +13738,28 @@ void CodeGenerator::visitNaNToZero(LNaNT
     FloatRegister scratch = ToFloatRegister(lir->tempDouble());
     masm.loadConstantDouble(0.0, scratch);
     masm.branchDouble(Assembler::DoubleEqualOrUnordered, input, scratch,
                       ool->entry());
   }
   masm.bind(ool->rejoin());
 }
 
-typedef bool (*FinishBoundFunctionInitFn)(JSContext* cx, HandleFunction bound,
-                                          HandleObject target,
-                                          int32_t argCount);
-static const VMFunction FinishBoundFunctionInitInfo =
-    FunctionInfo<FinishBoundFunctionInitFn>(
-        JSFunction::finishBoundFunctionInit,
-        "JSFunction::finishBoundFunctionInit");
-
 void CodeGenerator::visitFinishBoundFunctionInit(
     LFinishBoundFunctionInit* lir) {
   Register bound = ToRegister(lir->bound());
   Register target = ToRegister(lir->target());
   Register argCount = ToRegister(lir->argCount());
   Register temp1 = ToRegister(lir->temp1());
   Register temp2 = ToRegister(lir->temp2());
 
-  OutOfLineCode* ool =
-      oolCallVM(FinishBoundFunctionInitInfo, lir,
-                ArgList(bound, target, argCount), StoreNothing());
+  using Fn = bool (*)(JSContext * cx, HandleFunction bound, HandleObject target,
+                      int32_t argCount);
+  OutOfLineCode* ool = oolCallVM<Fn, JSFunction::finishBoundFunctionInit>(
+      lir, ArgList(bound, target, argCount), StoreNothing());
   Label* slowPath = ool->entry();
 
   const size_t boundLengthOffset =
       FunctionExtended::offsetOfExtendedSlot(BOUND_FUN_LENGTH_SLOT);
 
   // Take the slow path if the target is not a JSFunction.
   masm.branchTestObjClass(Assembler::NotEqual, target, &JSFunction::class_,
                           temp1, target, slowPath);
@@ -14057,27 +13889,24 @@ void CodeGenerator::visitIsPackedArray(L
   masm.loadPtr(Address(array, NativeObject::offsetOfElements()), elementsTemp);
   masm.load32(Address(elementsTemp, ObjectElements::offsetOfLength()), output);
 
   // Test length == initializedLength.
   Address initLength(elementsTemp, ObjectElements::offsetOfInitializedLength());
   masm.cmp32Set(Assembler::Equal, initLength, output, output);
 }
 
-typedef bool (*GetPrototypeOfFn)(JSContext*, HandleObject, MutableHandleValue);
-static const VMFunction GetPrototypeOfInfo =
-    FunctionInfo<GetPrototypeOfFn>(jit::GetPrototypeOf, "GetPrototypeOf");
-
 void CodeGenerator::visitGetPrototypeOf(LGetPrototypeOf* lir) {
   Register target = ToRegister(lir->target());
   ValueOperand out = ToOutValue(lir);
   Register scratch = out.scratchReg();
 
-  OutOfLineCode* ool =
-      oolCallVM(GetPrototypeOfInfo, lir, ArgList(target), StoreValueTo(out));
+  using Fn = bool (*)(JSContext*, HandleObject, MutableHandleValue);
+  OutOfLineCode* ool = oolCallVM<Fn, jit::GetPrototypeOf>(lir, ArgList(target),
+                                                          StoreValueTo(out));
 
   MOZ_ASSERT(uintptr_t(TaggedProto::LazyProto) == 1);
 
   masm.loadObjProto(target, scratch);
 
   Label hasProto;
   masm.branchPtr(Assembler::Above, scratch, ImmWord(1), &hasProto);
 
--- a/js/src/jit/CodeGenerator.h
+++ b/js/src/jit/CodeGenerator.h
@@ -30,17 +30,17 @@
 #  error "Unknown architecture!"
 #endif
 
 #include "wasm/WasmGC.h"
 
 namespace js {
 namespace jit {
 
-template <class ArgSeq, class StoreOutputTo>
+template <typename Fn, Fn fn, class ArgSeq, class StoreOutputTo>
 class OutOfLineCallVM;
 
 enum class SwitchTableType { Inline, OutOfLine };
 
 template <SwitchTableType tableType>
 class OutOfLineSwitch;
 class OutOfLineTestObject;
 class OutOfLineNewArray;
@@ -71,30 +71,25 @@ 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 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);
+  template <typename Fn, Fn fn, class ArgSeq, class StoreOutputTo>
+  inline OutOfLineCode* oolCallVM(LInstruction* ins, const ArgSeq& args,
+                                  const StoreOutputTo& out);
 
  public:
   CodeGenerator(MIRGenerator* gen, LIRGraph* graph,
                 MacroAssembler* masm = nullptr);
   ~CodeGenerator();
 
   MOZ_MUST_USE bool generate();
   MOZ_MUST_USE bool generateWasm(wasm::FuncTypeIdDesc funcTypeId,
@@ -106,18 +101,19 @@ class CodeGenerator final : public CodeG
                                  wasm::StackMaps* stackMaps);
 
   MOZ_MUST_USE bool link(JSContext* cx, CompilerConstraintList* constraints);
 
   void emitOOLTestObject(Register objreg, Label* ifTruthy, Label* ifFalsy,
                          Register scratch);
   void emitIntToString(Register input, Register output, Label* ool);
 
-  template <class ArgSeq, class StoreOutputTo>
-  void visitOutOfLineCallVM(OutOfLineCallVM<ArgSeq, StoreOutputTo>* ool);
+  template <typename Fn, Fn fn, class ArgSeq, class StoreOutputTo>
+  void visitOutOfLineCallVM(
+      OutOfLineCallVM<Fn, fn, ArgSeq, StoreOutputTo>* ool);
 
   void visitOutOfLineRegExpMatcher(OutOfLineRegExpMatcher* ool);
   void visitOutOfLineRegExpSearcher(OutOfLineRegExpSearcher* ool);
   void visitOutOfLineRegExpTester(OutOfLineRegExpTester* ool);
   void visitOutOfLineRegExpPrototypeOptimizable(
       OutOfLineRegExpPrototypeOptimizable* ool);
   void visitOutOfLineRegExpInstanceOptimizable(
       OutOfLineRegExpInstanceOptimizable* ool);
--- a/js/src/jit/VMFunctionList-inl.h
+++ b/js/src/jit/VMFunctionList-inl.h
@@ -23,45 +23,55 @@ namespace js {
 namespace jit {
 
 // List of all VM functions to be used with callVM. Each entry stores the name
 // (must be unique, used for the VMFunctionId enum and profiling) and the C++
 // function to be called. This list must be sorted on the name field.
 #define VMFUNCTION_LIST(_)                                                     \
   _(AddValues, js::AddValues)                                                  \
   _(ArgumentsObjectCreateForIon, js::ArgumentsObject::createForIon)            \
+  _(ArrayConstructorOneArg, js::ArrayConstructorOneArg)                        \
   _(ArrayJoin, js::jit::ArrayJoin)                                             \
+  _(ArrayPopDense, js::jit::ArrayPopDense)                                     \
+  _(ArrayPushDense, js::jit::ArrayPushDense)                                   \
+  _(ArrayShiftDense, js::jit::ArrayShiftDense)                                 \
   _(ArraySliceDense, js::ArraySliceDense)                                      \
   _(AsyncFunctionAwait, js::AsyncFunctionAwait)                                \
   _(AsyncFunctionResolve, js::AsyncFunctionResolve)                            \
   _(BaselineDebugPrologue, js::jit::DebugPrologue)                             \
   _(BaselineGetFunctionThis, js::jit::BaselineGetFunctionThis)                 \
   _(BaselineThrowInitializedThis, js::jit::BaselineThrowInitializedThis)       \
   _(BaselineThrowUninitializedThis, js::jit::BaselineThrowUninitializedThis)   \
   _(BindVarOperation, js::BindVarOperation)                                    \
   _(BitAnd, js::BitAnd)                                                        \
   _(BitLsh, js::BitLsh)                                                        \
   _(BitNot, js::BitNot)                                                        \
   _(BitOr, js::BitOr)                                                          \
   _(BitRsh, js::BitRsh)                                                        \
   _(BitXor, js::BitXor)                                                        \
+  _(BoxNonStrictThis, js::BoxNonStrictThis)                                    \
   _(BuiltinProtoOperation, js::BuiltinProtoOperation)                          \
+  _(CharCodeAt, js::jit::CharCodeAt)                                           \
   _(CheckClassHeritageOperation, js::CheckClassHeritageOperation)              \
   _(CheckGlobalOrEvalDeclarationConflicts,                                     \
     js::CheckGlobalOrEvalDeclarationConflicts)                                 \
   _(CheckIsCallable, js::jit::CheckIsCallable)                                 \
   _(CheckOverRecursed, js::jit::CheckOverRecursed)                             \
   _(CheckOverRecursedBaseline, js::jit::CheckOverRecursedBaseline)             \
   _(CloneRegExpObject, js::CloneRegExpObject)                                  \
+  _(ConcatStrings, js::ConcatStrings<CanGC>)                                   \
+  _(ConvertElementsToDoubles, js::ObjectElements::ConvertElementsToDoubles)    \
+  _(CopyElementsForWrite, js::NativeObject::CopyElementsForWrite)              \
   _(CopyLexicalEnvironmentObject, js::jit::CopyLexicalEnvironmentObject)       \
   _(CreateAsyncFromSyncIterator, js::CreateAsyncFromSyncIterator)              \
   _(CreateDerivedTypedObj, js::jit::CreateDerivedTypedObj)                     \
   _(CreateGenerator, js::jit::CreateGenerator)                                 \
   _(CreateThis, js::jit::CreateThis)                                           \
   _(CreateThisForFunctionWithProto, js::CreateThisForFunctionWithProto)        \
+  _(CreateThisWithTemplate, js::CreateThisWithTemplate)                        \
   _(DebugAfterYield, js::jit::DebugAfterYield)                                 \
   _(DebugEpilogueOnBaselineReturn, js::jit::DebugEpilogueOnBaselineReturn)     \
   _(DebugLeaveLexicalEnv, js::jit::DebugLeaveLexicalEnv)                       \
   _(DebugLeaveThenFreshenLexicalEnv, js::jit::DebugLeaveThenFreshenLexicalEnv) \
   _(DebugLeaveThenPopLexicalEnv, js::jit::DebugLeaveThenPopLexicalEnv)         \
   _(DebugLeaveThenRecreateLexicalEnv,                                          \
     js::jit::DebugLeaveThenRecreateLexicalEnv)                                 \
   _(Debug_CheckSelfHosted, js::Debug_CheckSelfHosted)                          \
@@ -75,81 +85,102 @@ namespace jit {
   _(DeletePropertyNonStrict, js::DeletePropertyJit<false>)                     \
   _(DeletePropertyStrict, js::DeletePropertyJit<true>)                         \
   _(DirectEvalStringFromIon, js::DirectEvalStringFromIon)                      \
   _(DivValues, js::DivValues)                                                  \
   _(DoToNumber, js::jit::DoToNumber)                                           \
   _(DoToNumeric, js::jit::DoToNumeric)                                         \
   _(EnterWith, js::jit::EnterWith)                                             \
   _(FinalSuspend, js::jit::FinalSuspend)                                       \
+  _(FinishBoundFunctionInit, JSFunction::finishBoundFunctionInit)              \
   _(FreshenLexicalEnv, js::jit::FreshenLexicalEnv)                             \
   _(FunWithProtoOperation, js::FunWithProtoOperation)                          \
   _(GetAndClearException, js::GetAndClearException)                            \
   _(GetElementOperation, js::GetElementOperation)                              \
+  _(GetFirstDollarIndexRaw, js::GetFirstDollarIndexRaw)                        \
   _(GetImportOperation, js::GetImportOperation)                                \
   _(GetIntrinsicValue, js::jit::GetIntrinsicValue)                             \
   _(GetNonSyntacticGlobalThis, js::GetNonSyntacticGlobalThis)                  \
   _(GetOrCreateModuleMetaObject, js::GetOrCreateModuleMetaObject)              \
+  _(GetPrototypeOf, js::jit::GetPrototypeOf)                                   \
   _(GetValueProperty, js::GetValueProperty)                                    \
   _(GlobalNameConflictsCheckFromIon, js::jit::GlobalNameConflictsCheckFromIon) \
   _(GreaterThan, js::jit::GreaterThan)                                         \
   _(GreaterThanOrEqual, js::jit::GreaterThanOrEqual)                           \
   _(HomeObjectSuperBase, js::HomeObjectSuperBase)                              \
   _(ImplicitThisOperation, js::ImplicitThisOperation)                          \
   _(ImportMetaOperation, js::ImportMetaOperation)                              \
   _(InitElemGetterSetterOperation, js::InitElemGetterSetterOperation)          \
   _(InitElemOperation, js::InitElemOperation)                                  \
   _(InitElementArray, js::InitElementArray)                                    \
   _(InitFunctionEnvironmentObjects, js::jit::InitFunctionEnvironmentObjects)   \
   _(InitPropGetterSetterOperation, js::InitPropGetterSetterOperation)          \
   _(InitRestParameter, js::jit::InitRestParameter)                             \
+  _(InlineTypedObjectCreateCopy, js::InlineTypedObject::createCopy)            \
+  _(Int32ToString, js::Int32ToString<CanGC>)                                   \
   _(InterpretResume, js::jit::InterpretResume)                                 \
   _(InterruptCheck, js::jit::InterruptCheck)                                   \
   _(InvokeFunction, js::jit::InvokeFunction)                                   \
   _(InvokeFunctionShuffleNewTarget, js::jit::InvokeFunctionShuffleNewTarget)   \
   _(IonBinaryArithICUpdate, js::jit::IonBinaryArithIC::update)                 \
   _(IonBindNameICUpdate, js::jit::IonBindNameIC::update)                       \
   _(IonCompareICUpdate, js::jit::IonCompareIC::update)                         \
   _(IonCompileScriptForBaseline, js::jit::IonCompileScriptForBaseline)         \
+  _(IonForcedRecompile, js::jit::IonForcedRecompile)                           \
   _(IonGetIteratorICUpdate, js::jit::IonGetIteratorIC::update)                 \
   _(IonGetNameICUpdate, js::jit::IonGetNameIC::update)                         \
   _(IonGetPropSuperICUpdate, js::jit::IonGetPropSuperIC::update)               \
   _(IonGetPropertyICUpdate, js::jit::IonGetPropertyIC::update)                 \
   _(IonHasOwnICUpdate, js::jit::IonHasOwnIC::update)                           \
   _(IonInICUpdate, js::jit::IonInIC::update)                                   \
   _(IonInstanceOfICUpdate, js::jit::IonInstanceOfIC::update)                   \
+  _(IonRecompile, js::jit::IonRecompile)                                       \
   _(IonSetPropertyICUpdate, js::jit::IonSetPropertyIC::update)                 \
   _(IonUnaryArithICUpdate, js::jit::IonUnaryArithIC::update)                   \
+  _(IsArrayFromJit, js::IsArrayFromJit)                                        \
+  _(IsPossiblyWrappedTypedArray, js::jit::IsPossiblyWrappedTypedArray)         \
+  _(IsPrototypeOf, js::IsPrototypeOf)                                          \
   _(Lambda, js::Lambda)                                                        \
   _(LambdaArrow, js::LambdaArrow)                                              \
   _(LeaveWith, js::jit::LeaveWith)                                             \
   _(LessThan, js::jit::LessThan)                                               \
   _(LessThanOrEqual, js::jit::LessThanOrEqual)                                 \
   _(LexicalEnvironmentObjectCreate, js::LexicalEnvironmentObject::create)      \
   _(LooselyEqual, js::jit::LooselyEqual<true>)                                 \
   _(LooselyNotEqual, js::jit::LooselyEqual<false>)                             \
   _(MakeDefaultConstructor, js::MakeDefaultConstructor)                        \
   _(ModValues, js::ModValues)                                                  \
   _(MulValues, js::MulValues)                                                  \
   _(MutatePrototype, js::jit::MutatePrototype)                                 \
+  _(NamedLambdaObjectCreateTemplateObject,                                     \
+    js::NamedLambdaObject::createTemplateObject)                               \
   _(NewArgumentsObject, js::jit::NewArgumentsObject)                           \
   _(NewArrayCopyOnWriteOperation, js::NewArrayCopyOnWriteOperation)            \
+  _(NewArrayIteratorObject, js::NewArrayIteratorObject)                        \
   _(NewArrayOperation, js::NewArrayOperation)                                  \
   _(NewArrayWithGroup, js::NewArrayWithGroup)                                  \
+  _(NewCallObject, js::jit::NewCallObject)                                     \
   _(NewDenseCopyOnWriteArray, js::NewDenseCopyOnWriteArray)                    \
   _(NewObjectOperation, js::NewObjectOperation)                                \
   _(NewObjectOperationWithTemplate, js::NewObjectOperationWithTemplate)        \
+  _(NewRegExpStringIteratorObject, js::NewRegExpStringIteratorObject)          \
+  _(NewStringIteratorObject, js::NewStringIteratorObject)                      \
+  _(NewStringObject, js::jit::NewStringObject)                                 \
   _(NewTypedArrayWithTemplateAndArray, js::NewTypedArrayWithTemplateAndArray)  \
   _(NewTypedArrayWithTemplateAndBuffer,                                        \
     js::NewTypedArrayWithTemplateAndBuffer)                                    \
+  _(NewTypedArrayWithTemplateAndLength,                                        \
+    js::NewTypedArrayWithTemplateAndLength)                                    \
   _(NormalSuspend, js::jit::NormalSuspend)                                     \
+  _(NumberToString, js::NumberToString<CanGC>)                                 \
   _(ObjectClassToString, js::ObjectClassToString)                              \
   _(ObjectCreateWithTemplate, js::ObjectCreateWithTemplate)                    \
   _(ObjectWithProtoOperation, js::ObjectWithProtoOperation)                    \
   _(OnDebuggerStatement, js::jit::OnDebuggerStatement)                         \
+  _(OperatorInI, js::jit::OperatorInI)                                         \
   _(OptimizeSpreadCall, js::OptimizeSpreadCall)                                \
   _(PopLexicalEnv, js::jit::PopLexicalEnv)                                     \
   _(PopVarEnv, js::jit::PopVarEnv)                                             \
   _(PowValues, js::PowValues)                                                  \
   _(ProcessCallSiteObjOperation, js::ProcessCallSiteObjOperation)              \
   _(PushLexicalEnv, js::jit::PushLexicalEnv)                                   \
   _(PushVarEnv, js::jit::PushVarEnv)                                           \
   _(RecreateLexicalEnv, js::jit::RecreateLexicalEnv)                           \
@@ -163,31 +194,40 @@ namespace jit {
   _(SetObjectElementWithReceiver, js::SetObjectElementWithReceiver)            \
   _(SetProperty, js::jit::SetProperty)                                         \
   _(SetPropertySuper, js::SetPropertySuper)                                    \
   _(SingletonObjectLiteralOperation, js::SingletonObjectLiteralOperation)      \
   _(StartDynamicModuleImport, js::StartDynamicModuleImport)                    \
   _(StrictlyEqual, js::jit::StrictlyEqual<true>)                               \
   _(StrictlyNotEqual, js::jit::StrictlyEqual<false>)                           \
   _(StringFlatReplaceString, js::StringFlatReplaceString)                      \
+  _(StringFromCharCode, js::jit::StringFromCharCode)                           \
+  _(StringFromCodePoint, js::jit::StringFromCodePoint)                         \
   _(StringReplace, js::jit::StringReplace)                                     \
   _(StringSplitString, js::StringSplitString)                                  \
   _(StringToLowerCase, js::StringToLowerCase)                                  \
+  _(StringToNumber, js::StringToNumber)                                        \
   _(StringToUpperCase, js::StringToUpperCase)                                  \
+  _(StringsEqual, js::jit::StringsEqual<true>)                                 \
+  _(StringsNotEqual, js::jit::StringsEqual<false>)                             \
   _(SubValues, js::SubValues)                                                  \
+  _(SubstringKernel, js::SubstringKernel)                                      \
   _(SuperFunOperation, js::SuperFunOperation)                                  \
   _(ThrowBadDerivedReturn, js::jit::ThrowBadDerivedReturn)                     \
   _(ThrowCheckIsObject, js::ThrowCheckIsObject)                                \
   _(ThrowMsgOperation, js::ThrowMsgOperation)                                  \
   _(ThrowObjectCoercible, js::jit::ThrowObjectCoercible)                       \
   _(ThrowOperation, js::ThrowOperation)                                        \
   _(ThrowRuntimeLexicalError, js::jit::ThrowRuntimeLexicalError)               \
   _(ToIdOperation, js::ToIdOperation)                                          \
+  _(ToObjectSlow, js::ToObjectSlow)                                            \
   _(ToStringSlow, js::ToStringSlow<CanGC>)                                     \
   _(TrySkipAwait, js::jit::TrySkipAwait)                                       \
+  _(UnboxedPlainObjectConvertToNative,                                         \
+    js::UnboxedPlainObject::convertToNative)                                   \
   _(UrshValues, js::UrshValues)
 
 enum class VMFunctionId {
 #define DEF_ID(name, fp) name,
   VMFUNCTION_LIST(DEF_ID)
 #undef DEF_ID
       Count
 };
--- a/js/src/jit/VMFunctions.cpp
+++ b/js/src/jit/VMFunctions.cpp
@@ -1269,21 +1269,23 @@ bool RecompileImpl(JSContext* cx, bool f
   MethodStatus status = Recompile(cx, script, nullptr, nullptr, force);
   if (status == Method_Error) {
     return false;
   }
 
   return true;
 }
 
-bool ForcedRecompile(JSContext* cx) {
+bool IonForcedRecompile(JSContext* cx) {
   return RecompileImpl(cx, /* force = */ true);
 }
 
-bool Recompile(JSContext* cx) { return RecompileImpl(cx, /* force = */ false); }
+bool IonRecompile(JSContext* cx) {
+  return RecompileImpl(cx, /* force = */ false);
+}
 
 bool SetDenseElement(JSContext* cx, HandleNativeObject obj, int32_t index,
                      HandleValue value, bool strict) {
   // This function is called from Ion code for StoreElementHole's OOL path.
   // In this case we know the object is native and that no type changes are
   // needed.
 
   DenseElementResult result = obj->setOrExtendDenseElements(
@@ -1992,16 +1994,10 @@ bool DoToNumber(JSContext* cx, HandleVal
   return ToNumber(cx, ret);
 }
 
 bool DoToNumeric(JSContext* cx, HandleValue arg, MutableHandleValue ret) {
   ret.set(arg);
   return ToNumeric(cx, ret);
 }
 
-typedef bool (*ToNumericFn)(JSContext*, HandleValue, MutableHandleValue);
-const VMFunction ToNumberInfo =
-    FunctionInfo<ToNumericFn>(DoToNumber, "ToNumber");
-const VMFunction ToNumericInfo =
-    FunctionInfo<ToNumericFn>(DoToNumeric, "ToNumeric");
-
 }  // namespace jit
 }  // namespace js
--- a/js/src/jit/VMFunctions.h
+++ b/js/src/jit/VMFunctions.h
@@ -1110,18 +1110,18 @@ MOZ_MUST_USE bool PopVarEnv(JSContext* c
 
 MOZ_MUST_USE bool InitBaselineFrameForOsr(BaselineFrame* frame,
                                           InterpreterFrame* interpFrame,
                                           uint32_t numStackValues);
 
 JSObject* CreateDerivedTypedObj(JSContext* cx, HandleObject descr,
                                 HandleObject owner, int32_t offset);
 
-MOZ_MUST_USE bool Recompile(JSContext* cx);
-MOZ_MUST_USE bool ForcedRecompile(JSContext* cx);
+MOZ_MUST_USE bool IonRecompile(JSContext* cx);
+MOZ_MUST_USE bool IonForcedRecompile(JSContext* cx);
 JSString* StringReplace(JSContext* cx, HandleString string,
                         HandleString pattern, HandleString repl);
 
 MOZ_MUST_USE bool SetDenseElement(JSContext* cx, HandleNativeObject obj,
                                   int32_t index, HandleValue value,
                                   bool strict);
 
 void AssertValidObjectPtr(JSContext* cx, JSObject* obj);
@@ -1238,19 +1238,16 @@ extern const VMFunction ProxySetProperty
 extern const VMFunction ProxyHasInfo;
 extern const VMFunction ProxyHasOwnInfo;
 
 extern const VMFunction NativeGetElementInfo;
 
 extern const VMFunction AddOrUpdateSparseElementHelperInfo;
 extern const VMFunction GetSparseElementHelperInfo;
 
-extern const VMFunction ToNumberInfo;
-extern const VMFunction ToNumericInfo;
-
 // TailCall VMFunctions
 extern const VMFunction DoConcatStringObjectInfo;
 
 enum class VMFunctionId;
 
 extern const VMFunctionData& GetVMFunction(VMFunctionId id);
 
 }  // namespace jit