Bug 1530937 part 15 - Convert callVMs in BaselineIC code. r=tcampbell
authorJan de Mooij <jdemooij@mozilla.com>
Tue, 12 Mar 2019 14:04:57 +0000
changeset 521530 5aee21579936
parent 521529 1e2091a92a1d
child 521531 6382f22140dd
push id10867
push userdvarga@mozilla.com
push dateThu, 14 Mar 2019 15:20:45 +0000
treeherdermozilla-beta@abad13547875 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstcampbell
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 15 - Convert callVMs in BaselineIC code. r=tcampbell Differential Revision: https://phabricator.services.mozilla.com/D23108
js/src/jit/BaselineIC.cpp
js/src/jit/BaselineIC.h
js/src/jit/VMFunctionList-inl.h
js/src/jit/VMFunctions.cpp
js/src/jit/VMFunctions.h
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -38,16 +38,17 @@
 #include "vm/TypedArrayObject.h"
 
 #include "builtin/Boolean-inl.h"
 
 #include "jit/JitFrames-inl.h"
 #include "jit/MacroAssembler-inl.h"
 #include "jit/shared/Lowering-shared-inl.h"
 #include "jit/SharedICHelpers-inl.h"
+#include "jit/VMFunctionList-inl.h"
 #include "vm/EnvironmentObject-inl.h"
 #include "vm/Interpreter-inl.h"
 #include "vm/JSScript-inl.h"
 #include "vm/StringObject-inl.h"
 #include "vm/UnboxedObject-inl.h"
 
 using mozilla::DebugOnly;
 
@@ -735,19 +736,19 @@ static IonOsrTempData* PrepareOsrTempDat
 
   JitSpew(JitSpew_BaselineOSR, "Allocated IonOsrTempData at %p", (void*)info);
   JitSpew(JitSpew_BaselineOSR, "Jitcode is %p", info->jitcode);
 
   // All done.
   return info;
 }
 
