Issue #2083 - Part 2: Remove use of RegExpGuard.

Based on Mozilla bug 1345177.
There were more uses of RegExpGuard in js/src/builtin/RegExp.cpp not found in
 the original bug's patch.
This commit is contained in:
Job Bautista 2023-01-26 15:13:53 +08:00 • committed by roytam1
commit d163d08cb2
21 changed files with 92 additions and 73 deletions

View file

@ -128,7 +128,8 @@ class CPOWProxyHandler : public BaseProxyHandler
virtual bool isArray(JSContext* cx, HandleObject obj, virtual bool isArray(JSContext* cx, HandleObject obj,
IsArrayAnswer* answer) const override; IsArrayAnswer* answer) const override;
virtual const char* className(JSContext* cx, HandleObject proxy) const override; virtual const char* className(JSContext* cx, HandleObject proxy) const override;
virtual bool regexp_toShared(JSContext* cx, HandleObject proxy, RegExpGuard* g) const override; virtual bool regexp_toShared(JSContext* cx, HandleObject proxy,
MutableHandle<RegExpShared*> shared) const override;
virtual void finalize(JSFreeOp* fop, JSObject* proxy) const override; virtual void finalize(JSFreeOp* fop, JSObject* proxy) const override;
virtual void objectMoved(JSObject* proxy, const JSObject* old) const override; virtual void objectMoved(JSObject* proxy, const JSObject* old) const override;
virtual bool isCallable(JSObject* obj) const override; virtual bool isCallable(JSObject* obj) const override;
@ -854,13 +855,14 @@ WrapperOwner::getPrototypeIfOrdinary(JSContext* cx, HandleObject proxy, bool* is
} }
bool bool
CPOWProxyHandler::regexp_toShared(JSContext* cx, HandleObject proxy, RegExpGuard* g) const CPOWProxyHandler::regexp_toShared(JSContext* cx, HandleObject proxy,
MutableHandle<RegExpShared*> shared) const
{ {
FORWARD(regexp_toShared, (cx, proxy, g)); FORWARD(regexp_toShared, (cx, proxy, shared));
} }
bool bool
WrapperOwner::regexp_toShared(JSContext* cx, HandleObject proxy, RegExpGuard* g) WrapperOwner::regexp_toShared(JSContext* cx, HandleObject proxy, MutableHandle<RegExpShared*> shared)
{ {
ObjectId objId = idOf(proxy); ObjectId objId = idOf(proxy);
@ -880,7 +882,7 @@ WrapperOwner::regexp_toShared(JSContext* cx, HandleObject proxy, RegExpGuard* g)
if (!regexp) if (!regexp)
return false; return false;
return js::RegExpToSharedNonInline(cx, regexp, g); return js::RegExpToSharedNonInline(cx, regexp, shared);
} }
void void

View file

@ -59,7 +59,8 @@ class WrapperOwner : public virtual JavaScriptShared
bool getPrototypeIfOrdinary(JSContext* cx, JS::HandleObject proxy, bool* isOrdinary, bool getPrototypeIfOrdinary(JSContext* cx, JS::HandleObject proxy, bool* isOrdinary,
JS::MutableHandleObject protop); JS::MutableHandleObject protop);
bool regexp_toShared(JSContext* cx, JS::HandleObject proxy, js::RegExpGuard* g); bool regexp_toShared(JSContext* cx, JS::HandleObject proxy,
js::MutableHandle<js::RegExpShared*> shared);
nsresult instanceOf(JSObject* obj, const nsID* id, bool* bp); nsresult instanceOf(JSObject* obj, const nsID* id, bool* bp);

View file

