mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-14 13:55:43 +00:00
Bug 965712: Part 1 - Use our string matching logic for regexps when possible, r=luke
This commit is contained in:
parent
9f228ac8a9
commit
1eddd2ecf5
2
js/src/jit-test/tests/ion/bug965712.js
Normal file
2
js/src/jit-test/tests/ion/bug965712.js
Normal file
@ -0,0 +1,2 @@
|
||||
var result = "D1D1D1D1D1D1D1D1D1D1".replace(/d1/ig,1);
|
||||
assertEq(result, "1111111111");
|
@ -1173,6 +1173,13 @@ js::StringHasPattern(const jschar *text, uint32_t textlen,
|
||||
return StringMatch(text, textlen, pat, patlen) != -1;
|
||||
}
|
||||
|
||||
int
|
||||
js::StringFindPattern(const jschar *text, uint32_t textlen,
|
||||
const jschar *pat, uint32_t patlen)
|
||||
{
|
||||
return StringMatch(text, textlen, pat, patlen);
|
||||
}
|
||||
|
||||
// When an algorithm does not need a string represented as a single linear
|
||||
// array of characters, this range utility may be used to traverse the string a
|
||||
// sequence of linear arrays of characters. This avoids flattening ropes.
|
||||
@ -1737,6 +1744,12 @@ HasRegExpMetaChars(const jschar *chars, size_t length)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
js::StringHasRegExpMetaChars(const jschar *chars, size_t length)
|
||||
{
|
||||
return HasRegExpMetaChars(chars, length);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
/*
|
||||
|
@ -213,6 +213,13 @@ extern bool
|
||||
StringHasPattern(const jschar *text, uint32_t textlen,
|
||||
const jschar *pat, uint32_t patlen);
|
||||
|
||||
extern int
|
||||
StringFindPattern(const jschar *text, uint32_t textlen,
|
||||
const jschar *pat, uint32_t patlen);
|
||||
|
||||
extern bool
|
||||
StringHasRegExpMetaChars(const jschar *chars, size_t length);
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
extern size_t
|
||||
|
@ -8,6 +8,8 @@
|
||||
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
|
||||
#include "jsstr.h"
|
||||
|
||||
#include "frontend/TokenStream.h"
|
||||
#include "vm/MatchPairs.h"
|
||||
#include "vm/RegExpStatics.h"
|
||||
@ -377,7 +379,7 @@ RegExpObject::toString(JSContext *cx) const
|
||||
/* RegExpShared */
|
||||
|
||||
RegExpShared::RegExpShared(JSAtom *source, RegExpFlag flags, uint64_t gcNumber)
|
||||
: source(source), flags(flags), parenCount(0),
|
||||
: source(source), flags(flags), parenCount(0), canStringMatch(false),
|
||||
#if ENABLE_YARR_JIT
|
||||
codeBlock(),
|
||||
#endif
|
||||
@ -438,6 +440,9 @@ RegExpShared::checkSyntax(ExclusiveContext *cx, TokenStream *tokenStream, JSLine
|
||||
bool
|
||||
RegExpShared::compile(JSContext *cx, bool matchOnly)
|
||||
{
|
||||
TraceLogger *logger = TraceLoggerForMainThread(cx->runtime());
|
||||
AutoTraceLog logCompile(logger, TraceLogger::YarrCompile);
|
||||
|
||||
if (!sticky())
|
||||
return compile(cx, *source, matchOnly);
|
||||
|
||||
@ -466,6 +471,12 @@ RegExpShared::compile(JSContext *cx, bool matchOnly)
|
||||
bool
|
||||
RegExpShared::compile(JSContext *cx, JSLinearString &pattern, bool matchOnly)
|
||||
{
|
||||
if (!ignoreCase() && !StringHasRegExpMetaChars(pattern.chars(), pattern.length())) {
|
||||
canStringMatch = true;
|
||||
parenCount = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Parse the pattern. */
|
||||
ErrorCode yarrError;
|
||||
YarrPattern yarrPattern(pattern, ignoreCase(), multiline(), &yarrError);
|
||||
@ -507,7 +518,7 @@ RegExpShared::compile(JSContext *cx, JSLinearString &pattern, bool matchOnly)
|
||||
bool
|
||||
RegExpShared::compileIfNecessary(JSContext *cx)
|
||||
{
|
||||
if (hasCode() || hasBytecode())
|
||||
if (hasCode() || hasBytecode() || canStringMatch)
|
||||
return true;
|
||||
return compile(cx, false);
|
||||
}
|
||||
@ -515,7 +526,7 @@ RegExpShared::compileIfNecessary(JSContext *cx)
|
||||
bool
|
||||
RegExpShared::compileMatchOnlyIfNecessary(JSContext *cx)
|
||||
{
|
||||
if (hasMatchOnlyCode() || hasBytecode())
|
||||
if (hasMatchOnlyCode() || hasBytecode() || canStringMatch)
|
||||
return true;
|
||||
return compile(cx, true);
|
||||
}
|
||||
@ -526,12 +537,9 @@ RegExpShared::execute(JSContext *cx, const jschar *chars, size_t length,
|
||||
{
|
||||
TraceLogger *logger = TraceLoggerForMainThread(cx->runtime());
|
||||
|
||||
{
|
||||
/* Compile the code at point-of-use. */
|
||||
AutoTraceLog logCompile(logger, TraceLogger::YarrCompile);
|
||||
if (!compileIfNecessary(cx))
|
||||
return RegExpRunStatus_Error;
|
||||
}
|
||||
/* Compile the code at point-of-use. */
|
||||
if (!compileIfNecessary(cx))
|
||||
return RegExpRunStatus_Error;
|
||||
|
||||
/* Ensure sufficient memory for output vector. */
|
||||
if (!matches.initArray(pairCount()))
|
||||
@ -555,6 +563,20 @@ RegExpShared::execute(JSContext *cx, const jschar *chars, size_t length,
|
||||
unsigned *outputBuf = matches.rawBuf();
|
||||
unsigned result;
|
||||
|
||||
if (canStringMatch) {
|
||||
int res = StringFindPattern(chars+start, length-start, source->chars(), source->length());
|
||||
if (res == -1)
|
||||
return RegExpRunStatus_Success_NotFound;
|
||||
|
||||
outputBuf[0] = res + start;
|
||||
outputBuf[1] = outputBuf[0] + source->length();
|
||||
|
||||
matches.displace(displacement);
|
||||
matches.checkAgainst(origLength);
|
||||
*lastIndex = matches[0].limit;
|
||||
return RegExpRunStatus_Success;
|
||||
}
|
||||
|
||||
#if ENABLE_YARR_JIT
|
||||
if (codeBlock.isFallBack()) {
|
||||
AutoTraceLog logInterpret(logger, TraceLogger::YarrInterpret);
|
||||
@ -590,12 +612,9 @@ RegExpShared::executeMatchOnly(JSContext *cx, const jschar *chars, size_t length
|
||||
{
|
||||
TraceLogger *logger = js::TraceLoggerForMainThread(cx->runtime());
|
||||
|
||||
{
|
||||
/* Compile the code at point-of-use. */
|
||||
AutoTraceLog logCompile(logger, TraceLogger::YarrCompile);
|
||||
if (!compileMatchOnlyIfNecessary(cx))
|
||||
return RegExpRunStatus_Error;
|
||||
}
|
||||
/* Compile the code at point-of-use. */
|
||||
if (!compileMatchOnlyIfNecessary(cx))
|
||||
return RegExpRunStatus_Error;
|
||||
|
||||
#ifdef DEBUG
|
||||
const size_t origLength = length;
|
||||
@ -610,6 +629,17 @@ RegExpShared::executeMatchOnly(JSContext *cx, const jschar *chars, size_t length
|
||||
start = 0;
|
||||
}
|
||||
|
||||
if (canStringMatch) {
|
||||
int res = StringFindPattern(chars+start, length-start, source->chars(), source->length());
|
||||
if (res == -1)
|
||||
return RegExpRunStatus_Success_NotFound;
|
||||
|
||||
match = MatchPair(res + start, res + start + source->length());
|
||||
match.displace(displacement);
|
||||
*lastIndex = match.limit;
|
||||
return RegExpRunStatus_Success;
|
||||
}
|
||||
|
||||
#if ENABLE_YARR_JIT
|
||||
if (!codeBlock.isFallBack()) {
|
||||
AutoTraceLog logJIT(logger, TraceLogger::YarrJIT);
|
||||
|
@ -145,6 +145,7 @@ class RegExpShared
|
||||
|
||||
RegExpFlag flags;
|
||||
unsigned parenCount;
|
||||
bool canStringMatch;
|
||||
|
||||
#if ENABLE_YARR_JIT
|
||||
/* Note: Native code is valid only if |codeBlock.isFallBack() == false|. */
|
||||
@ -204,7 +205,11 @@ class RegExpShared
|
||||
|
||||
/* Accessors */
|
||||
|
||||
size_t getParenCount() const { JS_ASSERT(isCompiled()); return parenCount; }
|
||||
size_t getParenCount() const {
|
||||
JS_ASSERT(isCompiled() || canStringMatch);
|
||||
return parenCount;
|
||||
}
|
||||
|
||||
void incRef() { activeUseCount++; }
|
||||
void decRef() { JS_ASSERT(activeUseCount > 0); activeUseCount--; }
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user