Bug 1644590: Add fast path for atom regexps r=jandem

We fill in the match pairs for atom regexps using an ABI call, then use the normal jit path for everything else (checking for errors, allocating results, etc...).

I also made a drive-by fix to remove the cx argument from RegExpShared::executeAtom, since we don't need it.

Differential Revision: https://phabricator.services.mozilla.com/D79001
This commit is contained in:
Iain Ireland 2020-06-10 15:11:45 +00:00
Родитель 2756eea4aa
Коммит 5c8dcb2c0a
4 изменённых файлов: 59 добавлений и 16 удалений

Просмотреть файл

@ -2182,7 +2182,8 @@ static bool PrepareAndExecuteRegExp(JSContext* cx, MacroAssembler& masm,
// execution finished successfully.
// Initialize MatchPairs::pairCount to 1. The correct value can only
// be determined after loading the RegExpShared.
// be determined after loading the RegExpShared. If the RegExpShared
// has Kind::Atom, this is the correct pairCount.
masm.store32(Imm32(1), pairCountAddress);
// Initialize MatchPairs::pairs pointer
@ -2202,6 +2203,33 @@ static bool PrepareAndExecuteRegExp(JSContext* cx, MacroAssembler& masm,
regexpReg);
masm.branchPtr(Assembler::Equal, regexpReg, ImmWord(0), failure);
// Handle Atom matches
Label notAtom, checkSuccess;
masm.branchPtr(Assembler::Equal,
Address(regexpReg, RegExpShared::offsetOfPatternAtom()),
ImmWord(0), &notAtom);
{
LiveGeneralRegisterSet regsToSave(GeneralRegisterSet::Volatile());
regsToSave.takeUnchecked(temp1);
regsToSave.takeUnchecked(temp2);
regsToSave.takeUnchecked(temp3);
masm.computeEffectiveAddress(matchPairsAddress, temp3);
masm.PushRegsInMask(regsToSave);
masm.setupUnalignedABICall(temp2);
masm.passABIArg(regexpReg);
masm.passABIArg(input);
masm.passABIArg(lastIndex);
masm.passABIArg(temp3);
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, ExecuteRegExpAtomRaw));
masm.storeCallInt32Result(temp1);
masm.PopRegsInMask(regsToSave);
masm.jump(&checkSuccess);
}
masm.bind(&notAtom);
// Don't handle regexps with too many capture pairs.
masm.load32(Address(regexpReg, RegExpShared::offsetOfPairCount()), temp2);
masm.branch32(Assembler::Above, temp2, Imm32(RegExpObject::MaxPairCount),
@ -2296,6 +2324,7 @@ static bool PrepareAndExecuteRegExp(JSContext* cx, MacroAssembler& masm,
#endif
Label success;
masm.bind(&checkSuccess);
masm.branch32(Assembler::Equal, temp1,
Imm32(RegExpRunStatus_Success_NotFound), notFound);
masm.branch32(Assembler::Equal, temp1, Imm32(RegExpRunStatus_Error), failure);

Просмотреть файл

@ -66,6 +66,7 @@ class MatchPairs {
void forgetArray() { pairs_ = nullptr; }
public:
void checkAgainst(size_t inputLength) {
#ifdef DEBUG
for (size_t i = 0; i < pairCount_; i++) {
@ -79,7 +80,6 @@ class MatchPairs {
#endif
}
public:
/* Querying functions in the style of RegExpStatics. */
bool empty() const { return pairCount_ == 0; }
size_t pairCount() const {

Просмотреть файл

@ -712,7 +712,7 @@ RegExpRunStatus RegExpShared::execute(JSContext* cx,
}
if (re->kind() == RegExpShared::Kind::Atom) {
return RegExpShared::executeAtom(cx, re, input, start, matches);
return RegExpShared::executeAtom(re, input, start, matches);
}
/*
@ -854,14 +854,9 @@ bool RegExpShared::markedForTierUp() const {
return ticks_ == 0;
}
/* static */
RegExpRunStatus RegExpShared::executeAtom(JSContext* cx,
MutableHandleRegExpShared re,
HandleLinearString input,
size_t start,
VectorMatchPairs* matches) {
static RegExpRunStatus ExecuteAtomImpl(RegExpShared* re, JSLinearString* input,
size_t start, MatchPairs* matches) {
MOZ_ASSERT(re->pairCount() == 1);
size_t length = input->length();
size_t searchLength = re->patternAtom()->length();
@ -876,8 +871,7 @@ RegExpRunStatus RegExpShared::executeAtom(JSContext* cx,
(*matches)[0].start = start;
(*matches)[0].limit = start + searchLength;
matches->checkAgainst(length);
matches->checkAgainst(input->length());
return RegExpRunStatus_Success;
}
@ -888,11 +882,25 @@ RegExpRunStatus RegExpShared::executeAtom(JSContext* cx,
(*matches)[0].start = res;
(*matches)[0].limit = res + searchLength;
matches->checkAgainst(length);
matches->checkAgainst(input->length());
return RegExpRunStatus_Success;
}
RegExpRunStatus js::ExecuteRegExpAtomRaw(RegExpShared* re,
JSLinearString* input, size_t start,
MatchPairs* matchPairs) {
AutoUnsafeCallWithABI unsafe;
return ExecuteAtomImpl(re, input, start, matchPairs);
}
/* static */
RegExpRunStatus RegExpShared::executeAtom(MutableHandleRegExpShared re,
HandleLinearString input,
size_t start,
VectorMatchPairs* matches) {
return ExecuteAtomImpl(re, input, start, matches);
}
size_t RegExpShared::sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) {
size_t n = 0;

Просмотреть файл

@ -152,8 +152,7 @@ class RegExpShared : public gc::TenuredCell {
static bool compileIfNecessary(JSContext* cx, MutableHandleRegExpShared res,
HandleLinearString input, CodeKind code);
static RegExpRunStatus executeAtom(JSContext* cx,
MutableHandleRegExpShared re,
static RegExpRunStatus executeAtom(MutableHandleRegExpShared re,
HandleLinearString input, size_t start,
VectorMatchPairs* matches);
@ -238,6 +237,10 @@ class RegExpShared : public gc::TenuredCell {
HeaderWithAtom::offsetOfPtr();
}
static size_t offsetOfPatternAtom() {
return offsetof(RegExpShared, patternAtom_);
}
static size_t offsetOfFlags() { return offsetof(RegExpShared, flags); }
static size_t offsetOfPairCount() {
@ -396,6 +399,9 @@ class RegExpRealm {
}
};
RegExpRunStatus ExecuteRegExpAtomRaw(RegExpShared* re, JSLinearString* input,
size_t start, MatchPairs* matchPairs);
} /* namespace js */
namespace JS {