mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 820124, Part 1/2 - Use RegExpShared for lazy RegExpStatics. r=dvander
This commit is contained in:
parent
f2f6f1e8d7
commit
51920c3c44
@ -114,7 +114,7 @@ js::CreateRegExpMatchResult(JSContext *cx, HandleString string, MatchPairs &matc
|
||||
}
|
||||
|
||||
RegExpRunStatus
|
||||
ExecuteRegExpImpl(JSContext *cx, RegExpStatics *res, RegExpShared &re, RegExpObject ®exp,
|
||||
ExecuteRegExpImpl(JSContext *cx, RegExpStatics *res, RegExpShared &re,
|
||||
JSLinearString *input, StableCharPtr chars, size_t length,
|
||||
size_t *lastIndex, MatchConduit &matches)
|
||||
{
|
||||
@ -126,7 +126,7 @@ ExecuteRegExpImpl(JSContext *cx, RegExpStatics *res, RegExpShared &re, RegExpObj
|
||||
/* Only one MatchPair slot provided: execute short-circuiting regexp. */
|
||||
status = re.executeMatchOnly(cx, chars, length, lastIndex, *matches.u.pair);
|
||||
if (status == RegExpRunStatus_Success && res)
|
||||
res->updateLazily(cx, input, ®exp, lastIndex_orig);
|
||||
res->updateLazily(cx, input, &re, lastIndex_orig);
|
||||
} else {
|
||||
/* Vector of MatchPairs provided: execute full regexp. */
|
||||
status = re.execute(cx, chars, length, lastIndex, *matches.u.pairs);
|
||||
@ -151,7 +151,7 @@ js::ExecuteRegExpLegacy(JSContext *cx, RegExpStatics *res, RegExpObject &reobj,
|
||||
MatchConduit conduit(&matches);
|
||||
|
||||
RegExpRunStatus status =
|
||||
ExecuteRegExpImpl(cx, res, *shared, reobj, input, chars, length, lastIndex, conduit);
|
||||
ExecuteRegExpImpl(cx, res, *shared, input, chars, length, lastIndex, conduit);
|
||||
|
||||
if (status == RegExpRunStatus_Error)
|
||||
return false;
|
||||
@ -580,7 +580,7 @@ js::ExecuteRegExp(JSContext *cx, HandleObject regexp, HandleString string, Match
|
||||
/* Steps 8-21. */
|
||||
size_t lastIndexInt(i);
|
||||
RegExpRunStatus status =
|
||||
ExecuteRegExpImpl(cx, res, *re, *reobj, stableInput, chars, length, &lastIndexInt, matches);
|
||||
ExecuteRegExpImpl(cx, res, *re, stableInput, chars, length, &lastIndexInt, matches);
|
||||
|
||||
if (status == RegExpRunStatus_Error)
|
||||
return RegExpRunStatus_Error;
|
||||
|
@ -339,7 +339,6 @@ DeclMarkerImpl(Object, DebugScopeObject)
|
||||
DeclMarkerImpl(Object, GlobalObject)
|
||||
DeclMarkerImpl(Object, JSObject)
|
||||
DeclMarkerImpl(Object, JSFunction)
|
||||
DeclMarkerImpl(Object, RegExpObject)
|
||||
DeclMarkerImpl(Object, ScopeObject)
|
||||
DeclMarkerImpl(Script, JSScript)
|
||||
DeclMarkerImpl(Shape, Shape)
|
||||
|
@ -97,7 +97,6 @@ DeclMarker(Object, DebugScopeObject)
|
||||
DeclMarker(Object, GlobalObject)
|
||||
DeclMarker(Object, JSObject)
|
||||
DeclMarker(Object, JSFunction)
|
||||
DeclMarker(Object, RegExpObject)
|
||||
DeclMarker(Object, ScopeObject)
|
||||
DeclMarker(Script, JSScript)
|
||||
DeclMarker(Shape, Shape)
|
||||
|
@ -562,10 +562,8 @@ AutoGCRooter::trace(JSTracer *trc)
|
||||
}
|
||||
|
||||
case REGEXPSTATICS: {
|
||||
/*
|
||||
RegExpStatics::AutoRooter *rooter = static_cast<RegExpStatics::AutoRooter *>(this);
|
||||
rooter->trace(trc);
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
@ -646,15 +644,14 @@ Shape::Range::AutoRooter::trace(JSTracer *trc)
|
||||
void
|
||||
RegExpStatics::AutoRooter::trace(JSTracer *trc)
|
||||
{
|
||||
if (statics->regexp)
|
||||
MarkObjectRoot(trc, reinterpret_cast<JSObject**>(&statics->regexp),
|
||||
"RegExpStatics::AutoRooter regexp");
|
||||
if (statics->matchesInput)
|
||||
MarkStringRoot(trc, reinterpret_cast<JSString**>(&statics->matchesInput),
|
||||
"RegExpStatics::AutoRooter matchesInput");
|
||||
if (statics->pendingInput)
|
||||
MarkStringRoot(trc, reinterpret_cast<JSString**>(&statics->pendingInput),
|
||||
"RegExpStatics::AutoRooter pendingInput");
|
||||
if (statics->regexp.initialized())
|
||||
statics->regexp->trace(trc);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -405,12 +405,6 @@ RegExpShared::~RegExpShared()
|
||||
js_delete<BytecodePattern>(bytecode);
|
||||
}
|
||||
|
||||
void
|
||||
RegExpShared::trace(JSTracer *trc)
|
||||
{
|
||||
MarkStringUnbarriered(trc, &source, "regexpshared source");
|
||||
}
|
||||
|
||||
void
|
||||
RegExpShared::reportYarrError(JSContext *cx, TokenStream *ts, ErrorCode error)
|
||||
{
|
||||
@ -651,6 +645,18 @@ RegExpCompartment::RegExpCompartment(JSRuntime *rt)
|
||||
RegExpCompartment::~RegExpCompartment()
|
||||
{
|
||||
JS_ASSERT(map_.empty());
|
||||
|
||||
/*
|
||||
* RegExpStatics may have prevented a single RegExpShared from
|
||||
* being collected during RegExpCompartment::sweep().
|
||||
*/
|
||||
if (!inUse_.empty()) {
|
||||
PendingSet::Enum e(inUse_);
|
||||
RegExpShared *shared = e.front();
|
||||
JS_ASSERT(shared->activeUseCount == 0);
|
||||
js_delete(shared);
|
||||
e.removeFront();
|
||||
}
|
||||
JS_ASSERT(inUse_.empty());
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,8 @@
|
||||
#include "jscntxt.h"
|
||||
#include "jsobj.h"
|
||||
|
||||
#include "gc/Barrier.h"
|
||||
#include "gc/Marking.h"
|
||||
#include "js/TemplateLib.h"
|
||||
#include "vm/MatchPairs.h"
|
||||
|
||||
@ -120,11 +122,12 @@ class RegExpShared
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Source to the RegExp. The RegExpShared must either be protected by a
|
||||
* RegExpGuard, which handles rooting for stacky RegExpShareds,
|
||||
* or trace() must be explicitly called during marking.
|
||||
* Source to the RegExp, for lazy compilation.
|
||||
* The source must be rooted while activeUseCount is non-zero
|
||||
* via RegExpGuard, RegExpHeapGuard, or explicit calls to trace().
|
||||
*/
|
||||
JSAtom * source;
|
||||
|
||||
RegExpFlag flags;
|
||||
unsigned parenCount;
|
||||
|
||||
@ -149,7 +152,10 @@ class RegExpShared
|
||||
RegExpShared(JSRuntime *rt, JSAtom *source, RegExpFlag flags);
|
||||
~RegExpShared();
|
||||
|
||||
void trace(JSTracer *trc);
|
||||
/* Explicit trace function for use by the RegExpStatics and JITs. */
|
||||
void trace(JSTracer *trc) {
|
||||
MarkStringUnbarriered(trc, &source, "regexpshared source");
|
||||
}
|
||||
|
||||
/* Static functions to expose some Yarr logic. */
|
||||
static inline bool isJITRuntimeEnabled(JSContext *cx);
|
||||
@ -222,17 +228,58 @@ class RegExpGuard
|
||||
re_->incRef();
|
||||
}
|
||||
|
||||
~RegExpGuard() {
|
||||
if (re_)
|
||||
re_->decRef();
|
||||
}
|
||||
~RegExpGuard() { release(); }
|
||||
|
||||
public:
|
||||
void init(RegExpShared &re) {
|
||||
JS_ASSERT(!re_);
|
||||
JS_ASSERT(!initialized());
|
||||
re_ = &re;
|
||||
re_->incRef();
|
||||
source_ = re.source;
|
||||
source_ = re_->source;
|
||||
}
|
||||
void release() {
|
||||
if (re_) {
|
||||
re_->decRef();
|
||||
re_ = NULL;
|
||||
source_ = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool initialized() const { return !!re_; }
|
||||
RegExpShared *re() const { JS_ASSERT(initialized()); return re_; }
|
||||
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) { }
|
||||
RegExpHeapGuard(RegExpShared &re) { init(re); }
|
||||
~RegExpHeapGuard() { release(); }
|
||||
|
||||
public:
|
||||
void init(RegExpShared &re) {
|
||||
JS_ASSERT(!initialized());
|
||||
re_ = &re;
|
||||
re_->incRef();
|
||||
}
|
||||
void release() {
|
||||
if (re_) {
|
||||
re_->decRef();
|
||||
re_ = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void trace(JSTracer *trc) {
|
||||
if (initialized())
|
||||
re_->trace(trc);
|
||||
}
|
||||
|
||||
bool initialized() const { return !!re_; }
|
||||
@ -246,9 +293,12 @@ class RegExpCompartment
|
||||
struct Key {
|
||||
JSAtom *atom;
|
||||
uint16_t flag;
|
||||
|
||||
Key() {}
|
||||
Key(JSAtom *atom, RegExpFlag flag)
|
||||
: atom(atom), flag(flag) {}
|
||||
: atom(atom), flag(flag)
|
||||
{ }
|
||||
|
||||
typedef Key Lookup;
|
||||
static HashNumber hash(const Lookup &l) {
|
||||
return DefaultHasher<JSAtom *>::hash(l.atom) ^ (l.flag << 1);
|
||||
|
@ -27,15 +27,6 @@ SizeOfRegExpStaticsData(const JSObject *obj, JSMallocSizeOfFun mallocSizeOf)
|
||||
return mallocSizeOf(obj->getPrivate());
|
||||
}
|
||||
|
||||
inline
|
||||
RegExpStatics::RegExpStatics()
|
||||
: pendingLazyEvaluation(false),
|
||||
bufferLink(NULL),
|
||||
copied(false)
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
inline bool
|
||||
RegExpStatics::createDependent(JSContext *cx, size_t start, size_t end, Value *out)
|
||||
{
|
||||
@ -231,15 +222,20 @@ RegExpStatics::copyTo(RegExpStatics &dst)
|
||||
if (!pendingLazyEvaluation)
|
||||
dst.matches.initArrayFrom(matches);
|
||||
|
||||
if (regexp.initialized())
|
||||
dst.regexp.init(*regexp);
|
||||
else
|
||||
dst.regexp.release();
|
||||
|
||||
dst.matchesInput = matchesInput;
|
||||
dst.regexp = regexp;
|
||||
dst.lastIndex = lastIndex;
|
||||
dst.pendingInput = pendingInput;
|
||||
dst.flags = flags;
|
||||
dst.pendingLazyEvaluation = pendingLazyEvaluation;
|
||||
|
||||
JS_ASSERT_IF(pendingLazyEvaluation, regexp);
|
||||
JS_ASSERT_IF(pendingLazyEvaluation, regexp.initialized());
|
||||
JS_ASSERT_IF(pendingLazyEvaluation, matchesInput);
|
||||
JS_ASSERT(regexp.initialized() == dst.regexp.initialized());
|
||||
}
|
||||
|
||||
inline void
|
||||
@ -261,17 +257,20 @@ RegExpStatics::restore()
|
||||
|
||||
inline void
|
||||
RegExpStatics::updateLazily(JSContext *cx, JSLinearString *input,
|
||||
RegExpObject *regexp, size_t lastIndex)
|
||||
RegExpShared *shared, size_t lastIndex)
|
||||
{
|
||||
JS_ASSERT(input && regexp);
|
||||
JS_ASSERT(input && shared);
|
||||
aboutToWrite();
|
||||
|
||||
BarrieredSetPair<JSString, JSLinearString>(cx->compartment,
|
||||
pendingInput, input,
|
||||
matchesInput, input);
|
||||
pendingLazyEvaluation = true;
|
||||
this->regexp = regexp;
|
||||
if (regexp.initialized())
|
||||
regexp.release();
|
||||
regexp.init(*shared);
|
||||
|
||||
this->lastIndex = lastIndex;
|
||||
pendingLazyEvaluation = true;
|
||||
}
|
||||
|
||||
inline bool
|
||||
@ -282,7 +281,7 @@ RegExpStatics::updateFromMatchPairs(JSContext *cx, JSLinearString *input, MatchP
|
||||
|
||||
/* Unset all lazy state. */
|
||||
pendingLazyEvaluation = false;
|
||||
this->regexp = NULL;
|
||||
this->regexp.release();
|
||||
this->lastIndex = size_t(-1);
|
||||
|
||||
BarrieredSetPair<JSString, JSLinearString>(cx->compartment,
|
||||
@ -301,11 +300,14 @@ inline void
|
||||
RegExpStatics::clear()
|
||||
{
|
||||
aboutToWrite();
|
||||
flags = RegExpFlag(0);
|
||||
pendingInput = NULL;
|
||||
pendingLazyEvaluation = false;
|
||||
matchesInput = NULL;
|
||||
|
||||
matches.forgetArray();
|
||||
matchesInput = NULL;
|
||||
regexp.release();
|
||||
lastIndex = size_t(-1);
|
||||
pendingInput = NULL;
|
||||
flags = RegExpFlag(0);
|
||||
pendingLazyEvaluation = false;
|
||||
}
|
||||
|
||||
inline void
|
||||
@ -363,8 +365,9 @@ RegExpStatics::checkInvariants()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (pendingLazyEvaluation) {
|
||||
JS_ASSERT(regexp);
|
||||
JS_ASSERT(regexp.initialized());
|
||||
JS_ASSERT(pendingInput);
|
||||
JS_ASSERT(lastIndex != size_t(-1));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -74,7 +74,7 @@ RegExpStatics::executeLazy(JSContext *cx)
|
||||
if (!pendingLazyEvaluation)
|
||||
return true;
|
||||
|
||||
JS_ASSERT(regexp);
|
||||
JS_ASSERT(regexp.initialized());
|
||||
JS_ASSERT(matchesInput);
|
||||
JS_ASSERT(lastIndex != size_t(-1));
|
||||
|
||||
@ -87,17 +87,14 @@ RegExpStatics::executeLazy(JSContext *cx)
|
||||
StableCharPtr chars(matchesInput->chars(), length);
|
||||
|
||||
/* Execute the full regular expression. */
|
||||
RegExpGuard shared(cx);
|
||||
if (!regexp->getShared(cx, &shared))
|
||||
return false;
|
||||
|
||||
RegExpRunStatus status = shared->execute(cx, chars, length, &this->lastIndex, this->matches);
|
||||
RegExpRunStatus status = regexp->execute(cx, chars, length, &this->lastIndex, this->matches);
|
||||
if (status == RegExpRunStatus_Error)
|
||||
return false;
|
||||
|
||||
/* Unset lazy state and remove rooted values that now have no use. */
|
||||
pendingLazyEvaluation = false;
|
||||
regexp = NULL;
|
||||
regexp.release();
|
||||
lastIndex = size_t(-1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "js/Vector.h"
|
||||
|
||||
#include "vm/MatchPairs.h"
|
||||
#include "vm/RegExpObject.h"
|
||||
|
||||
namespace js {
|
||||
|
||||
@ -27,7 +28,7 @@ class RegExpStatics
|
||||
HeapPtr<JSLinearString> matchesInput;
|
||||
|
||||
/* The previous RegExp input, used to resolve lazy state. */
|
||||
HeapPtr<RegExpObject> regexp;
|
||||
RegExpHeapGuard regexp;
|
||||
size_t lastIndex;
|
||||
|
||||
/* The latest RegExp input, set before execution. */
|
||||
@ -44,6 +45,10 @@ class RegExpStatics
|
||||
RegExpStatics *bufferLink;
|
||||
bool copied;
|
||||
|
||||
public:
|
||||
RegExpStatics() : bufferLink(NULL), copied(false) { clear(); }
|
||||
static JSObject *create(JSContext *cx, GlobalObject *parent);
|
||||
|
||||
private:
|
||||
bool executeLazy(JSContext *cx);
|
||||
|
||||
@ -80,14 +85,9 @@ class RegExpStatics
|
||||
friend class PreserveRegExpStatics;
|
||||
|
||||
public:
|
||||
inline RegExpStatics();
|
||||
|
||||
static JSObject *create(JSContext *cx, GlobalObject *parent);
|
||||
|
||||
/* Mutators. */
|
||||
|
||||
inline void updateLazily(JSContext *cx, JSLinearString *input,
|
||||
RegExpObject *regexp, size_t lastIndex);
|
||||
RegExpShared *shared, size_t lastIndex);
|
||||
inline bool updateFromMatchPairs(JSContext *cx, JSLinearString *input, MatchPairs &newPairs);
|
||||
inline void setMultiline(JSContext *cx, bool enabled);
|
||||
|
||||
@ -120,12 +120,16 @@ class RegExpStatics
|
||||
}
|
||||
|
||||
void mark(JSTracer *trc) {
|
||||
if (regexp)
|
||||
gc::MarkObject(trc, ®exp, "res->regexp");
|
||||
/*
|
||||
* Changes to this function must also be reflected in
|
||||
* RegExpStatics::AutoRooter::trace().
|
||||
*/
|
||||
if (pendingInput)
|
||||
MarkString(trc, &pendingInput, "res->pendingInput");
|
||||
if (matchesInput)
|
||||
MarkString(trc, &matchesInput, "res->matchesInput");
|
||||
if (regexp.initialized())
|
||||
regexp->trace(trc);
|
||||
}
|
||||
|
||||
/* Value creators. */
|
||||
|
Loading…
Reference in New Issue
Block a user