Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (87326 => 87327)
--- trunk/Source/_javascript_Core/ChangeLog 2011-05-25 22:46:51 UTC (rev 87326)
+++ trunk/Source/_javascript_Core/ChangeLog 2011-05-25 22:49:56 UTC (rev 87327)
@@ -1,3 +1,30 @@
+2011-05-25 Oliver Hunt <[email protected]>
+
+ Reviewed by Geoffrey Garen.
+
+ Generate regexp code lazily
+ https://bugs.webkit.org/show_bug.cgi?id=61476
+
+ RegExp construction now simply validates the RegExp, it does
+ not perform actual codegen.
+
+ * runtime/RegExp.cpp:
+ (JSC::RegExp::RegExp):
+ (JSC::RegExp::recompile):
+ (JSC::RegExp::compile):
+ (JSC::RegExp::match):
+ * runtime/RegExp.h:
+ (JSC::RegExp::recompileIfNecessary):
+ * runtime/RegExpConstructor.h:
+ (JSC::RegExpConstructor::performMatch):
+ * runtime/RegExpObject.cpp:
+ (JSC::RegExpObject::match):
+ * runtime/StringPrototype.cpp:
+ (JSC::stringProtoFuncReplace):
+ (JSC::stringProtoFuncMatch):
+ (JSC::stringProtoFuncSearch):
+ (JSC::stringProtoFuncSplit):
+
2011-05-24 Geoffrey Garen <[email protected]>
Reviewed by Geoffrey Garen.
Modified: trunk/Source/_javascript_Core/runtime/RegExp.cpp (87326 => 87327)
--- trunk/Source/_javascript_Core/runtime/RegExp.cpp 2011-05-25 22:46:51 UTC (rev 87326)
+++ trunk/Source/_javascript_Core/runtime/RegExp.cpp 2011-05-25 22:49:56 UTC (rev 87327)
@@ -73,8 +73,9 @@
OwnPtr<Yarr::BytecodePattern> m_regExpBytecode;
};
-inline RegExp::RegExp(JSGlobalData* globalData, const UString& patternString, RegExpFlags flags)
- : m_patternString(patternString)
+inline RegExp::RegExp(JSGlobalData*, const UString& patternString, RegExpFlags flags)
+ : m_state(NotCompiled)
+ , m_patternString(patternString)
, m_flags(flags)
, m_constructionError(0)
, m_numSubpatterns(0)
@@ -82,9 +83,12 @@
, m_rtMatchCallCount(0)
, m_rtMatchFoundCount(0)
#endif
- , m_representation(adoptPtr(new RegExpRepresentation))
{
- m_state = compile(globalData);
+ Yarr::YarrPattern pattern(m_patternString, ignoreCase(), multiline(), &m_constructionError);
+ if (m_constructionError)
+ m_state = ParseError;
+ else
+ m_numSubpatterns = pattern.m_numSubpatterns;
}
RegExp::~RegExp()
@@ -100,37 +104,42 @@
return res.release();
}
-RegExp::RegExpState RegExp::compile(JSGlobalData* globalData)
+void RegExp::compile(JSGlobalData* globalData)
{
+ ASSERT(m_state == NotCompiled);
+ m_representation = adoptPtr(new RegExpRepresentation);
Yarr::YarrPattern pattern(m_patternString, ignoreCase(), multiline(), &m_constructionError);
- if (m_constructionError)
- return ParseError;
+ if (m_constructionError) {
+ ASSERT_NOT_REACHED();
+ m_state = ParseError;
+ return;
+ }
- m_numSubpatterns = pattern.m_numSubpatterns;
+ ASSERT(m_numSubpatterns == pattern.m_numSubpatterns);
- RegExpState res = ByteCode;
+ m_state = ByteCode;
#if ENABLE(YARR_JIT)
if (!pattern.m_containsBackreferences && globalData->canUseJIT()) {
Yarr::jitCompile(pattern, globalData, m_representation->m_regExpJITCode);
#if ENABLE(YARR_JIT_DEBUG)
if (!m_representation->m_regExpJITCode.isFallBack())
- res = JITCode;
+ m_state = JITCode;
else
- res = ByteCode;
+ m_state = ByteCode;
#else
- if (!m_representation->m_regExpJITCode.isFallBack())
- return JITCode;
+ if (!m_representation->m_regExpJITCode.isFallBack()) {
+ m_state = JITCode;
+ return;
+ }
#endif
}
#endif
m_representation->m_regExpBytecode = Yarr::byteCompile(pattern, &globalData->m_regExpAllocator);
-
- return res;
}
-int RegExp::match(const UString& s, int startOffset, Vector<int, 32>* ovector)
+int RegExp::match(JSGlobalData& globalData, const UString& s, int startOffset, Vector<int, 32>* ovector)
{
if (startOffset < 0)
startOffset = 0;
@@ -143,6 +152,7 @@
return -1;
if (m_state != ParseError) {
+ compileIfNecessary(globalData);
int offsetVectorSize = (m_numSubpatterns + 1) * 2;
int* offsetVector;
Vector<int, 32> nonReturnedOvector;
Modified: trunk/Source/_javascript_Core/runtime/RegExp.h (87326 => 87327)
--- trunk/Source/_javascript_Core/runtime/RegExp.h 2011-05-25 22:46:51 UTC (rev 87326)
+++ trunk/Source/_javascript_Core/runtime/RegExp.h 2011-05-25 22:49:56 UTC (rev 87327)
@@ -49,7 +49,7 @@
bool isValid() const { return !m_constructionError && m_flags != InvalidFlags; }
const char* errorMessage() const { return m_constructionError; }
- int match(const UString&, int startOffset, Vector<int, 32>* ovector = 0);
+ int match(JSGlobalData&, const UString&, int startOffset, Vector<int, 32>* ovector = 0);
unsigned numSubpatterns() const { return m_numSubpatterns; }
#if ENABLE(REGEXP_TRACING)
@@ -62,10 +62,17 @@
enum RegExpState {
ParseError,
JITCode,
- ByteCode
+ ByteCode,
+ NotCompiled
} m_state;
- RegExpState compile(JSGlobalData*);
+ void compile(JSGlobalData*);
+ void compileIfNecessary(JSGlobalData& globalData)
+ {
+ if (m_representation)
+ return;
+ compile(&globalData);
+ }
#if ENABLE(YARR_JIT_DEBUG)
void matchCompareWithInterpreter(const UString&, int startOffset, int* offsetVector, int jitResult);
Modified: trunk/Source/_javascript_Core/runtime/RegExpConstructor.h (87326 => 87327)
--- trunk/Source/_javascript_Core/runtime/RegExpConstructor.h 2011-05-25 22:46:51 UTC (rev 87326)
+++ trunk/Source/_javascript_Core/runtime/RegExpConstructor.h 2011-05-25 22:49:56 UTC (rev 87327)
@@ -70,7 +70,7 @@
static const ClassInfo s_info;
- void performMatch(RegExp*, const UString&, int startOffset, int& position, int& length, int** ovector = 0);
+ void performMatch(JSGlobalData&, RegExp*, const UString&, int startOffset, int& position, int& length, int** ovector = 0);
JSObject* arrayOfMatches(ExecState*) const;
void setInput(const UString&);
@@ -109,9 +109,9 @@
_expression_ matching through the performMatch function. We use cached results to calculate,
e.g., RegExp.lastMatch and RegExp.leftParen.
*/
- ALWAYS_INLINE void RegExpConstructor::performMatch(RegExp* r, const UString& s, int startOffset, int& position, int& length, int** ovector)
+ ALWAYS_INLINE void RegExpConstructor::performMatch(JSGlobalData& globalData, RegExp* r, const UString& s, int startOffset, int& position, int& length, int** ovector)
{
- position = r->match(s, startOffset, &d->tempOvector());
+ position = r->match(globalData, s, startOffset, &d->tempOvector());
if (ovector)
*ovector = d->tempOvector().data();
Modified: trunk/Source/_javascript_Core/runtime/RegExpObject.cpp (87326 => 87327)
--- trunk/Source/_javascript_Core/runtime/RegExpObject.cpp 2011-05-25 22:46:51 UTC (rev 87326)
+++ trunk/Source/_javascript_Core/runtime/RegExpObject.cpp 2011-05-25 22:49:56 UTC (rev 87327)
@@ -144,11 +144,11 @@
{
RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor();
UString input = exec->argument(0).toString(exec);
-
+ JSGlobalData* globalData = &exec->globalData();
if (!regExp()->global()) {
int position;
int length;
- regExpConstructor->performMatch(d->regExp.get(), input, 0, position, length);
+ regExpConstructor->performMatch(*globalData, d->regExp.get(), input, 0, position, length);
return position >= 0;
}
@@ -171,7 +171,7 @@
int position;
int length = 0;
- regExpConstructor->performMatch(d->regExp.get(), input, lastIndex, position, length);
+ regExpConstructor->performMatch(*globalData, d->regExp.get(), input, lastIndex, position, length);
if (position < 0) {
setLastIndex(0);
return false;
Modified: trunk/Source/_javascript_Core/runtime/StringPrototype.cpp (87326 => 87327)
--- trunk/Source/_javascript_Core/runtime/StringPrototype.cpp 2011-05-25 22:46:51 UTC (rev 87326)
+++ trunk/Source/_javascript_Core/runtime/StringPrototype.cpp 2011-05-25 22:49:56 UTC (rev 87327)
@@ -300,6 +300,7 @@
JSString* sourceVal = thisValue.toThisJSString(exec);
JSValue pattern = exec->argument(0);
JSValue replacement = exec->argument(1);
+ JSGlobalData* globalData = &exec->globalData();
UString replacementString;
CallData callData;
@@ -335,7 +336,7 @@
int matchIndex;
int matchLen = 0;
int* ovector;
- regExpConstructor->performMatch(reg, source, startPosition, matchIndex, matchLen, &ovector);
+ regExpConstructor->performMatch(*globalData, reg, source, startPosition, matchIndex, matchLen, &ovector);
if (matchIndex < 0)
break;
@@ -380,7 +381,7 @@
int matchIndex;
int matchLen = 0;
int* ovector;
- regExpConstructor->performMatch(reg, source, startPosition, matchIndex, matchLen, &ovector);
+ regExpConstructor->performMatch(*globalData, reg, source, startPosition, matchIndex, matchLen, &ovector);
if (matchIndex < 0)
break;
@@ -601,6 +602,7 @@
if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
return throwVMTypeError(exec);
UString s = thisValue.toThisString(exec);
+ JSGlobalData* globalData = &exec->globalData();
JSValue a0 = exec->argument(0);
@@ -618,7 +620,7 @@
RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor();
int pos;
int matchLength = 0;
- regExpConstructor->performMatch(reg.get(), s, 0, pos, matchLength);
+ regExpConstructor->performMatch(*globalData, reg.get(), s, 0, pos, matchLength);
if (!(reg->global())) {
// case without 'g' flag is handled like RegExp.prototype.exec
if (pos < 0)
@@ -631,7 +633,7 @@
while (pos >= 0) {
list.append(jsSubstring(exec, s, pos, matchLength));
pos += matchLength == 0 ? 1 : matchLength;
- regExpConstructor->performMatch(reg.get(), s, pos, pos, matchLength);
+ regExpConstructor->performMatch(*globalData, reg.get(), s, pos, pos, matchLength);
}
if (list.isEmpty()) {
// if there are no matches at all, it's important to return
@@ -649,6 +651,7 @@
if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
return throwVMTypeError(exec);
UString s = thisValue.toThisString(exec);
+ JSGlobalData* globalData = &exec->globalData();
JSValue a0 = exec->argument(0);
@@ -666,7 +669,7 @@
RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor();
int pos;
int matchLength = 0;
- regExpConstructor->performMatch(reg.get(), s, 0, pos, matchLength);
+ regExpConstructor->performMatch(*globalData, reg.get(), s, 0, pos, matchLength);
return JSValue::encode(jsNumber(pos));
}
@@ -703,6 +706,7 @@
if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
return throwVMTypeError(exec);
UString s = thisValue.toThisString(exec);
+ JSGlobalData* globalData = &exec->globalData();
JSValue a0 = exec->argument(0);
JSValue a1 = exec->argument(1);
@@ -713,14 +717,14 @@
unsigned limit = a1.isUndefined() ? 0xFFFFFFFFU : a1.toUInt32(exec);
if (a0.inherits(&RegExpObject::s_info)) {
RegExp* reg = asRegExpObject(a0)->regExp();
- if (s.isEmpty() && reg->match(s, 0) >= 0) {
+ if (s.isEmpty() && reg->match(*globalData, s, 0) >= 0) {
// empty string matched by regexp -> empty array
return JSValue::encode(result);
}
unsigned pos = 0;
while (i != limit && pos < s.length()) {
Vector<int, 32> ovector;
- int mpos = reg->match(s, pos, &ovector);
+ int mpos = reg->match(*globalData, s, pos, &ovector);
if (mpos < 0)
break;
int mlen = ovector[1] - ovector[0];