Bug 1447372 - Cleanup LifoAlloc usage for RegExp r=jorendorff
authorTed Campbell <tcampbell@mozilla.com>
Tue, 30 Oct 2018 19:24:14 +0000
changeset 500009 77e0c47e18d61653440632dbd6a699c1e6c07365
parent 500008 9ca2c179e63e292808918158eb778b16bf18e67f
child 500010 66ed28ca0a0616756dfe8f587d4bb1dfd84e845a
push id10290
push userffxbld-merge
push dateMon, 03 Dec 2018 16:23:23 +0000
treeherdermozilla-beta@700bed2445e6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjorendorff
bugs1447372
milestone65.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1447372 - Cleanup LifoAlloc usage for RegExp r=jorendorff Directly construct a LifoAllocScope on cx->tempLifoAlloc inside RegExpObject::create. The data allocated temporarily does not outlive this function. Also simplify callers as a result. Differential Revision: https://phabricator.services.mozilla.com/D9976
js/src/builtin/RegExp.cpp
js/src/builtin/TestingFunctions.cpp
js/src/frontend/BinSource-auto.cpp
js/src/frontend/BinSource.yaml
js/src/frontend/Parser.cpp
js/src/irregexp/RegExpEngine.cpp
js/src/irregexp/RegExpEngine.h
js/src/irregexp/RegExpParser.cpp
js/src/jsapi.cpp
js/src/vm/RegExpObject.cpp
js/src/vm/RegExpObject.h
js/src/vm/SelfHosting.cpp
js/src/vm/StructuredClone.cpp
--- a/js/src/builtin/RegExp.cpp
+++ b/js/src/builtin/RegExp.cpp
@@ -180,19 +180,20 @@ js::ExecuteRegExpLegacy(JSContext* cx, R
     }
 
     return CreateRegExpMatchResult(cx, input, matches, rval);
 }
 
 static bool
 CheckPatternSyntaxSlow(JSContext* cx, HandleAtom pattern, RegExpFlag flags)
 {
+    LifoAllocScope allocScope(&cx->tempLifoAlloc());
     CompileOptions options(cx);
     frontend::TokenStream dummyTokenStream(cx, options, nullptr, 0, nullptr);
-    return irregexp::ParsePatternSyntax(dummyTokenStream, cx->tempLifoAlloc(), pattern,
+    return irregexp::ParsePatternSyntax(dummyTokenStream, allocScope.alloc(), pattern,
                                         flags & UnicodeFlag);
 }
 
 static RegExpShared*
 CheckPatternSyntax(JSContext* cx, HandleAtom pattern, RegExpFlag flags)
 {
     // If we already have a RegExpShared for this pattern/flags, we can
     // avoid the much slower CheckPatternSyntaxSlow call.
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -4698,17 +4698,17 @@ AssertionTypeToString(irregexp::RegExpAs
         return "NOT_AFTER_LEAD_SURROGATE";
       case irregexp::RegExpAssertion::NOT_IN_SURROGATE_PAIR:
         return "NOT_IN_SURROGATE_PAIR";
     }
     MOZ_CRASH("unexpected AssertionType");
 }
 
 static JSObject*
-ConvertRegExpTreeToObject(JSContext* cx, irregexp::RegExpTree* tree)
+ConvertRegExpTreeToObject(JSContext* cx, LifoAlloc& alloc, irregexp::RegExpTree* tree)
 {
     RootedObject obj(cx, JS_NewPlainObject(cx));
     if (!obj) {
         return nullptr;
     }
 
     auto IntProp = [](JSContext* cx, HandleObject obj,
                       const char* name, int32_t value) {
@@ -4745,36 +4745,36 @@ ConvertRegExpTreeToObject(JSContext* cx,
         if (!valueStr) {
             return false;
         }
 
         RootedValue val(cx, StringValue(valueStr));
         return JS_SetProperty(cx, obj, name, val);
     };
 
-    auto TreeProp = [&ObjectProp](JSContext* cx, HandleObject obj,
-                                  const char* name, irregexp::RegExpTree* tree) {
-        RootedObject treeObj(cx, ConvertRegExpTreeToObject(cx, tree));
+    auto TreeProp = [&ObjectProp, &alloc](JSContext* cx, HandleObject obj,
+                                          const char* name, irregexp::RegExpTree* tree) {
+        RootedObject treeObj(cx, ConvertRegExpTreeToObject(cx, alloc, tree));
         if (!treeObj) {
             return false;
         }
         return ObjectProp(cx, obj, name, treeObj);
     };
 
-    auto TreeVectorProp = [&ObjectProp](JSContext* cx, HandleObject obj,
-                                        const char* name,
-                                        const irregexp::RegExpTreeVector& nodes) {
+    auto TreeVectorProp = [&ObjectProp, &alloc](JSContext* cx, HandleObject obj,
+                                                const char* name,
+                                                const irregexp::RegExpTreeVector& nodes) {
         size_t len = nodes.length();
         RootedObject array(cx, JS_NewArrayObject(cx, len));
         if (!array) {
             return false;
         }
 
         for (size_t i = 0; i < len; i++) {
-            RootedObject child(cx, ConvertRegExpTreeToObject(cx, nodes[i]));
+            RootedObject child(cx, ConvertRegExpTreeToObject(cx, alloc, nodes[i]));
             if (!child) {
                 return false;
             }
 
             RootedValue childVal(cx, ObjectValue(*child));
             if (!JS_SetElement(cx, array, i, childVal)) {
                 return false;
             }
@@ -4818,27 +4818,27 @@ ConvertRegExpTreeToObject(JSContext* cx,
             RootedValue rangeVal(cx, ObjectValue(*rangeObj));
             if (!JS_SetElement(cx, array, i, rangeVal)) {
                 return false;
             }
         }
         return ObjectProp(cx, obj, name, array);
     };
 
-    auto ElemProp = [&ObjectProp](JSContext* cx, HandleObject obj,
-                                  const char* name, const irregexp::TextElementVector& elements) {
+    auto ElemProp = [&ObjectProp, &alloc](JSContext* cx, HandleObject obj, const char* name,
+                                          const irregexp::TextElementVector& elements) {
         size_t len = elements.length();
         RootedObject array(cx, JS_NewArrayObject(cx, len));
         if (!array) {
             return false;
         }
 
         for (size_t i = 0; i < len; i++) {
             const irregexp::TextElement& element = elements[i];
-            RootedObject elemTree(cx, ConvertRegExpTreeToObject(cx, element.tree()));
+            RootedObject elemTree(cx, ConvertRegExpTreeToObject(cx, alloc, element.tree()));
             if (!elemTree) {
                 return false;
             }
 
             RootedValue elemTreeVal(cx, ObjectValue(*elemTree));
             if (!JS_SetElement(cx, array, i, elemTreeVal)) {
                 return false;
             }
@@ -4879,18 +4879,17 @@ ConvertRegExpTreeToObject(JSContext* cx,
     if (tree->IsCharacterClass()) {
         if (!StringProp(cx, obj, "type", "CharacterClass")) {
             return nullptr;
         }
         irregexp::RegExpCharacterClass* t = tree->AsCharacterClass();
         if (!BooleanProp(cx, obj, "is_negated", t->is_negated())) {
             return nullptr;
         }
-        LifoAlloc* alloc = &cx->tempLifoAlloc();
-        if (!CharRangesProp(cx, obj, "ranges", t->ranges(alloc))) {
+        if (!CharRangesProp(cx, obj, "ranges", t->ranges(&alloc))) {
             return nullptr;
         }
         return obj;
     }
     if (tree->IsAtom()) {
         if (!StringProp(cx, obj, "type", "Atom")) {
             return nullptr;
         }
@@ -5017,27 +5016,29 @@ ParseRegExp(JSContext* cx, unsigned argc
     RootedAtom pattern(cx, AtomizeString(cx, args[0].toString()));
     if (!pattern) {
         return false;
     }
 
     CompileOptions options(cx);
     frontend::TokenStream dummyTokenStream(cx, options, nullptr, 0, nullptr);
 
+    // Data lifetime is controlled by LifoAllocScope.
+    LifoAllocScope allocScope(&cx->tempLifoAlloc());
     irregexp::RegExpCompileData data;
-    if (!irregexp::ParsePattern(dummyTokenStream, cx->tempLifoAlloc(), pattern,
+    if (!irregexp::ParsePattern(dummyTokenStream, allocScope.alloc(), pattern,
                                 flags & MultilineFlag, match_only,
                                 flags & UnicodeFlag, flags & IgnoreCaseFlag,
                                 flags & GlobalFlag, flags & StickyFlag,
                                 &data))
     {
         return false;
     }
 
-    RootedObject obj(cx, ConvertRegExpTreeToObject(cx, data.tree));
+    RootedObject obj(cx, ConvertRegExpTreeToObject(cx, allocScope.alloc(), data.tree));
     if (!obj) {
         return false;
     }
 
     args.rval().setObject(*obj);
     return true;
 }
 
--- a/js/src/frontend/BinSource-auto.cpp
+++ b/js/src/frontend/BinSource-auto.cpp
@@ -4352,17 +4352,16 @@ BinASTParser<Tok>::parseInterfaceLiteral
         }
     }
 
 
     Rooted<RegExpObject*> reobj(cx_);
     BINJS_TRY_VAR(reobj, RegExpObject::create(cx_,
         pattern,
         reflags,
-        alloc_,
         TenuredObject));
 
     BINJS_TRY_DECL(result, factory_.newRegExp(reobj, tokenizer_->pos(start), *this));
     return result;
 }
 
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceLiteralStringExpression(const size_t start, const BinKind kind, const BinFields& fields)
--- a/js/src/frontend/BinSource.yaml
+++ b/js/src/frontend/BinSource.yaml
@@ -1076,17 +1076,16 @@ LiteralRegExpExpression:
             }
         }
 
 
         Rooted<RegExpObject*> reobj(cx_);
         BINJS_TRY_VAR(reobj, RegExpObject::create(cx_,
             pattern,
             reflags,
-            alloc_,
             TenuredObject));
 
         BINJS_TRY_DECL(result, factory_.newRegExp(reobj, tokenizer_->pos(start), *this));
 
 LiteralStringExpression:
     build:
         BINJS_TRY_DECL(result, factory_.newStringLiteral(value, tokenizer_->pos(start)));
 
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -10027,18 +10027,17 @@ Parser<FullParseHandler, Unit>::newRegEx
 {
     MOZ_ASSERT(!options().selfHostingMode);
 
     // Create the regexp and check its syntax.
     const auto& chars = tokenStream.getCharBuffer();
     RegExpFlag flags = anyChars.currentToken().regExpFlags();
 
     Rooted<RegExpObject*> reobj(context);
-    reobj = RegExpObject::create(context, chars.begin(), chars.length(), flags, anyChars, alloc,
-                                 TenuredObject);
+    reobj = RegExpObject::create(context, chars.begin(), chars.length(), flags, anyChars, TenuredObject);
     if (!reobj) {
         return null();
     }
 
     return handler.newRegExp(reobj, pos(), *this);
 }
 
 template <typename Unit>
@@ -10047,18 +10046,23 @@ Parser<SyntaxParseHandler, Unit>::newReg
 {
     MOZ_ASSERT(!options().selfHostingMode);
 
     // Only check the regexp's syntax, but don't create a regexp object.
     const auto& chars = tokenStream.getCharBuffer();
     RegExpFlag flags = anyChars.currentToken().regExpFlags();
 
     mozilla::Range<const char16_t> source(chars.begin(), chars.length());
-    if (!js::irregexp::ParsePatternSyntax(anyChars, alloc, source, flags & UnicodeFlag)) {
-        return null();
+    {
+        LifoAllocScope scopeAlloc(&alloc);
+        if (!js::irregexp::ParsePatternSyntax(anyChars, scopeAlloc.alloc(),
+                                              source, flags & UnicodeFlag))
+        {
+            return null();
+        }
     }
 
     return handler.newRegExp(SyntaxParseHandler::NodeGeneric, pos(), *this);
 }
 
 template <class ParseHandler, typename Unit>
 typename ParseHandler::RegExpLiteralType
 GeneralParser<ParseHandler, Unit>::newRegExp()
--- a/js/src/irregexp/RegExpEngine.cpp
+++ b/js/src/irregexp/RegExpEngine.cpp
@@ -1730,27 +1730,26 @@ IsNativeRegExpEnabled(JSContext* cx)
 #ifdef JS_CODEGEN_NONE
     return false;
 #else
     return cx->options().nativeRegExp();
 #endif
 }
 
 RegExpCode
-irregexp::CompilePattern(JSContext* cx, HandleRegExpShared shared, RegExpCompileData* data,
-                         HandleLinearString sample, bool is_global, bool ignore_case,
-                         bool is_latin1, bool match_only, bool force_bytecode, bool sticky,
-                         bool unicode, RegExpShared::JitCodeTables& tables)
+irregexp::CompilePattern(JSContext* cx, LifoAlloc& alloc, HandleRegExpShared shared,
+                         RegExpCompileData* data, HandleLinearString sample, bool is_global,
+                         bool ignore_case, bool is_latin1, bool match_only, bool force_bytecode,
+                         bool sticky, bool unicode, RegExpShared::JitCodeTables& tables)
 {
     if ((data->capture_count + 1) * 2 - 1 > RegExpMacroAssembler::kMaxRegister) {
         JS_ReportErrorASCII(cx, "regexp too big");
         return RegExpCode();
     }
 
-    LifoAlloc& alloc = cx->tempLifoAlloc();
     RegExpCompiler compiler(cx, &alloc, data->capture_count, ignore_case, is_latin1, match_only,
                             unicode);
 
     // Sample some characters from the middle of the string.
     if (sample->hasLatin1Chars()) {
         JS::AutoCheckCannotGC nogc;
         SampleChars(compiler.frequency_collator(), sample->latin1Chars(nogc), sample->length());
     } else {
--- a/js/src/irregexp/RegExpEngine.h
+++ b/js/src/irregexp/RegExpEngine.h
@@ -80,17 +80,17 @@ struct RegExpCode
     }
 
     void destroy() {
         js_free(byteCode);
     }
 };
 
 RegExpCode
-CompilePattern(JSContext* cx, HandleRegExpShared shared, RegExpCompileData* data,
+CompilePattern(JSContext* cx, LifoAlloc& alloc, HandleRegExpShared shared, RegExpCompileData* data,
                HandleLinearString sample,  bool is_global, bool ignore_case,
                bool is_latin1, bool match_only, bool force_bytecode, bool sticky,
                bool unicode, RegExpShared::JitCodeTables& tables);
 
 // Note: this may return RegExpRunStatus_Error if an interrupt was requested
 // while the code was executing.
 template <typename CharT>
 RegExpRunStatus
--- a/js/src/irregexp/RegExpParser.cpp
+++ b/js/src/irregexp/RegExpParser.cpp
@@ -1953,18 +1953,16 @@ irregexp::ParsePattern(frontend::TokenSt
                             multiline, match_only, unicode, ignore_case, global, sticky, data);
 }
 
 template <typename CharT>
 static bool
 ParsePatternSyntax(frontend::TokenStreamAnyChars& ts, LifoAlloc& alloc,
                    const CharT* chars, size_t length, bool unicode)
 {
-    LifoAllocScope scope(&alloc);
-
     RegExpParser<CharT> parser(ts, &alloc, chars, chars + length, false, unicode, false);
     return parser.ParsePattern() != nullptr;
 }
 
 bool
 irregexp::ParsePatternSyntax(frontend::TokenStreamAnyChars& ts, LifoAlloc& alloc, JSAtom* str,
                              bool unicode)
 {
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -6000,28 +6000,26 @@ JS_NewRegExpObject(JSContext* cx, const 
     AssertHeapIsIdle();
     CHECK_THREAD(cx);
 
     UniqueTwoByteChars chars(InflateString(cx, bytes, length));
     if (!chars) {
         return nullptr;
     }
 
-    return RegExpObject::create(cx, chars.get(), length, RegExpFlag(flags), cx->tempLifoAlloc(),
-                                GenericObject);
+    return RegExpObject::create(cx, chars.get(), length, RegExpFlag(flags), GenericObject);
 }
 
 JS_PUBLIC_API(JSObject*)
 JS_NewUCRegExpObject(JSContext* cx, const char16_t* chars, size_t length, unsigned flags)
 {
     AssertHeapIsIdle();
     CHECK_THREAD(cx);
 
-    return RegExpObject::create(cx, chars, length, RegExpFlag(flags), cx->tempLifoAlloc(),
-                                GenericObject);
+    return RegExpObject::create(cx, chars, length, RegExpFlag(flags), GenericObject);
 }
 
 JS_PUBLIC_API(bool)
 JS_SetRegExpInput(JSContext* cx, HandleObject obj, HandleString input)
 {
     AssertHeapIsIdle();
     CHECK_THREAD(cx);
     cx->check(input);
--- a/js/src/vm/RegExpObject.cpp
+++ b/js/src/vm/RegExpObject.cpp
@@ -204,82 +204,84 @@ const Class RegExpObject::protoClass_ = 
     JSCLASS_HAS_CACHED_PROTO(JSProto_RegExp),
     JS_NULL_CLASS_OPS,
     &RegExpObjectClassSpec
 };
 
 template<typename CharT>
 RegExpObject*
 RegExpObject::create(JSContext* cx, const CharT* chars, size_t length, RegExpFlag flags,
-                     frontend::TokenStreamAnyChars& tokenStream, LifoAlloc& alloc,
-                     NewObjectKind newKind)
+                     frontend::TokenStreamAnyChars& tokenStream, NewObjectKind newKind)
 {
     static_assert(mozilla::IsSame<CharT, char16_t>::value,
                   "this code may need updating if/when CharT encodes UTF-8");
 
     RootedAtom source(cx, AtomizeChars(cx, chars, length));
     if (!source) {
         return nullptr;
     }
 
-    return create(cx, source, flags, tokenStream, alloc, newKind);
+    return create(cx, source, flags, tokenStream, newKind);
 }
 
 template RegExpObject*
 RegExpObject::create(JSContext* cx, const char16_t* chars, size_t length, RegExpFlag flags,
-                     frontend::TokenStreamAnyChars& tokenStream, LifoAlloc& alloc,
-                     NewObjectKind newKind);
+                     frontend::TokenStreamAnyChars& tokenStream, NewObjectKind newKind);
 
 template<typename CharT>
 RegExpObject*
-RegExpObject::create(JSContext* cx, const CharT* chars, size_t length, RegExpFlag flags,
-                     LifoAlloc& alloc, NewObjectKind newKind)
+RegExpObject::create(JSContext* cx, const CharT* chars, size_t length,
+                     RegExpFlag flags, NewObjectKind newKind)
 {
     static_assert(mozilla::IsSame<CharT, char16_t>::value,
                   "this code may need updating if/when CharT encodes UTF-8");
 
     RootedAtom source(cx, AtomizeChars(cx, chars, length));
     if (!source) {
         return nullptr;
     }
 
-    return create(cx, source, flags, alloc, newKind);
+    return create(cx, source, flags, newKind);
 }
 
 template RegExpObject*
-RegExpObject::create(JSContext* cx, const char16_t* chars, size_t length, RegExpFlag flags,
-                     LifoAlloc& alloc, NewObjectKind newKind);
+RegExpObject::create(JSContext* cx, const char16_t* chars, size_t length,
+                     RegExpFlag flags, NewObjectKind newKind);
 
 RegExpObject*
 RegExpObject::create(JSContext* cx, HandleAtom source, RegExpFlag flags,
-                     frontend::TokenStreamAnyChars& tokenStream,
-                     LifoAlloc& alloc, NewObjectKind newKind)
+                     frontend::TokenStreamAnyChars& tokenStream, NewObjectKind newKind)
 {
-    if (!irregexp::ParsePatternSyntax(tokenStream, alloc, source, flags & UnicodeFlag)) {
+    LifoAllocScope allocScope(&cx->tempLifoAlloc());
+    if (!irregexp::ParsePatternSyntax(tokenStream, allocScope.alloc(),
+                                      source, flags & UnicodeFlag))
+    {
         return nullptr;
     }
 
     Rooted<RegExpObject*> regexp(cx, RegExpAlloc(cx, newKind));
     if (!regexp) {
         return nullptr;
     }
 
     regexp->initAndZeroLastIndex(source, flags, cx);
 
     return regexp;
 }
 
 RegExpObject*
-RegExpObject::create(JSContext* cx, HandleAtom source, RegExpFlag flags, LifoAlloc& alloc,
-                     NewObjectKind newKind)
+RegExpObject::create(JSContext* cx, HandleAtom source, RegExpFlag flags, NewObjectKind newKind)
 {
     CompileOptions dummyOptions(cx);
     TokenStream dummyTokenStream(cx, dummyOptions, (const char16_t*) nullptr, 0, nullptr);
 
-    if (!irregexp::ParsePatternSyntax(dummyTokenStream, alloc, source, flags & UnicodeFlag)) {
+    LifoAllocScope allocScope(&cx->tempLifoAlloc());
+    if (!irregexp::ParsePatternSyntax(dummyTokenStream, allocScope.alloc(),
+                                      source, flags & UnicodeFlag))
+    {
         return nullptr;
     }
 
     Rooted<RegExpObject*> regexp(cx, RegExpAlloc(cx, newKind));
     if (!regexp) {
         return nullptr;
     }
 
@@ -1045,31 +1047,32 @@ RegExpShared::compile(JSContext* cx, Mut
 {
     if (!re->ignoreCase() && !StringHasRegExpMetaChars(pattern)) {
         re->canStringMatch = true;
     }
 
     CompileOptions options(cx);
     frontend::TokenStream dummyTokenStream(cx, options, nullptr, 0, nullptr);
 
-    LifoAllocScope scope(&cx->tempLifoAlloc());
-
-    /* Parse the pattern. */
+    /* Parse the pattern. The RegExpCompileData is allocated in LifoAlloc and
+     * will only be live while LifoAllocScope is on stack. */
+    LifoAllocScope allocScope(&cx->tempLifoAlloc());
     irregexp::RegExpCompileData data;
-    if (!irregexp::ParsePattern(dummyTokenStream, cx->tempLifoAlloc(), pattern,
+    if (!irregexp::ParsePattern(dummyTokenStream, allocScope.alloc(), pattern,
                                 re->multiline(), mode == MatchOnly, re->unicode(),
                                 re->ignoreCase(), re->global(), re->sticky(), &data))
     {
         return false;
     }
 
     re->parenCount = data.capture_count;
 
     JitCodeTables tables;
-    irregexp::RegExpCode code = irregexp::CompilePattern(cx, re, &data, input,
+    irregexp::RegExpCode code = irregexp::CompilePattern(cx, allocScope.alloc(),
+                                                         re, &data, input,
                                                          false /* global() */,
                                                          re->ignoreCase(),
                                                          input->hasLatin1Chars(),
                                                          mode == MatchOnly,
                                                          force == ForceByteCode,
                                                          re->sticky(),
                                                          re->unicode(),
                                                          tables);
@@ -1510,17 +1513,17 @@ js::XDRScriptRegExpObject(XDRState<mode>
         RegExpObject& reobj = *objp;
         source = reobj.getSource();
         flagsword = reobj.getFlags();
     }
     MOZ_TRY(XDRAtom(xdr, &source));
     MOZ_TRY(xdr->codeUint32(&flagsword));
     if (mode == XDR_DECODE) {
         RegExpObject* reobj = RegExpObject::create(xdr->cx(), source, RegExpFlag(flagsword),
-                                                   xdr->lifoAlloc(), TenuredObject);
+                                                   TenuredObject);
         if (!reobj) {
             return xdr->fail(JS::TranscodeResult_Throw);
         }
 
         objp.set(reobj);
     }
     return Ok();
 }
@@ -1534,17 +1537,17 @@ js::XDRScriptRegExpObject(XDRState<XDR_D
 JSObject*
 js::CloneScriptRegExpObject(JSContext* cx, RegExpObject& reobj)
 {
     /* NB: Keep this in sync with XDRScriptRegExpObject. */
 
     RootedAtom source(cx, reobj.getSource());
     cx->markAtom(source);
 
-    return RegExpObject::create(cx, source, reobj.getFlags(), cx->tempLifoAlloc(), TenuredObject);
+    return RegExpObject::create(cx, source, reobj.getFlags(), TenuredObject);
 }
 
 JS_FRIEND_API(RegExpShared*)
 js::RegExpToSharedNonInline(JSContext* cx, HandleObject obj)
 {
     return RegExpToShared(cx, obj);
 }
 
--- a/js/src/vm/RegExpObject.h
+++ b/js/src/vm/RegExpObject.h
@@ -65,31 +65,30 @@ class RegExpObject : public NativeObject
     static const Class protoClass_;
 
     // The maximum number of pairs a MatchResult can have, without having to
     // allocate a bigger MatchResult.
     static const size_t MaxPairCount = 14;
 
     template<typename CharT>
     static RegExpObject*
-    create(JSContext* cx, const CharT* chars, size_t length, RegExpFlag flags, LifoAlloc& alloc,
-           NewObjectKind newKind);
+    create(JSContext* cx, const CharT* chars, size_t length,
+           RegExpFlag flags, NewObjectKind newKind);
 
     template<typename CharT>
     static RegExpObject*
     create(JSContext* cx, const CharT* chars, size_t length, RegExpFlag flags,
-           frontend::TokenStreamAnyChars& ts, LifoAlloc& alloc, NewObjectKind kind);
+           frontend::TokenStreamAnyChars& ts, NewObjectKind kind);
 
     static RegExpObject*
-    create(JSContext* cx, HandleAtom atom, RegExpFlag flags, LifoAlloc& alloc,
-           NewObjectKind newKind);
+    create(JSContext* cx, HandleAtom source, RegExpFlag flags, NewObjectKind newKind);
 
     static RegExpObject*
-    create(JSContext* cx, HandleAtom atom, RegExpFlag flags, frontend::TokenStreamAnyChars& ts,
-           LifoAlloc& alloc, NewObjectKind newKind);
+    create(JSContext* cx, HandleAtom source, RegExpFlag flags,
+           frontend::TokenStreamAnyChars& ts, NewObjectKind newKind);
 
     /*
      * Compute the initial shape to associate with fresh RegExp objects,
      * encoding their initial properties. Return the shape after
      * changing |obj|'s last property to it.
      */
     static Shape*
     assignInitialShape(JSContext* cx, Handle<RegExpObject*> obj);
--- a/js/src/vm/SelfHosting.cpp
+++ b/js/src/vm/SelfHosting.cpp
@@ -3179,18 +3179,17 @@ CloneObject(JSContext* cx, HandleNativeO
             }
         } else {
             clone = CloneSelfHostingIntrinsic(cx, selfHostedFunction);
         }
     } else if (selfHostedObject->is<RegExpObject>()) {
         RegExpObject& reobj = selfHostedObject->as<RegExpObject>();
         RootedAtom source(cx, reobj.getSource());
         MOZ_ASSERT(source->isPermanentAtom());
-        clone = RegExpObject::create(cx, source, reobj.getFlags(), cx->tempLifoAlloc(),
-                                     TenuredObject);
+        clone = RegExpObject::create(cx, source, reobj.getFlags(), TenuredObject);
     } else if (selfHostedObject->is<DateObject>()) {
         clone = JS::NewDateObject(cx, selfHostedObject->as<DateObject>().clippedTime());
     } else if (selfHostedObject->is<BooleanObject>()) {
         clone = BooleanObject::create(cx, selfHostedObject->as<BooleanObject>().unbox());
     } else if (selfHostedObject->is<NumberObject>()) {
         clone = NumberObject::create(cx, selfHostedObject->as<NumberObject>().unbox());
     } else if (selfHostedObject->is<StringObject>()) {
         JSString* selfHostedString = selfHostedObject->as<StringObject>().unbox();
--- a/js/src/vm/StructuredClone.cpp
+++ b/js/src/vm/StructuredClone.cpp
@@ -2590,18 +2590,17 @@ JSStructuredCloneReader::startRead(Mutab
             return false;
         }
 
         RootedAtom atom(context(), AtomizeString(context(), str));
         if (!atom) {
             return false;
         }
 
-        RegExpObject* reobj = RegExpObject::create(context(), atom, flags,
-                                                   context()->tempLifoAlloc(), GenericObject);
+        RegExpObject* reobj = RegExpObject::create(context(), atom, flags, GenericObject);
         if (!reobj) {
             return false;
         }
         vp.setObject(*reobj);
         break;
       }
 
       case SCTAG_ARRAY_OBJECT: