Regexp matching should incur less call overhead
https://bugs.webkit.org/show_bug.cgi?id=155181
Reviewed by Geoffrey Garen.
Previously we had DFG/FTL code call into the DFGOperation, which then called in to
RegExpObject, which then called into createRegExpMatchesArray, which then called into
RegExp, which then called the code generated by Yarr.
Now we have DFG/FTL code call into the DFGOperation, which does all of the things and calls
into code generated by Yarr.
This is another tiny Octane/regexp speed-up.
* JavaScriptCore.xcodeproj/project.pbxproj:
* dfg/DFGOperations.cpp:
* runtime/RegExp.cpp:
(JSC::regExpFlags):
(JSC::RegExp::compile):
(JSC::RegExp::match):
(JSC::RegExp::compileMatchOnly):
(JSC::RegExp::deleteCode):
(JSC::RegExpFunctionalTestCollector::clearRegExp): Deleted.
(JSC::RegExp::compileIfNecessary): Deleted.
(JSC::RegExp::compileIfNecessaryMatchOnly): Deleted.
* runtime/RegExp.h:
* runtime/RegExpInlines.h: Added.
(JSC::RegExpFunctionalTestCollector::clearRegExp):
(JSC::RegExp::compileIfNecessary):
(JSC::RegExp::matchInline):
(JSC::RegExp::compileIfNecessaryMatchOnly):
* runtime/RegExpMatchesArray.cpp:
(JSC::createEmptyRegExpMatchesArray):
(JSC::createStructureImpl):
(JSC::tryCreateUninitializedRegExpMatchesArray): Deleted.
(JSC::createRegExpMatchesArray): Deleted.
* runtime/RegExpMatchesArray.h:
(JSC::tryCreateUninitializedRegExpMatchesArray):
(JSC::createRegExpMatchesArray):
* runtime/RegExpObject.cpp:
(JSC::RegExpObject::put):
(JSC::RegExpObject::exec):
(JSC::RegExpObject::match):
(JSC::getLastIndexAsUnsigned): Deleted.
* runtime/RegExpObject.h:
(JSC::RegExpObject::getLastIndex):
(JSC::RegExpObject::test):
(JSC::RegExpObject::testInline):
* runtime/RegExpObjectInlines.h: Added.
(JSC::getRegExpObjectLastIndexAsUnsigned):
(JSC::RegExpObject::execInline):
(JSC::RegExpObject::matchInline):
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@197796 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/runtime/RegExpMatchesArray.h b/Source/JavaScriptCore/runtime/RegExpMatchesArray.h
index d470e7c..b034e97 100644
--- a/Source/JavaScriptCore/runtime/RegExpMatchesArray.h
+++ b/Source/JavaScriptCore/runtime/RegExpMatchesArray.h
@@ -20,17 +20,96 @@
#ifndef RegExpMatchesArray_h
#define RegExpMatchesArray_h
+#include "ButterflyInlines.h"
#include "JSArray.h"
+#include "JSCInlines.h"
#include "JSGlobalObject.h"
+#include "RegExpInlines.h"
#include "RegExpObject.h"
namespace JSC {
-JSArray* createRegExpMatchesArray(ExecState*, JSGlobalObject*, JSString*, RegExp*, unsigned startOffset, MatchResult&);
+static const PropertyOffset RegExpMatchesArrayIndexPropertyOffset = 100;
+static const PropertyOffset RegExpMatchesArrayInputPropertyOffset = 101;
+
+ALWAYS_INLINE JSArray* tryCreateUninitializedRegExpMatchesArray(VM& vm, Structure* structure, unsigned initialLength)
+{
+ unsigned vectorLength = std::max(BASE_VECTOR_LEN, initialLength);
+ if (vectorLength > MAX_STORAGE_VECTOR_LENGTH)
+ return 0;
+
+ void* temp;
+ if (!vm.heap.tryAllocateStorage(0, Butterfly::totalSize(0, structure->outOfLineCapacity(), true, vectorLength * sizeof(EncodedJSValue)), &temp))
+ return 0;
+ Butterfly* butterfly = Butterfly::fromBase(temp, 0, structure->outOfLineCapacity());
+ butterfly->setVectorLength(vectorLength);
+ butterfly->setPublicLength(initialLength);
+
+ return JSArray::createWithButterfly(vm, structure, butterfly);
+}
+
+ALWAYS_INLINE JSArray* createRegExpMatchesArray(
+ VM& vm, JSGlobalObject* globalObject, JSString* input, const String& inputValue,
+ RegExp* regExp, unsigned startOffset, MatchResult& result)
+{
+ SamplingRegion samplingRegion("createRegExpMatchesArray");
+
+ Vector<int, 32> subpatternResults;
+ int position = regExp->matchInline(vm, inputValue, startOffset, subpatternResults);
+ if (position == -1) {
+ result = MatchResult::failed();
+ return nullptr;
+ }
+
+ result.start = position;
+ result.end = subpatternResults[1];
+
+ JSArray* array;
+
+ // FIXME: This should handle array allocation errors gracefully.
+ // https://bugs.webkit.org/show_bug.cgi?id=155144
+
+ if (UNLIKELY(globalObject->isHavingABadTime())) {
+ array = JSArray::tryCreateUninitialized(vm, globalObject->regExpMatchesArrayStructure(), regExp->numSubpatterns() + 1);
+
+ array->initializeIndex(vm, 0, jsSubstringOfResolved(vm, input, result.start, result.end - result.start));
+
+ if (unsigned numSubpatterns = regExp->numSubpatterns()) {
+ for (unsigned i = 1; i <= numSubpatterns; ++i) {
+ int start = subpatternResults[2 * i];
+ if (start >= 0)
+ array->initializeIndex(vm, i, JSRopeString::createSubstringOfResolved(vm, input, start, subpatternResults[2 * i + 1] - start));
+ else
+ array->initializeIndex(vm, i, jsUndefined());
+ }
+ }
+ } else {
+ array = tryCreateUninitializedRegExpMatchesArray(vm, globalObject->regExpMatchesArrayStructure(), regExp->numSubpatterns() + 1);
+ RELEASE_ASSERT(array);
+
+ array->initializeIndex(vm, 0, jsSubstringOfResolved(vm, input, result.start, result.end - result.start), ArrayWithContiguous);
+
+ if (unsigned numSubpatterns = regExp->numSubpatterns()) {
+ for (unsigned i = 1; i <= numSubpatterns; ++i) {
+ int start = subpatternResults[2 * i];
+ if (start >= 0)
+ array->initializeIndex(vm, i, JSRopeString::createSubstringOfResolved(vm, input, start, subpatternResults[2 * i + 1] - start), ArrayWithContiguous);
+ else
+ array->initializeIndex(vm, i, jsUndefined(), ArrayWithContiguous);
+ }
+ }
+ }
+
+ array->putDirect(vm, RegExpMatchesArrayIndexPropertyOffset, jsNumber(result.start));
+ array->putDirect(vm, RegExpMatchesArrayInputPropertyOffset, input);
+
+ return array;
+}
+
inline JSArray* createRegExpMatchesArray(ExecState* exec, JSGlobalObject* globalObject, JSString* string, RegExp* regExp, unsigned startOffset)
{
MatchResult ignoredResult;
- return createRegExpMatchesArray(exec, globalObject, string, regExp, startOffset, ignoredResult);
+ return createRegExpMatchesArray(globalObject->vm(), globalObject, string, string->value(exec), regExp, startOffset, ignoredResult);
}
JSArray* createEmptyRegExpMatchesArray(JSGlobalObject*, JSString*, RegExp*);
Structure* createRegExpMatchesArrayStructure(VM&, JSGlobalObject*);