-static bool DoWarmUpCounterFallbackOSR(JSContext* cx, BaselineFrame* frame,
-                                       ICWarmUpCounter_Fallback* stub,
-                                       IonOsrTempData** infoPtr) {
+bool DoWarmUpCounterFallbackOSR(JSContext* cx, BaselineFrame* frame,
+                                ICWarmUpCounter_Fallback* stub,
+                                IonOsrTempData** infoPtr) {
   MOZ_ASSERT(infoPtr);
   *infoPtr = nullptr;
 
   RootedScript script(cx, frame->script());
   jsbytecode* pc = stub->icEntry()->pc(script);
   MOZ_ASSERT(JSOp(*pc) == JSOP_LOOPENTRY);
 
   FallbackICSpew(cx, stub, "WarmUpCounter(%d)", int(script->pcToOffset(pc)));
@@ -776,23 +777,16 @@ static bool DoWarmUpCounterFallbackOSR(J
   if (!info) {
     return false;
   }
   *infoPtr = info;
 
   return true;
 }
 
-typedef bool (*DoWarmUpCounterFallbackOSRFn)(JSContext*, BaselineFrame*,
-                                             ICWarmUpCounter_Fallback*,
-                                             IonOsrTempData** infoPtr);
-static const VMFunction DoWarmUpCounterFallbackOSRInfo =
-    FunctionInfo<DoWarmUpCounterFallbackOSRFn>(DoWarmUpCounterFallbackOSR,
-                                               "DoWarmUpCounterFallbackOSR");
-
 bool ICWarmUpCounter_Fallback::Compiler::generateStubCode(
     MacroAssembler& masm) {
   // Push a stub frame so that we can perform a non-tail call.
   enterStubFrame(masm, R1.scratchReg());
 
   Label noCompiledCode;
   // Call DoWarmUpCounterFallbackOSR to compile/check-for Ion-compiled function
   {
@@ -800,17 +794,19 @@ bool ICWarmUpCounter_Fallback::Compiler:
     masm.subFromStackPtr(Imm32(sizeof(void*)));
     masm.push(masm.getStackPointer());
 
     // Push stub pointer.
     masm.push(ICStubReg);
 
     pushStubPayload(masm, R0.scratchReg());
 
-    if (!callVM(DoWarmUpCounterFallbackOSRInfo, masm)) {
+    using Fn = bool (*)(JSContext*, BaselineFrame*, ICWarmUpCounter_Fallback*,
+                        IonOsrTempData * *infoPtr);
+    if (!callVM<Fn, DoWarmUpCounterFallbackOSR>(masm)) {
       return false;
     }
 
     // Pop IonOsrTempData pointer.
     masm.pop(R0.scratchReg());
 
     leaveStubFrame(masm);
 
@@ -1107,26 +1103,32 @@ JitCode* ICStubCompiler::getStubCode() {
 bool ICStubCompiler::tailCallVM(const VMFunction& fun, MacroAssembler& masm) {
   TrampolinePtr code = cx->runtime()->jitRuntime()->getVMWrapper(fun);
   MOZ_ASSERT(fun.expectTailCall == TailCall);
   uint32_t argSize = fun.explicitStackSlots() * sizeof(void*);
   EmitBaselineTailCallVM(code, masm, argSize);
   return true;
 }
 
-bool ICStubCompiler::callVM(const VMFunction& fun, MacroAssembler& masm) {
+bool ICStubCompiler::callVMInternal(MacroAssembler& masm, VMFunctionId id) {
   MOZ_ASSERT(inStubFrame_);
 
-  TrampolinePtr code = cx->runtime()->jitRuntime()->getVMWrapper(fun);
-  MOZ_ASSERT(fun.expectTailCall == NonTailCall);
+  TrampolinePtr code = cx->runtime()->jitRuntime()->getVMWrapper(id);
+  MOZ_ASSERT(GetVMFunction(id).expectTailCall == NonTailCall);
 
   EmitBaselineCallVM(code, masm);
   return true;
 }
 
+template <typename Fn, Fn fn>
+bool ICStubCompiler::callVM(MacroAssembler& masm) {
+  VMFunctionId id = VMFunctionToId<Fn, fn>::id;
+  return callVMInternal(masm, id);
+}
+
 void ICStubCompiler::enterStubFrame(MacroAssembler& masm, Register scratch) {
   EmitBaselineEnterStubFrame(masm, scratch);
 #ifdef DEBUG
   framePushedAtEnterStubFrame_ = masm.framePushed();
 #endif
 
   MOZ_ASSERT(!inStubFrame_);
   inStubFrame_ = true;
@@ -3714,35 +3716,16 @@ static bool TryAttachCallStub(JSContext*
     stub->addNewStub(newStub);
     *handled = true;
     return true;
   }
 
   return true;
 }
 
-static bool CopyStringSplitArray(JSContext* cx, HandleArrayObject arr,
-                                 MutableHandleValue result) {
-  MOZ_ASSERT(arr->isTenured(),
-             "ConstStringSplit needs a tenured template object");
-
-  uint32_t length = arr->getDenseInitializedLength();
-  MOZ_ASSERT(length == arr->length(),
-             "template object is a fully initialized array");
-
-  ArrayObject* nobj = NewFullyAllocatedArrayTryReuseGroup(cx, arr, length);
-  if (!nobj) {
-    return false;
-  }
-  nobj->initDenseElements(arr, 0, length);
-
-  result.setObject(*nobj);
-  return true;
-}
-
 static bool TryAttachConstStringSplit(JSContext* cx, ICCall_Fallback* stub,
                                       HandleScript script, uint32_t argc,
                                       HandleValue callee, Value* vp,
                                       jsbytecode* pc, HandleValue res,
                                       bool* attached) {
   if (stub->numOptimizedStubs() != 0) {
     return true;
   }
@@ -3799,19 +3782,18 @@ static bool TryAttachConstStringSplit(JS
     return false;
   }
 
   stub->addNewStub(newStub);
   *attached = true;
   return true;
 }
 
-static bool DoCallFallback(JSContext* cx, BaselineFrame* frame,
-                           ICCall_Fallback* stub, uint32_t argc, Value* vp,
-                           MutableHandleValue res) {
+bool DoCallFallback(JSContext* cx, BaselineFrame* frame, ICCall_Fallback* stub,
+                    uint32_t argc, Value* vp, MutableHandleValue res) {
   stub->incrementEnteredCount();
 
   RootedScript script(cx, frame->script());
   jsbytecode* pc = stub->icEntry()->pc(script);
   JSOp op = JSOp(*pc);
   FallbackICSpew(cx, stub, "Call(%s)", CodeName[op]);
 
   MOZ_ASSERT(argc == GET_ARGC(pc));
@@ -3929,19 +3911,19 @@ static bool DoCallFallback(JSContext* cx
   if (!handled) {
     if (canAttachStub) {
       stub->state().trackNotAttached();
     }
   }
   return true;
 }
 
-static bool DoSpreadCallFallback(JSContext* cx, BaselineFrame* frame,
-                                 ICCall_Fallback* stub, Value* vp,
-                                 MutableHandleValue res) {
+bool DoSpreadCallFallback(JSContext* cx, BaselineFrame* frame,
+                          ICCall_Fallback* stub, Value* vp,
+                          MutableHandleValue res) {
   stub->incrementEnteredCount();
 
   RootedScript script(cx, frame->script());
   jsbytecode* pc = stub->icEntry()->pc(script);
   JSOp op = JSOp(*pc);
   bool constructing = (op == JSOP_SPREADNEW || op == JSOP_SPREADSUPERCALL);
   FallbackICSpew(cx, stub, "SpreadCall(%s)", CodeName[op]);
 
@@ -4279,28 +4261,16 @@ void ICCallStubCompiler::pushArrayArgume
   masm.bind(&copyStart);
   masm.branchPtr(Assembler::Equal, endReg, startReg, &copyDone);
   masm.subPtr(Imm32(sizeof(Value)), endReg);
   masm.pushValue(Address(endReg, 0));
   masm.jump(&copyStart);
   masm.bind(&copyDone);
 }
 
-typedef bool (*DoCallFallbackFn)(JSContext*, BaselineFrame*, ICCall_Fallback*,
-                                 uint32_t, Value*, MutableHandleValue);
-static const VMFunction DoCallFallbackInfo =
-    FunctionInfo<DoCallFallbackFn>(DoCallFallback, "DoCallFallback");
-
-typedef bool (*DoSpreadCallFallbackFn)(JSContext*, BaselineFrame*,
-                                       ICCall_Fallback*, Value*,
-                                       MutableHandleValue);
-static const VMFunction DoSpreadCallFallbackInfo =
-    FunctionInfo<DoSpreadCallFallbackFn>(DoSpreadCallFallback,
-                                         "DoSpreadCallFallback");
-
 bool ICCall_Fallback::Compiler::generateStubCode(MacroAssembler& masm) {
   MOZ_ASSERT(R0 == JSReturnOperand);
 
   // Values are on the stack left-to-right. Calling convention wants them
   // right-to-left so duplicate them on the stack in reverse order.
   // |this| and callee are pushed last.
 
   AllocatableGeneralRegisterSet regs(availableGeneralRegs(0));
@@ -4331,17 +4301,19 @@ bool ICCall_Fallback::Compiler::generate
     masm.pushValue(Address(BaselineFrameReg,
                            valueOffset++ * sizeof(Value) + STUB_FRAME_SIZE));
 
     masm.push(masm.getStackPointer());
     masm.push(ICStubReg);
 
     PushStubPayload(masm, R0.scratchReg());
 
-    if (!callVM(DoSpreadCallFallbackInfo, masm)) {
+    using Fn = bool (*)(JSContext*, BaselineFrame*, ICCall_Fallback*, Value*,
+                        MutableHandleValue);
+    if (!callVM<Fn, DoSpreadCallFallback>(masm)) {
       return false;
     }
 
     leaveStubFrame(masm);
     EmitReturnFromIC(masm);
 
     // SPREADCALL is not yet supported in Ion, so do not generate asmcode for
     // bailout.
@@ -4357,17 +4329,19 @@ bool ICCall_Fallback::Compiler::generate
                     isConstructing_);
 
   masm.push(masm.getStackPointer());
   masm.push(R0.scratchReg());
   masm.push(ICStubReg);
 
   PushStubPayload(masm, R0.scratchReg());
 
-  if (!callVM(DoCallFallbackInfo, masm)) {
+  using Fn = bool (*)(JSContext*, BaselineFrame*, ICCall_Fallback*, uint32_t,
+                      Value*, MutableHandleValue);
+  if (!callVM<Fn, DoCallFallback>(masm)) {
     return false;
   }
 
   leaveStubFrame(masm);
   EmitReturnFromIC(masm);
 
   // This is the resume point used when bailout rewrites call stack to undo
   // Ion inlined frames. The return address pushed onto reconstructed stack
@@ -4419,21 +4393,16 @@ void ICCall_Fallback::Compiler::postGene
   }
 
   void* address = code->raw() + bailoutReturnOffset_.offset();
   BailoutReturnStub kind =
       isConstructing_ ? BailoutReturnStub::New : BailoutReturnStub::Call;
   cx->realm()->jitRealm()->initBailoutReturnAddr(address, getKey(), kind);
 }
 
-typedef bool (*CreateThisFn)(JSContext* cx, HandleObject callee,
-                             HandleObject newTarget, MutableHandleValue rval);
-static const VMFunction CreateThisInfoBaseline =
-    FunctionInfo<CreateThisFn>(CreateThis, "CreateThis");
-
 bool ICCallScriptedCompiler::generateStubCode(MacroAssembler& masm) {
   Label failure;
   AllocatableGeneralRegisterSet regs(availableGeneralRegs(0));
   bool canUseTailCallReg = regs.has(ICTailCallReg);
 
   Register argcReg = R0.scratchReg();
   regs.take(argcReg);
   regs.takeUnchecked(ICTailCallReg);
@@ -4529,17 +4498,20 @@ bool ICCallScriptedCompiler::generateStu
                      R1);
     } else {
       BaseValueIndex calleeSlot2(masm.getStackPointer(), argcReg,
                                  2 * sizeof(Value) + STUB_FRAME_SIZE +
                                      sizeof(size_t) + sizeof(JSObject*));
       masm.loadValue(calleeSlot2, R1);
     }
     masm.push(masm.extractObject(R1, ExtractTemp0));
-    if (!callVM(CreateThisInfoBaseline, masm)) {
+
+    using Fn = bool (*)(JSContext * cx, HandleObject callee,
+                        HandleObject newTarget, MutableHandleValue rval);
+    if (!callVM<Fn, CreateThis>(masm)) {
       return false;
     }
 
     // Return of CreateThis must be an object or uninitialized.
 #ifdef DEBUG
     Label createdThisOK;
     masm.branchTestObject(Assembler::Equal, JSReturnOperand, &createdThisOK);
     masm.branchTestMagic(Assembler::Equal, JSReturnOperand, &createdThisOK);
@@ -4718,22 +4690,16 @@ bool ICCallScriptedCompiler::generateStu
   // Enter type monitor IC to type-check result.
   EmitEnterTypeMonitorIC(masm);
 
   masm.bind(&failure);
   EmitStubGuardFailure(masm);
   return true;
 }
 
-typedef bool (*CopyStringSplitArrayFn)(JSContext*, HandleArrayObject,
-                                       MutableHandleValue);
-static const VMFunction CopyStringSplitArrayInfo =
-    FunctionInfo<CopyStringSplitArrayFn>(CopyStringSplitArray,
-                                         "CopyStringSplitArray");
-
 bool ICCall_ConstStringSplit::Compiler::generateStubCode(MacroAssembler& masm) {
   // Stack Layout:
   //      [ ..., CalleeVal, ThisVal, strVal, sepVal, +ICStackValueOffset+ ]
   static const size_t SEP_DEPTH = 0;
   static const size_t STR_DEPTH = sizeof(Value);
   static const size_t CALLEE_DEPTH = 3 * sizeof(Value);
 
   AllocatableGeneralRegisterSet regs(availableGeneralRegs(0));
@@ -4811,17 +4777,18 @@ bool ICCall_ConstStringSplit::Compiler::
   {
     Register paramReg = regs.takeAny();
 
     // Push arguments.
     enterStubFrame(masm, scratchReg);
     masm.loadPtr(Address(ICStubReg, offsetOfTemplateObject()), paramReg);
     masm.push(paramReg);
 
-    if (!callVM(CopyStringSplitArrayInfo, masm)) {
+    using Fn = bool (*)(JSContext*, HandleArrayObject, MutableHandleValue);
+    if (!callVM<Fn, CopyStringSplitArray>(masm)) {
       return false;
     }
     leaveStubFrame(masm);
     regs.add(paramReg);
   }
 
   // Enter type monitor IC to type-check result.
   EmitEnterTypeMonitorIC(masm);
--- a/js/src/jit/BaselineIC.h
+++ b/js/src/jit/BaselineIC.h
@@ -994,17 +994,20 @@ class ICStubCompiler {
   // Push a payload specialized per compiler needed to execute stubs.
   void PushStubPayload(MacroAssembler& masm, Register scratch);
   void pushStubPayload(MacroAssembler& masm, Register scratch);
 
   // Emits a tail call to a VMFunction wrapper.
   MOZ_MUST_USE bool tailCallVM(const VMFunction& fun, MacroAssembler& masm);
 
   // Emits a normal (non-tail) call to a VMFunction wrapper.
-  MOZ_MUST_USE bool callVM(const VMFunction& fun, MacroAssembler& masm);
+  MOZ_MUST_USE bool callVMInternal(MacroAssembler& masm, VMFunctionId id);
+
+  template <typename Fn, Fn fn>
+  MOZ_MUST_USE bool callVM(MacroAssembler& masm);
 
   // A stub frame is used when a stub wants to call into the VM without
   // performing a tail call. This is required for the return address
   // to pc mapping to work.
   void enterStubFrame(MacroAssembler& masm, Register scratch);
   void assumeStubFrame();
   void leaveStubFrame(MacroAssembler& masm, bool calledIntoIon = false);
 
@@ -2718,12 +2721,24 @@ template <typename T>
 void StoreToTypedArray(JSContext* cx, MacroAssembler& masm, Scalar::Type type,
                        const ValueOperand& value, const T& dest,
                        Register scratch, Label* failure);
 
 extern bool DoTypeUpdateFallback(JSContext* cx, BaselineFrame* frame,
                                  ICUpdatedStub* stub, HandleValue objval,
                                  HandleValue value);
 
+extern bool DoWarmUpCounterFallbackOSR(JSContext* cx, BaselineFrame* frame,
+                                       ICWarmUpCounter_Fallback* stub,
+                                       IonOsrTempData** infoPtr);
+
+extern bool DoCallFallback(JSContext* cx, BaselineFrame* frame,
+                           ICCall_Fallback* stub, uint32_t argc, Value* vp,
+                           MutableHandleValue res);
+
+extern bool DoSpreadCallFallback(JSContext* cx, BaselineFrame* frame,
+                                 ICCall_Fallback* stub, Value* vp,
+                                 MutableHandleValue res);
+
 }  // namespace jit
 }  // namespace js
 
 #endif /* jit_BaselineIC_h */
--- a/js/src/jit/VMFunctionList-inl.h
+++ b/js/src/jit/VMFunctionList-inl.h
@@ -1,14 +1,17 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * vim: set ts=8 sts=2 et sw=2 tw=80:
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+#ifndef jit_VMFunctionList_inl_h
+#define jit_VMFunctionList_inl_h
+
 #include "builtin/Eval.h"
 #include "builtin/RegExp.h"
 #include "jit/BaselineIC.h"
 #include "jit/IonIC.h"
 #include "jit/JitRealm.h"
 #include "jit/VMFunctions.h"
 #include "vm/AsyncFunction.h"
 #include "vm/AsyncIteration.h"
@@ -59,16 +62,17 @@ namespace jit {
   _(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)       \
+  _(CopyStringSplitArray, js::jit::CopyStringSplitArray)                       \
   _(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)     \
@@ -84,20 +88,23 @@ namespace jit {
   _(DefVarOperation, js::DefVarOperation)                                      \
   _(DeleteElementNonStrict, js::DeleteElementJit<false>)                       \
   _(DeleteElementStrict, js::DeleteElementJit<true>)                           \
   _(DeleteNameOperation, js::DeleteNameOperation)                              \
   _(DeletePropertyNonStrict, js::DeletePropertyJit<false>)                     \
   _(DeletePropertyStrict, js::DeletePropertyJit<true>)                         \
   _(DirectEvalStringFromIon, js::DirectEvalStringFromIon)                      \
   _(DivValues, js::DivValues)                                                  \
+  _(DoCallFallback, js::jit::DoCallFallback)                                   \
   _(DoConcatStringObject, js::jit::DoConcatStringObject)                       \
+  _(DoSpreadCallFallback, js::jit::DoSpreadCallFallback)                       \
   _(DoToNumber, js::jit::DoToNumber)                                           \
   _(DoToNumeric, js::jit::DoToNumeric)                                         \
   _(DoTypeUpdateFallback, js::jit::DoTypeUpdateFallback)                       \
+  _(DoWarmUpCounterFallbackOSR, js::jit::DoWarmUpCounterFallbackOSR)           \
   _(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)                        \
@@ -271,8 +278,10 @@ VMFUNCTION_LIST(DEF_TEMPLATE)
 #undef DEF_TEMPLATE
 
 #if MOZ_IS_GCC
 #  pragma GCC diagnostic pop
 #endif
 
 }  // namespace jit
 }  // namespace js
+
+#endif // jit_VMFunctionList_inl_h
--- a/js/src/jit/VMFunctions.cpp
+++ b/js/src/jit/VMFunctions.cpp
@@ -1918,10 +1918,29 @@ bool DoToNumber(JSContext* cx, HandleVal
   return ToNumber(cx, ret);
 }
 
 bool DoToNumeric(JSContext* cx, HandleValue arg, MutableHandleValue ret) {
   ret.set(arg);
   return ToNumeric(cx, ret);
 }
 
+bool CopyStringSplitArray(JSContext* cx, HandleArrayObject arr,
+                          MutableHandleValue result) {
+  MOZ_ASSERT(arr->isTenured(),
+             "ConstStringSplit needs a tenured template object");
+
+  uint32_t length = arr->getDenseInitializedLength();
+  MOZ_ASSERT(length == arr->length(),
+             "template object is a fully initialized array");
+
+  ArrayObject* nobj = NewFullyAllocatedArrayTryReuseGroup(cx, arr, length);
+  if (!nobj) {
+    return false;
+  }
+  nobj->initDenseElements(arr, 0, length);
+
+  result.setObject(*nobj);
+  return true;
+}
+
 }  // namespace jit
 }  // namespace js
--- a/js/src/jit/VMFunctions.h
+++ b/js/src/jit/VMFunctions.h
@@ -1217,16 +1217,19 @@ bool DoConcatStringObject(JSContext* cx,
 MOZ_MUST_USE bool TrySkipAwait(JSContext* cx, HandleValue val,
                                MutableHandleValue resolved);
 
 bool IsPossiblyWrappedTypedArray(JSContext* cx, JSObject* obj, bool* result);
 
 bool DoToNumber(JSContext* cx, HandleValue arg, MutableHandleValue ret);
 bool DoToNumeric(JSContext* cx, HandleValue arg, MutableHandleValue ret);
 
+bool CopyStringSplitArray(JSContext* cx, HandleArrayObject arr,
+                          MutableHandleValue result);
+
 // TailCall VMFunctions
 extern const VMFunction DoConcatStringObjectInfo;
 
 enum class VMFunctionId;
 
 extern const VMFunctionData& GetVMFunction(VMFunctionId id);
 
 }  // namespace jit