@ -31,7 +31,7 @@ using JS::PrivateValue;
using JS::PropertyDescriptor; using JS::PropertyDescriptor;
using JS::Value; using JS::Value;
using RegExpGuard = JS::Rooted<RegExpShared*>; class RegExpShared;
class JS_FRIEND_API(Wrapper); class JS_FRIEND_API(Wrapper);
@ -328,7 +328,8 @@ class JS_FRIEND_API(BaseProxyHandler)
virtual bool isArray(JSContext* cx, HandleObject proxy, JS::IsArrayAnswer* answer) const; virtual bool isArray(JSContext* cx, HandleObject proxy, JS::IsArrayAnswer* answer) const;
virtual const char* className(JSContext* cx, HandleObject proxy) const; virtual const char* className(JSContext* cx, HandleObject proxy) const;
virtual JSString* fun_toString(JSContext* cx, HandleObject proxy, bool isToSource) const; virtual JSString* fun_toString(JSContext* cx, HandleObject proxy, bool isToSource) const;
virtual bool regexp_toShared(JSContext* cx, HandleObject proxy, RegExpGuard* g) const; virtual bool regexp_toShared(JSContext* cx, HandleObject proxy,
MutableHandle<js::RegExpShared*> shared) const;
virtual bool boxedValue_unbox(JSContext* cx, HandleObject proxy, MutableHandleValue vp) const; virtual bool boxedValue_unbox(JSContext* cx, HandleObject proxy, MutableHandleValue vp) const;
virtual void trace(JSTracer* trc, JSObject* proxy) const; virtual void trace(JSTracer* trc, JSObject* proxy) const;
virtual void finalize(JSFreeOp* fop, JSObject* proxy) const; virtual void finalize(JSFreeOp* fop, JSObject* proxy) const;

View file

