mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 832217 - Construct RegExpShared in the same compartment as the RegExpStatics. r=billm
This commit is contained in:
parent
a0a8f9ba33
commit
46f8dd6c33
@ -633,11 +633,12 @@ RegExpStatics::AutoRooter::trace(JSTracer *trc)
|
|||||||
if (statics->matchesInput)
|
if (statics->matchesInput)
|
||||||
MarkStringRoot(trc, reinterpret_cast<JSString**>(&statics->matchesInput),
|
MarkStringRoot(trc, reinterpret_cast<JSString**>(&statics->matchesInput),
|
||||||
"RegExpStatics::AutoRooter matchesInput");
|
"RegExpStatics::AutoRooter matchesInput");
|
||||||
|
if (statics->lazySource)
|
||||||
|
MarkStringRoot(trc, reinterpret_cast<JSString**>(&statics->lazySource),
|
||||||
|
"RegExpStatics::AutoRooter lazySource");
|
||||||
if (statics->pendingInput)
|
if (statics->pendingInput)
|
||||||
MarkStringRoot(trc, reinterpret_cast<JSString**>(&statics->pendingInput),
|
MarkStringRoot(trc, reinterpret_cast<JSString**>(&statics->pendingInput),
|
||||||
"RegExpStatics::AutoRooter pendingInput");
|
"RegExpStatics::AutoRooter pendingInput");
|
||||||
if (statics->regexp.initialized())
|
|
||||||
statics->regexp->trace(trc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -100,12 +100,6 @@ RegExpObject::setSticky(bool enabled)
|
|||||||
setSlot(STICKY_FLAG_SLOT, BooleanValue(enabled));
|
setSlot(STICKY_FLAG_SLOT, BooleanValue(enabled));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
|
||||||
RegExpShared::writeBarrierPre()
|
|
||||||
{
|
|
||||||
JSString::writeBarrierPre(source);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This function should be deleted once bad Android platforms phase out. See bug 604774. */
|
/* This function should be deleted once bad Android platforms phase out. See bug 604774. */
|
||||||
inline bool
|
inline bool
|
||||||
RegExpShared::isJITRuntimeEnabled(JSContext *cx)
|
RegExpShared::isJITRuntimeEnabled(JSContext *cx)
|
||||||
@ -170,32 +164,18 @@ RegExpGuard::release()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RegExpHeapGuard::RegExpHeapGuard(RegExpShared &re)
|
|
||||||
{
|
|
||||||
init(re);
|
|
||||||
}
|
|
||||||
|
|
||||||
RegExpHeapGuard::~RegExpHeapGuard()
|
|
||||||
{
|
|
||||||
release();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
RegExpHeapGuard::init(RegExpShared &re)
|
MatchPairs::checkAgainst(size_t inputLength)
|
||||||
{
|
{
|
||||||
JS_ASSERT(!initialized());
|
#ifdef DEBUG
|
||||||
re_ = &re;
|
for (size_t i = 0; i < pairCount_; i++) {
|
||||||
re_->incRef();
|
const MatchPair &p = pair(i);
|
||||||
}
|
JS_ASSERT(p.check());
|
||||||
|
if (p.isUndefined())
|
||||||
inline void
|
continue;
|
||||||
RegExpHeapGuard::release()
|
JS_ASSERT(size_t(p.limit) <= inputLength);
|
||||||
{
|
|
||||||
if (re_) {
|
|
||||||
re_->writeBarrierPre();
|
|
||||||
re_->decRef();
|
|
||||||
re_ = NULL;
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
} /* namespace js */
|
} /* namespace js */
|
||||||
|
@ -159,20 +159,6 @@ MatchPairs::displace(size_t disp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
|
||||||
MatchPairs::checkAgainst(size_t inputLength)
|
|
||||||
{
|
|
||||||
#if DEBUG
|
|
||||||
for (size_t i = 0; i < pairCount_; i++) {
|
|
||||||
const MatchPair &p = pair(i);
|
|
||||||
JS_ASSERT(p.check());
|
|
||||||
if (p.isUndefined())
|
|
||||||
continue;
|
|
||||||
JS_ASSERT(size_t(p.limit) <= inputLength);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ScopedMatchPairs::allocOrExpandArray(size_t pairCount)
|
ScopedMatchPairs::allocOrExpandArray(size_t pairCount)
|
||||||
{
|
{
|
||||||
@ -312,7 +298,7 @@ RegExpObject::assignInitialShape(JSContext *cx)
|
|||||||
return self->addDataProperty(cx, cx->names().sticky, STICKY_FLAG_SLOT, attrs);
|
return self->addDataProperty(cx, cx->names().sticky, STICKY_FLAG_SLOT, attrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
bool
|
||||||
RegExpObject::init(JSContext *cx, HandleAtom source, RegExpFlag flags)
|
RegExpObject::init(JSContext *cx, HandleAtom source, RegExpFlag flags)
|
||||||
{
|
{
|
||||||
Rooted<RegExpObject *> self(cx, this);
|
Rooted<RegExpObject *> self(cx, this);
|
||||||
@ -645,17 +631,6 @@ RegExpCompartment::RegExpCompartment(JSRuntime *rt)
|
|||||||
RegExpCompartment::~RegExpCompartment()
|
RegExpCompartment::~RegExpCompartment()
|
||||||
{
|
{
|
||||||
JS_ASSERT(map_.empty());
|
JS_ASSERT(map_.empty());
|
||||||
|
|
||||||
/*
|
|
||||||
* RegExpStatics may have prevented a single RegExpShared from
|
|
||||||
* being collected during RegExpCompartment::sweep().
|
|
||||||
*/
|
|
||||||
for (PendingSet::Enum e(inUse_); !e.empty(); e.popFront()) {
|
|
||||||
RegExpShared *shared = e.front();
|
|
||||||
JS_ASSERT(shared->activeUseCount == 0);
|
|
||||||
js_delete(shared);
|
|
||||||
e.removeFront();
|
|
||||||
}
|
|
||||||
JS_ASSERT(inUse_.empty());
|
JS_ASSERT(inUse_.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -691,7 +666,7 @@ RegExpCompartment::sweep(JSRuntime *rt)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
bool
|
||||||
RegExpCompartment::get(JSContext *cx, JSAtom *source, RegExpFlag flags, RegExpGuard *g)
|
RegExpCompartment::get(JSContext *cx, JSAtom *source, RegExpFlag flags, RegExpGuard *g)
|
||||||
{
|
{
|
||||||
Key key(source, flags);
|
Key key(source, flags);
|
||||||
|
@ -109,6 +109,7 @@ CloneRegExpObject(JSContext *cx, JSObject *obj, JSObject *proto);
|
|||||||
class RegExpShared
|
class RegExpShared
|
||||||
{
|
{
|
||||||
friend class RegExpCompartment;
|
friend class RegExpCompartment;
|
||||||
|
friend class RegExpStatics;
|
||||||
friend class RegExpGuard;
|
friend class RegExpGuard;
|
||||||
|
|
||||||
typedef frontend::TokenStream TokenStream;
|
typedef frontend::TokenStream TokenStream;
|
||||||
@ -124,7 +125,7 @@ class RegExpShared
|
|||||||
/*
|
/*
|
||||||
* Source to the RegExp, for lazy compilation.
|
* Source to the RegExp, for lazy compilation.
|
||||||
* The source must be rooted while activeUseCount is non-zero
|
* The source must be rooted while activeUseCount is non-zero
|
||||||
* via RegExpGuard, RegExpHeapGuard, or explicit calls to trace().
|
* via RegExpGuard or explicit calls to trace().
|
||||||
*/
|
*/
|
||||||
JSAtom * source;
|
JSAtom * source;
|
||||||
|
|
||||||
@ -156,7 +157,6 @@ class RegExpShared
|
|||||||
void trace(JSTracer *trc) {
|
void trace(JSTracer *trc) {
|
||||||
MarkStringUnbarriered(trc, &source, "regexpshared source");
|
MarkStringUnbarriered(trc, &source, "regexpshared source");
|
||||||
}
|
}
|
||||||
inline void writeBarrierPre();
|
|
||||||
|
|
||||||
/* Static functions to expose some Yarr logic. */
|
/* Static functions to expose some Yarr logic. */
|
||||||
static inline bool isJITRuntimeEnabled(JSContext *cx);
|
static inline bool isJITRuntimeEnabled(JSContext *cx);
|
||||||
@ -233,34 +233,6 @@ class RegExpGuard
|
|||||||
RegExpShared &operator*() { return *re(); }
|
RegExpShared &operator*() { return *re(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Equivalent of RegExpGuard, heap-allocated, with explicit tracing. */
|
|
||||||
class RegExpHeapGuard
|
|
||||||
{
|
|
||||||
RegExpShared *re_;
|
|
||||||
|
|
||||||
RegExpHeapGuard(const RegExpGuard &) MOZ_DELETE;
|
|
||||||
void operator=(const RegExpHeapGuard &) MOZ_DELETE;
|
|
||||||
|
|
||||||
public:
|
|
||||||
RegExpHeapGuard() : re_(NULL) { }
|
|
||||||
inline RegExpHeapGuard(RegExpShared &re);
|
|
||||||
inline ~RegExpHeapGuard();
|
|
||||||
|
|
||||||
public:
|
|
||||||
inline void init(RegExpShared &re);
|
|
||||||
inline void release();
|
|
||||||
|
|
||||||
void trace(JSTracer *trc) {
|
|
||||||
if (initialized())
|
|
||||||
re_->trace(trc);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool initialized() const { return !!re_; }
|
|
||||||
RegExpShared *re() const { JS_ASSERT(initialized()); return re_; }
|
|
||||||
RegExpShared *operator->() { return re(); }
|
|
||||||
RegExpShared &operator*() { return *re(); }
|
|
||||||
};
|
|
||||||
|
|
||||||
class RegExpCompartment
|
class RegExpCompartment
|
||||||
{
|
{
|
||||||
struct Key {
|
struct Key {
|
||||||
@ -384,7 +356,7 @@ class RegExpObject : public JSObject
|
|||||||
*/
|
*/
|
||||||
UnrootedShape assignInitialShape(JSContext *cx);
|
UnrootedShape assignInitialShape(JSContext *cx);
|
||||||
|
|
||||||
inline bool init(JSContext *cx, HandleAtom source, RegExpFlag flags);
|
bool init(JSContext *cx, HandleAtom source, RegExpFlag flags);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Precondition: the syntax for |source| has already been validated.
|
* Precondition: the syntax for |source| has already been validated.
|
||||||
|
@ -21,16 +21,21 @@ class RegExpStatics
|
|||||||
VectorMatchPairs matches;
|
VectorMatchPairs matches;
|
||||||
HeapPtr<JSLinearString> matchesInput;
|
HeapPtr<JSLinearString> matchesInput;
|
||||||
|
|
||||||
/* The previous RegExp input, used to resolve lazy state. */
|
/*
|
||||||
RegExpHeapGuard regexp;
|
* The previous RegExp input, used to resolve lazy state.
|
||||||
size_t lastIndex;
|
* A raw RegExpShared cannot be stored because it may be in
|
||||||
|
* a different compartment via evalcx().
|
||||||
|
*/
|
||||||
|
HeapPtr<JSAtom> lazySource;
|
||||||
|
RegExpFlag lazyFlags;
|
||||||
|
size_t lazyIndex;
|
||||||
|
|
||||||
/* The latest RegExp input, set before execution. */
|
/* The latest RegExp input, set before execution. */
|
||||||
HeapPtr<JSString> pendingInput;
|
HeapPtr<JSString> pendingInput;
|
||||||
RegExpFlag flags;
|
RegExpFlag flags;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If true, |matchesInput|, |regexp|, and |lastIndex| may be used
|
* If true, |matchesInput| and the |lazy*| fields may be used
|
||||||
* to replay the last executed RegExp, and |matches| is invalid.
|
* to replay the last executed RegExp, and |matches| is invalid.
|
||||||
*/
|
*/
|
||||||
bool pendingLazyEvaluation;
|
bool pendingLazyEvaluation;
|
||||||
@ -118,12 +123,12 @@ class RegExpStatics
|
|||||||
* Changes to this function must also be reflected in
|
* Changes to this function must also be reflected in
|
||||||
* RegExpStatics::AutoRooter::trace().
|
* RegExpStatics::AutoRooter::trace().
|
||||||
*/
|
*/
|
||||||
if (pendingInput)
|
|
||||||
MarkString(trc, &pendingInput, "res->pendingInput");
|
|
||||||
if (matchesInput)
|
if (matchesInput)
|
||||||
MarkString(trc, &matchesInput, "res->matchesInput");
|
MarkString(trc, &matchesInput, "res->matchesInput");
|
||||||
if (regexp.initialized())
|
if (lazySource)
|
||||||
regexp->trace(trc);
|
MarkString(trc, &lazySource, "res->lazySource");
|
||||||
|
if (pendingInput)
|
||||||
|
MarkString(trc, &pendingInput, "res->pendingInput");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Value creators. */
|
/* Value creators. */
|
||||||
@ -393,20 +398,16 @@ RegExpStatics::copyTo(RegExpStatics &dst)
|
|||||||
if (!pendingLazyEvaluation)
|
if (!pendingLazyEvaluation)
|
||||||
dst.matches.initArrayFrom(matches);
|
dst.matches.initArrayFrom(matches);
|
||||||
|
|
||||||
if (regexp.initialized())
|
|
||||||
dst.regexp.init(*regexp);
|
|
||||||
else
|
|
||||||
dst.regexp.release();
|
|
||||||
|
|
||||||
dst.matchesInput = matchesInput;
|
dst.matchesInput = matchesInput;
|
||||||
dst.lastIndex = lastIndex;
|
dst.lazySource = lazySource;
|
||||||
|
dst.lazyFlags = lazyFlags;
|
||||||
|
dst.lazyIndex = lazyIndex;
|
||||||
dst.pendingInput = pendingInput;
|
dst.pendingInput = pendingInput;
|
||||||
dst.flags = flags;
|
dst.flags = flags;
|
||||||
dst.pendingLazyEvaluation = pendingLazyEvaluation;
|
dst.pendingLazyEvaluation = pendingLazyEvaluation;
|
||||||
|
|
||||||
JS_ASSERT_IF(pendingLazyEvaluation, regexp.initialized());
|
JS_ASSERT_IF(pendingLazyEvaluation, lazySource);
|
||||||
JS_ASSERT_IF(pendingLazyEvaluation, matchesInput);
|
JS_ASSERT_IF(pendingLazyEvaluation, matchesInput);
|
||||||
JS_ASSERT(regexp.initialized() == dst.regexp.initialized());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
@ -436,11 +437,10 @@ RegExpStatics::updateLazily(JSContext *cx, JSLinearString *input,
|
|||||||
BarrieredSetPair<JSString, JSLinearString>(cx->zone(),
|
BarrieredSetPair<JSString, JSLinearString>(cx->zone(),
|
||||||
pendingInput, input,
|
pendingInput, input,
|
||||||
matchesInput, input);
|
matchesInput, input);
|
||||||
if (regexp.initialized())
|
|
||||||
regexp.release();
|
|
||||||
regexp.init(*shared);
|
|
||||||
|
|
||||||
this->lastIndex = lastIndex;
|
lazySource = shared->source;
|
||||||
|
lazyFlags = shared->flags;
|
||||||
|
lazyIndex = lastIndex;
|
||||||
pendingLazyEvaluation = true;
|
pendingLazyEvaluation = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -452,8 +452,8 @@ RegExpStatics::updateFromMatchPairs(JSContext *cx, JSLinearString *input, MatchP
|
|||||||
|
|
||||||
/* Unset all lazy state. */
|
/* Unset all lazy state. */
|
||||||
pendingLazyEvaluation = false;
|
pendingLazyEvaluation = false;
|
||||||
this->regexp.release();
|
this->lazySource = NULL;
|
||||||
this->lastIndex = size_t(-1);
|
this->lazyIndex = size_t(-1);
|
||||||
|
|
||||||
BarrieredSetPair<JSString, JSLinearString>(cx->zone(),
|
BarrieredSetPair<JSString, JSLinearString>(cx->zone(),
|
||||||
pendingInput, input,
|
pendingInput, input,
|
||||||
@ -474,8 +474,9 @@ RegExpStatics::clear()
|
|||||||
|
|
||||||
matches.forgetArray();
|
matches.forgetArray();
|
||||||
matchesInput = NULL;
|
matchesInput = NULL;
|
||||||
regexp.release();
|
lazySource = NULL;
|
||||||
lastIndex = size_t(-1);
|
lazyFlags = RegExpFlag(0);
|
||||||
|
lazyIndex = size_t(-1);
|
||||||
pendingInput = NULL;
|
pendingInput = NULL;
|
||||||
flags = RegExpFlag(0);
|
flags = RegExpFlag(0);
|
||||||
pendingLazyEvaluation = false;
|
pendingLazyEvaluation = false;
|
||||||
@ -536,9 +537,9 @@ RegExpStatics::checkInvariants()
|
|||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (pendingLazyEvaluation) {
|
if (pendingLazyEvaluation) {
|
||||||
JS_ASSERT(regexp.initialized());
|
JS_ASSERT(lazySource);
|
||||||
JS_ASSERT(pendingInput);
|
JS_ASSERT(matchesInput);
|
||||||
JS_ASSERT(lastIndex != size_t(-1));
|
JS_ASSERT(lazyIndex != size_t(-1));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,9 +74,14 @@ RegExpStatics::executeLazy(JSContext *cx)
|
|||||||
if (!pendingLazyEvaluation)
|
if (!pendingLazyEvaluation)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
JS_ASSERT(regexp.initialized());
|
JS_ASSERT(lazySource);
|
||||||
JS_ASSERT(matchesInput);
|
JS_ASSERT(matchesInput);
|
||||||
JS_ASSERT(lastIndex != size_t(-1));
|
JS_ASSERT(lazyIndex != size_t(-1));
|
||||||
|
|
||||||
|
/* Retrieve or create the RegExpShared in this compartment. */
|
||||||
|
RegExpGuard g(cx);
|
||||||
|
if (!cx->compartment->regExps.get(cx, lazySource, lazyFlags, &g))
|
||||||
|
return false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* It is not necessary to call aboutToWrite(): evaluation of
|
* It is not necessary to call aboutToWrite(): evaluation of
|
||||||
@ -87,7 +92,7 @@ RegExpStatics::executeLazy(JSContext *cx)
|
|||||||
StableCharPtr chars(matchesInput->chars(), length);
|
StableCharPtr chars(matchesInput->chars(), length);
|
||||||
|
|
||||||
/* Execute the full regular expression. */
|
/* Execute the full regular expression. */
|
||||||
RegExpRunStatus status = regexp->execute(cx, chars, length, &this->lastIndex, this->matches);
|
RegExpRunStatus status = g->execute(cx, chars, length, &this->lazyIndex, this->matches);
|
||||||
if (status == RegExpRunStatus_Error)
|
if (status == RegExpRunStatus_Error)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -99,8 +104,8 @@ RegExpStatics::executeLazy(JSContext *cx)
|
|||||||
|
|
||||||
/* Unset lazy state and remove rooted values that now have no use. */
|
/* Unset lazy state and remove rooted values that now have no use. */
|
||||||
pendingLazyEvaluation = false;
|
pendingLazyEvaluation = false;
|
||||||
regexp.release();
|
lazySource = NULL;
|
||||||
lastIndex = size_t(-1);
|
lazyIndex = size_t(-1);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user