@ -187,7 +187,7 @@ js::ExecuteRegExpLegacy(JSContext* cx, RegExpStatics* res, Handle<RegExpObject*>
HandleLinearString input, size_t* lastIndex, bool test, HandleLinearString input, size_t* lastIndex, bool test,
MutableHandleValue rval) MutableHandleValue rval)
{ {
RegExpGuard shared(cx); RootedRegExpShared shared(cx);
if (!RegExpObject::getShared(cx, reobj, &shared)) if (!RegExpObject::getShared(cx, reobj, &shared))
return false; return false;
@ -275,7 +275,7 @@ RegExpInitializeIgnoringLastIndex(JSContext* cx, Handle<RegExpObject*> obj,
if (sharedUse == UseRegExpShared) { if (sharedUse == UseRegExpShared) {
/* Steps 7-8. */ /* Steps 7-8. */
RegExpGuard re(cx); RootedRegExpShared re(cx);
if (!cx->compartment()->regExps.get(cx, pattern, flags, &re)) if (!cx->compartment()->regExps.get(cx, pattern, flags, &re))
return false; return false;
@ -381,7 +381,7 @@ regexp_compile_impl(JSContext* cx, const CallArgs& args)
RegExpFlag flags; RegExpFlag flags;
{ {
// Step 3b. // Step 3b.
RegExpGuard g(cx); RootedRegExpShared g(cx);
if (!RegExpToShared(cx, patternObj, &g)) if (!RegExpToShared(cx, patternObj, &g))
return false; return false;
@ -476,7 +476,7 @@ js::regexp_construct(JSContext* cx, unsigned argc, Value* vp)
RegExpFlag flags; RegExpFlag flags;
{ {
// Step 4.a. // Step 4.a.
RegExpGuard g(cx); RootedRegExpShared g(cx);
if (!RegExpToShared(cx, patternObj, &g)) if (!RegExpToShared(cx, patternObj, &g))
return false; return false;
sourceAtom = g->getSource(); sourceAtom = g->getSource();
@ -603,7 +603,7 @@ js::regexp_clone(JSContext* cx, unsigned argc, Value* vp)
RootedAtom sourceAtom(cx); RootedAtom sourceAtom(cx);
RegExpFlag flags; RegExpFlag flags;
{ {
RegExpGuard g(cx); RootedRegExpShared g(cx);
if (!RegExpToShared(cx, from, &g)) if (!RegExpToShared(cx, from, &g))
return false; return false;
sourceAtom = g->getSource(); sourceAtom = g->getSource();
@ -985,7 +985,7 @@ ExecuteRegExp(JSContext* cx, HandleObject regexp, HandleString string,
/* Steps 1-2 performed by the caller. */ /* Steps 1-2 performed by the caller. */
Rooted<RegExpObject*> reobj(cx, &regexp->as<RegExpObject>()); Rooted<RegExpObject*> reobj(cx, &regexp->as<RegExpObject>());
RegExpGuard re(cx); RootedRegExpShared re(cx);
if (!RegExpObject::getShared(cx, reobj, &re)) if (!RegExpObject::getShared(cx, reobj, &re))
return RegExpRunStatus_Error; return RegExpRunStatus_Error;
@ -1070,7 +1070,7 @@ RegExpMatcherImpl(JSContext* cx, HandleObject regexp, HandleString string,
/* Steps 16-25 */ /* Steps 16-25 */
Rooted<RegExpObject*> reobj(cx, &regexp->as<RegExpObject>()); Rooted<RegExpObject*> reobj(cx, &regexp->as<RegExpObject>());
RegExpGuard shared(cx); RootedRegExpShared shared(cx);
if (!RegExpObject::getShared(cx, reobj, &shared)) if (!RegExpObject::getShared(cx, reobj, &shared))
return false; return false;
return CreateRegExpMatchResult(cx, *shared, string, matches, rval); return CreateRegExpMatchResult(cx, *shared, string, matches, rval);
@ -1117,7 +1117,7 @@ js::RegExpMatcherRaw(JSContext* cx, HandleObject regexp, HandleString input,
// successful only if the pairs have actually been filled in. // successful only if the pairs have actually been filled in.
if (maybeMatches && maybeMatches->pairsRaw()[0] >= 0) { if (maybeMatches && maybeMatches->pairsRaw()[0] >= 0) {
Rooted<RegExpObject*> reobj(cx, &regexp->as<RegExpObject>()); Rooted<RegExpObject*> reobj(cx, &regexp->as<RegExpObject>());
RegExpGuard shared(cx); RootedRegExpShared shared(cx);
if (!RegExpObject::getShared(cx, reobj, &shared)) if (!RegExpObject::getShared(cx, reobj, &shared))
return false; return false;
return CreateRegExpMatchResult(cx, *shared, input, *maybeMatches, output); return CreateRegExpMatchResult(cx, *shared, input, *maybeMatches, output);

View file

@ -6141,7 +6141,7 @@ JS_GetRegExpFlags(JSContext* cx, HandleObject obj)
AssertHeapIsIdle(cx); AssertHeapIsIdle(cx);
CHECK_REQUEST(cx); CHECK_REQUEST(cx);
RegExpGuard shared(cx); RootedRegExpShared shared(cx);
if (!RegExpToShared(cx, obj, &shared)) if (!RegExpToShared(cx, obj, &shared))
return false; return false;
return shared->getFlags(); return shared->getFlags();
@ -6153,7 +6153,7 @@ JS_GetRegExpSource(JSContext* cx, HandleObject obj)
AssertHeapIsIdle(cx); AssertHeapIsIdle(cx);
CHECK_REQUEST(cx); CHECK_REQUEST(cx);
RegExpGuard shared(cx); RootedRegExpShared shared(cx);
if (!RegExpToShared(cx, obj, &shared)) if (!RegExpToShared(cx, obj, &shared))
return nullptr; return nullptr;
return shared->getSource(); return shared->getSource();

View file

@ -1114,9 +1114,9 @@ extern JS_FRIEND_API(unsigned)
GetEnterCompartmentDepth(JSContext* cx); GetEnterCompartmentDepth(JSContext* cx);
#endif #endif
using RegExpGuard = JS::Rooted<RegExpShared*>;
extern JS_FRIEND_API(bool) extern JS_FRIEND_API(bool)
RegExpToSharedNonInline(JSContext* cx, JS::HandleObject regexp, RegExpGuard* shared); RegExpToSharedNonInline(JSContext* cx, JS::HandleObject regexp,
JS::MutableHandle<RegExpShared*> shared);
/* Implemented in jswrapper.cpp. */ /* Implemented in jswrapper.cpp. */
typedef enum NukeReferencesToWindow { typedef enum NukeReferencesToWindow {

View file

@ -117,7 +117,7 @@ class JS_FRIEND_API(Wrapper) : public BaseProxyHandler
virtual JSString* fun_toString(JSContext* cx, HandleObject proxy, virtual JSString* fun_toString(JSContext* cx, HandleObject proxy,
bool isToSource) const override; bool isToSource) const override;
virtual bool regexp_toShared(JSContext* cx, HandleObject proxy, virtual bool regexp_toShared(JSContext* cx, HandleObject proxy,
RegExpGuard* g) const override; MutableHandle<RegExpShared*> shared) const override;
virtual bool boxedValue_unbox(JSContext* cx, HandleObject proxy, virtual bool boxedValue_unbox(JSContext* cx, HandleObject proxy,
MutableHandleValue vp) const override; MutableHandleValue vp) const override;
virtual bool isCallable(JSObject* obj) const override; virtual bool isCallable(JSObject* obj) const override;
@ -211,7 +211,8 @@ class JS_FRIEND_API(CrossCompartmentWrapper) : public Wrapper
virtual const char* className(JSContext* cx, HandleObject proxy) const override; virtual const char* className(JSContext* cx, HandleObject proxy) const override;
virtual JSString* fun_toString(JSContext* cx, HandleObject wrapper, virtual JSString* fun_toString(JSContext* cx, HandleObject wrapper,
bool isToSource) const override; bool isToSource) const override;
virtual bool regexp_toShared(JSContext* cx, HandleObject proxy, RegExpGuard* g) const override; virtual bool regexp_toShared(JSContext* cx, HandleObject proxy,
MutableHandle<RegExpShared*> shared) const override;
virtual bool boxedValue_unbox(JSContext* cx, HandleObject proxy, MutableHandleValue vp) const override; virtual bool boxedValue_unbox(JSContext* cx, HandleObject proxy, MutableHandleValue vp) const override;
// Allocate CrossCompartmentWrappers in the nursery. // Allocate CrossCompartmentWrappers in the nursery.
@ -312,7 +313,8 @@ class JS_FRIEND_API(SecurityWrapper) : public Base
const CallArgs& args) const override; const CallArgs& args) const override;
virtual bool getBuiltinClass(JSContext* cx, HandleObject wrapper, ESClass* cls) const override; virtual bool getBuiltinClass(JSContext* cx, HandleObject wrapper, ESClass* cls) const override;
virtual bool isArray(JSContext* cx, HandleObject wrapper, JS::IsArrayAnswer* answer) const override; virtual bool isArray(JSContext* cx, HandleObject wrapper, JS::IsArrayAnswer* answer) const override;
virtual bool regexp_toShared(JSContext* cx, HandleObject proxy, RegExpGuard* g) const override; virtual bool regexp_toShared(JSContext* cx, HandleObject proxy,
MutableHandle<RegExpShared*> shared) const override;
virtual bool boxedValue_unbox(JSContext* cx, HandleObject proxy, MutableHandleValue vp) const override; virtual bool boxedValue_unbox(JSContext* cx, HandleObject proxy, MutableHandleValue vp) const override;
/* /*

View file

@ -327,7 +327,7 @@ BaseProxyHandler::fun_toString(JSContext* cx, HandleObject proxy, bool isToSourc
bool bool
BaseProxyHandler::regexp_toShared(JSContext* cx, HandleObject proxy, BaseProxyHandler::regexp_toShared(JSContext* cx, HandleObject proxy,
RegExpGuard* g) const MutableHandleRegExpShared shared) const
{ {
MOZ_CRASH("This should have been a wrapped regexp"); MOZ_CRASH("This should have been a wrapped regexp");
} }

View file

@ -437,9 +437,10 @@ CrossCompartmentWrapper::fun_toString(JSContext* cx, HandleObject wrapper, bool
} }
bool bool
CrossCompartmentWrapper::regexp_toShared(JSContext* cx, HandleObject wrapper, RegExpGuard* g) const CrossCompartmentWrapper::regexp_toShared(JSContext* cx, HandleObject wrapper,
MutableHandleRegExpShared shared) const
{ {
RegExpGuard re(cx); RootedRegExpShared re(cx);
{ {
AutoCompartment call(cx, wrappedObject(wrapper)); AutoCompartment call(cx, wrappedObject(wrapper));
if (!Wrapper::regexp_toShared(cx, wrapper, &re)) if (!Wrapper::regexp_toShared(cx, wrapper, &re))
@ -447,7 +448,7 @@ CrossCompartmentWrapper::regexp_toShared(JSContext* cx, HandleObject wrapper, Re
} }
// Get an equivalent RegExpShared associated with the current compartment. // Get an equivalent RegExpShared associated with the current compartment.
return cx->compartment()->regExps.get(cx, re->getSource(), re->getFlags(), g); return cx->compartment()->regExps.get(cx, re->getSource(), re->getFlags(), shared);
} }
bool bool

View file

@ -142,7 +142,8 @@ DeadObjectProxy::fun_toString(JSContext* cx, HandleObject proxy, bool isToSource
} }
bool bool
DeadObjectProxy::regexp_toShared(JSContext* cx, HandleObject proxy, RegExpGuard* g) const DeadObjectProxy::regexp_toShared(JSContext* cx, HandleObject proxy,
MutableHandle<RegExpShared*> shared) const
{ {
ReportDead(cx); ReportDead(cx);
return false; return false;

View file

@ -49,7 +49,8 @@ class DeadObjectProxy : public BaseProxyHandler
virtual const char* className(JSContext* cx, HandleObject proxy) const override; virtual const char* className(JSContext* cx, HandleObject proxy) const override;
virtual JSString* fun_toString(JSContext* cx, HandleObject proxy, virtual JSString* fun_toString(JSContext* cx, HandleObject proxy,
bool isToSource) const override; bool isToSource) const override;
virtual bool regexp_toShared(JSContext* cx, HandleObject proxy, RegExpGuard* g) const override; virtual bool regexp_toShared(JSContext* cx, HandleObject proxy,
MutableHandle<RegExpShared*> shared) const override;
virtual bool isCallable(JSObject* obj) const override; virtual bool isCallable(JSObject* obj) const override;
virtual bool isConstructor(JSObject* obj) const override; virtual bool isConstructor(JSObject* obj) const override;

View file

@ -488,10 +488,10 @@ Proxy::fun_toString(JSContext* cx, HandleObject proxy, bool isToSource)
} }
bool bool
Proxy::regexp_toShared(JSContext* cx, HandleObject proxy, RegExpGuard* g) Proxy::regexp_toShared(JSContext* cx, HandleObject proxy, MutableHandleRegExpShared shared)
{ {
JS_CHECK_RECURSION(cx, return false); JS_CHECK_RECURSION(cx, return false);
return proxy->as<ProxyObject>().handler()->regexp_toShared(cx, proxy, g); return proxy->as<ProxyObject>().handler()->regexp_toShared(cx, proxy, shared);
} }
bool bool

View file

@ -59,7 +59,8 @@ class Proxy
static bool isArray(JSContext* cx, HandleObject proxy, JS::IsArrayAnswer* answer); static bool isArray(JSContext* cx, HandleObject proxy, JS::IsArrayAnswer* answer);
static const char* className(JSContext* cx, HandleObject proxy); static const char* className(JSContext* cx, HandleObject proxy);
static JSString* fun_toString(JSContext* cx, HandleObject proxy, bool isToSource); static JSString* fun_toString(JSContext* cx, HandleObject proxy, bool isToSource);
static bool regexp_toShared(JSContext* cx, HandleObject proxy, RegExpGuard* g); static bool regexp_toShared(JSContext* cx, HandleObject proxy,
MutableHandle<RegExpShared*> shared);
static bool boxedValue_unbox(JSContext* cx, HandleObject proxy, MutableHandleValue vp); static bool boxedValue_unbox(JSContext* cx, HandleObject proxy, MutableHandleValue vp);
static bool getElements(JSContext* cx, HandleObject obj, uint32_t begin, uint32_t end, static bool getElements(JSContext* cx, HandleObject obj, uint32_t begin, uint32_t end,

View file

@ -1265,7 +1265,8 @@ ScriptedProxyHandler::fun_toString(JSContext* cx, HandleObject proxy, bool isToS
} }
bool bool
ScriptedProxyHandler::regexp_toShared(JSContext* cx, HandleObject proxy, RegExpGuard* g) const ScriptedProxyHandler::regexp_toShared(JSContext* cx, HandleObject proxy,
MutableHandleRegExpShared shared) const
{ {
MOZ_CRASH("Should not end up in ScriptedProxyHandler::regexp_toShared"); MOZ_CRASH("Should not end up in ScriptedProxyHandler::regexp_toShared");
return false; return false;

View file

@ -69,7 +69,7 @@ class ScriptedProxyHandler : public BaseProxyHandler
virtual JSString* fun_toString(JSContext* cx, HandleObject proxy, virtual JSString* fun_toString(JSContext* cx, HandleObject proxy,
bool isToSource) const override; bool isToSource) const override;
virtual bool regexp_toShared(JSContext* cx, HandleObject proxy, virtual bool regexp_toShared(JSContext* cx, HandleObject proxy,
RegExpGuard* g) const override; MutableHandle<RegExpShared*> shared) const override;
virtual bool boxedValue_unbox(JSContext* cx, HandleObject proxy, virtual bool boxedValue_unbox(JSContext* cx, HandleObject proxy,
MutableHandleValue vp) const override; MutableHandleValue vp) const override;

View file

@ -93,9 +93,10 @@ SecurityWrapper<Base>::isArray(JSContext* cx, HandleObject obj, JS::IsArrayAnswe
template <class Base> template <class Base>
bool bool
SecurityWrapper<Base>::regexp_toShared(JSContext* cx, HandleObject obj, RegExpGuard* g) const SecurityWrapper<Base>::regexp_toShared(JSContext* cx, HandleObject obj,
MutableHandle<RegExpShared*> shared) const
{ {
return Base::regexp_toShared(cx, obj, g); return Base::regexp_toShared(cx, obj, shared);
} }
template <class Base> template <class Base>

View file

@ -267,10 +267,10 @@ Wrapper::fun_toString(JSContext* cx, HandleObject proxy, bool isToSource) const
} }
bool bool
Wrapper::regexp_toShared(JSContext* cx, HandleObject proxy, RegExpGuard* g) const Wrapper::regexp_toShared(JSContext* cx, HandleObject proxy, MutableHandleRegExpShared shared) const
{ {
RootedObject target(cx, proxy->as<ProxyObject>().target()); RootedObject target(cx, proxy->as<ProxyObject>().target());
return RegExpToShared(cx, target, g); return RegExpToShared(cx, target, shared);
} }
bool bool

View file

@ -122,14 +122,15 @@ VectorMatchPairs::allocOrExpandArray(size_t pairCount)
/* RegExpObject */ /* RegExpObject */
/* static */ bool /* static */ bool
RegExpObject::getShared(JSContext* cx, Handle<RegExpObject*> regexp, RegExpGuard* g) RegExpObject::getShared(JSContext* cx, Handle<RegExpObject*> regexp,
MutableHandleRegExpShared shared)
{ {
if (regexp->hasShared()) { if (regexp->hasShared()) {
g->set(regexp->sharedRef()); shared.set(regexp->sharedRef());
return true; return true;
} }
return createShared(cx, regexp, g); return createShared(cx, regexp, shared);
} }
/* static */ bool /* static */ bool
@ -278,13 +279,14 @@ RegExpObject::create(ExclusiveContext* cx, HandleAtom source, RegExpFlag flags,
} }
/* static */ bool /* static */ bool
RegExpObject::createShared(JSContext* cx, Handle<RegExpObject*> regexp, RegExpGuard* g) RegExpObject::createShared(JSContext* cx, Handle<RegExpObject*> regexp,
MutableHandleRegExpShared shared)
{ {
MOZ_ASSERT(!regexp->hasShared()); MOZ_ASSERT(!regexp->hasShared());
if (!cx->compartment()->regExps.get(cx, regexp->getSource(), regexp->getFlags(), g)) if (!cx->compartment()->regExps.get(cx, regexp->getSource(), regexp->getFlags(), shared))
return false; return false;
regexp->setShared(**g); regexp->setShared(*shared);
return true; return true;
} }
@ -891,11 +893,11 @@ RegExpShared::dumpBytecode(JSContext* cx, bool match_only, HandleLinearString in
RegExpObject::dumpBytecode(JSContext* cx, Handle<RegExpObject*> regexp, RegExpObject::dumpBytecode(JSContext* cx, Handle<RegExpObject*> regexp,
bool match_only, HandleLinearString input) bool match_only, HandleLinearString input)
{ {
RegExpGuard g(cx); RootedRegExpShared shared(cx);
if (!getShared(cx, regexp, &g)) if (!getShared(cx, regexp, &shared))
return false; return false;
return g->dumpBytecode(cx, match_only, input); return shared->dumpBytecode(cx, match_only, input);
} }
#endif #endif
@ -1351,11 +1353,12 @@ RegExpCompartment::sweep(JSRuntime* rt)
} }
bool bool
RegExpCompartment::get(JSContext* cx, JSAtom* source, RegExpFlag flags, RegExpGuard* g) RegExpCompartment::get(JSContext* cx, JSAtom* source, RegExpFlag flags,
MutableHandleRegExpShared result)
{ {
DependentAddPtr<Set> p(cx, set_.get(), Key(source, flags)); DependentAddPtr<Set> p(cx, set_.get(), Key(source, flags));
if (p) { if (p) {
g->set(*p); result.set(*p);
return true; return true;
} }
@ -1370,18 +1373,19 @@ RegExpCompartment::get(JSContext* cx, JSAtom* source, RegExpFlag flags, RegExpGu
return false; return false;
} }
g->set(shared); result.set(shared);
return true; return true;
} }
bool bool
RegExpCompartment::get(JSContext* cx, HandleAtom atom, JSString* opt, RegExpGuard* g) RegExpCompartment::get(JSContext* cx, HandleAtom atom, JSString* opt,
MutableHandleRegExpShared shared)
{ {
RegExpFlag flags = RegExpFlag(0); RegExpFlag flags = RegExpFlag(0);
if (opt && !ParseRegExpFlags(cx, opt, &flags)) if (opt && !ParseRegExpFlags(cx, opt, &flags))
return false; return false;
return get(cx, atom, flags, g); return get(cx, atom, flags, shared);
} }
size_t size_t
@ -1410,12 +1414,12 @@ js::CloneRegExpObject(JSContext* cx, JSObject* obj_)
Rooted<JSAtom*> source(cx, regex->getSource()); Rooted<JSAtom*> source(cx, regex->getSource());
RegExpGuard g(cx); RootedRegExpShared shared(cx);
if (!RegExpObject::getShared(cx, regex, &g)) if (!RegExpObject::getShared(cx, regex, &shared))
return nullptr; return nullptr;
clone->initAndZeroLastIndex(source, g->getFlags(), cx); clone->initAndZeroLastIndex(source, shared->getFlags(), cx);
clone->setShared(*g); clone->setShared(*shared);
return clone; return clone;
} }
@ -1554,9 +1558,9 @@ js::CloneScriptRegExpObject(JSContext* cx, RegExpObject& reobj)
} }
JS_FRIEND_API(bool) JS_FRIEND_API(bool)
js::RegExpToSharedNonInline(JSContext* cx, HandleObject obj, js::RegExpGuard* g) js::RegExpToSharedNonInline(JSContext* cx, HandleObject obj, MutableHandleRegExpShared shared)
{ {
return RegExpToShared(cx, obj, g); return RegExpToShared(cx, obj, shared);
} }
JS::ubi::Node::Size JS::ubi::Node::Size

View file

@ -32,10 +32,8 @@
* *
* To save memory, a RegExpShared is not created for a RegExpObject until it is * To save memory, a RegExpShared is not created for a RegExpObject until it is
* needed for execution. When a RegExpShared needs to be created, it is looked * needed for execution. When a RegExpShared needs to be created, it is looked
* up in a per-compartment table to allow reuse between objects. Lastly, on * up in a per-compartment table to allow reuse between objects. Lastly, on GC,
* GC, every RegExpShared (that is not active on the callstack) is discarded. * every RegExpShared that is not in active use is discarded.
* Because of the last point, any code using a RegExpShared (viz., by executing
* a regexp) must indicate the RegExpShared is active via RegExpGuard.
*/ */
namespace js { namespace js {
@ -251,6 +249,10 @@ class RegExpShared : public gc::TenuredCell
#endif #endif
}; };
using RootedRegExpShared = JS::Rooted<RegExpShared*>;
using HandleRegExpShared = JS::Handle<RegExpShared*>;
using MutableHandleRegExpShared = JS::MutableHandle<RegExpShared*>;
class RegExpCompartment class RegExpCompartment
{ {
struct Key { struct Key {
@ -321,10 +323,11 @@ class RegExpCompartment
bool empty() { return set_.empty(); } bool empty() { return set_.empty(); }
bool get(JSContext* cx, JSAtom* source, RegExpFlag flags, RegExpGuard* g); bool get(JSContext* cx, JSAtom* source, RegExpFlag flags, MutableHandleRegExpShared shared);
/* Like 'get', but compile 'maybeOpt' (if non-null). */ /* Like 'get', but compile 'maybeOpt' (if non-null). */
bool get(JSContext* cx, HandleAtom source, JSString* maybeOpt, RegExpGuard* g); bool get(JSContext* cx, HandleAtom source, JSString* maybeOpt,
MutableHandleRegExpShared shared);
/* Get or create template object used to base the result of .exec() on. */ /* Get or create template object used to base the result of .exec() on. */
ArrayObject* getOrCreateMatchResultTemplateObject(JSContext* cx) { ArrayObject* getOrCreateMatchResultTemplateObject(JSContext* cx) {
@ -447,7 +450,7 @@ class RegExpObject : public NativeObject
static bool isOriginalFlagGetter(JSNative native, RegExpFlag* mask); static bool isOriginalFlagGetter(JSNative native, RegExpFlag* mask);
static MOZ_MUST_USE bool getShared(JSContext* cx, Handle<RegExpObject*> regexp, static MOZ_MUST_USE bool getShared(JSContext* cx, Handle<RegExpObject*> regexp,
RegExpGuard* g); MutableHandleRegExpShared shared);
bool hasShared() { bool hasShared() {
return !!sharedRef(); return !!sharedRef();
@ -479,7 +482,7 @@ class RegExpObject : public NativeObject
* Side effect: sets the private field. * Side effect: sets the private field.
*/ */
static MOZ_MUST_USE bool createShared(JSContext* cx, Handle<RegExpObject*> regexp, static MOZ_MUST_USE bool createShared(JSContext* cx, Handle<RegExpObject*> regexp,
RegExpGuard* g); MutableHandleRegExpShared shared);
ReadBarriered<RegExpShared*>& sharedRef() { ReadBarriered<RegExpShared*>& sharedRef() {
auto& ref = NativeObject::privateRef(PRIVATE_SLOT); auto& ref = NativeObject::privateRef(PRIVATE_SLOT);
@ -501,12 +504,12 @@ ParseRegExpFlags(JSContext* cx, JSString* flagStr, RegExpFlag* flagsOut);
/* Assuming GetBuiltinClass(obj) is ESClass::RegExp, return a RegExpShared for obj. */ /* Assuming GetBuiltinClass(obj) is ESClass::RegExp, return a RegExpShared for obj. */
inline bool inline bool
RegExpToShared(JSContext* cx, HandleObject obj, RegExpGuard* g) RegExpToShared(JSContext* cx, HandleObject obj, MutableHandleRegExpShared shared)
{ {
if (obj->is<RegExpObject>()) if (obj->is<RegExpObject>())
return RegExpObject::getShared(cx, obj.as<RegExpObject>(), g); return RegExpObject::getShared(cx, obj.as<RegExpObject>(), shared);
return Proxy::regexp_toShared(cx, obj, g); return Proxy::regexp_toShared(cx, obj, shared);
} }
template<XDRMode mode> template<XDRMode mode>

View file

@ -80,8 +80,8 @@ RegExpStatics::executeLazy(JSContext* cx)
MOZ_ASSERT(lazyIndex != size_t(-1)); MOZ_ASSERT(lazyIndex != size_t(-1));
/* Retrieve or create the RegExpShared in this compartment. */ /* Retrieve or create the RegExpShared in this compartment. */
RegExpGuard g(cx); RootedRegExpShared shared(cx);
if (!cx->compartment()->regExps.get(cx, lazySource, lazyFlags, &g)) if (!cx->compartment()->regExps.get(cx, lazySource, lazyFlags, &shared))
return false; return false;
/* /*
@ -91,7 +91,7 @@ RegExpStatics::executeLazy(JSContext* cx)
/* Execute the full regular expression. */ /* Execute the full regular expression. */
RootedLinearString input(cx, matchesInput); RootedLinearString input(cx, matchesInput);
RegExpRunStatus status = g->execute(cx, input, lazyIndex, &this->matches, nullptr); RegExpRunStatus status = shared->execute(cx, input, lazyIndex, &this->matches, nullptr);
if (status == RegExpRunStatus_Error) if (status == RegExpRunStatus_Error)
return false; return false;

View file

@ -1402,7 +1402,7 @@ JSStructuredCloneWriter::startWrite(HandleValue v)
return false; return false;
if (cls == ESClass::RegExp) { if (cls == ESClass::RegExp) {
RegExpGuard re(context()); RootedRegExpShared re(context());
if (!RegExpToShared(context(), obj, &re)) if (!RegExpToShared(context(), obj, &re))
return false; return false;
return out.writePair(SCTAG_REGEXP_OBJECT, re->getFlags()) && return out.writePair(SCTAG_REGEXP_OBJECT, re->getFlags()) &&