Title: [197796] trunk/Source/_javascript_Core
Revision
197796
Author
[email protected]
Date
2016-03-08 13:15:07 -0800 (Tue, 08 Mar 2016)

Log Message

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.

* _javascript_Core.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):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (197795 => 197796)


--- trunk/Source/_javascript_Core/ChangeLog	2016-03-08 21:02:09 UTC (rev 197795)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-03-08 21:15:07 UTC (rev 197796)
@@ -1,3 +1,58 @@
+2016-03-08  Filip Pizlo  <[email protected]>
+
+        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.
+
+        * _javascript_Core.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):
+
 2016-03-08  Mark Lam  <[email protected]>
 
         synthesizePrototype() and friends need to be followed by exception checks (or equivalent).

Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (197795 => 197796)


--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2016-03-08 21:02:09 UTC (rev 197795)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2016-03-08 21:15:07 UTC (rev 197796)
@@ -486,6 +486,8 @@
 		0F7B294B14C3CD2F007C3DB1 /* DFGCapabilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD82E1F14172C2F00179C94 /* DFGCapabilities.h */; };
 		0F7B294D14C3CD4C007C3DB1 /* DFGCommon.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC0977E1469EBC400CF2442 /* DFGCommon.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		0F7C11AD1BC3862C00C74CDB /* CopyBarrier.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F7C11AC1BC3862C00C74CDB /* CopyBarrier.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		0F7C39FB1C8F629300480151 /* RegExpInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F7C39FA1C8F629300480151 /* RegExpInlines.h */; };
+		0F7C39FD1C8F659500480151 /* RegExpObjectInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F7C39FC1C8F659500480151 /* RegExpObjectInlines.h */; };
 		0F8023EA1613832B00A0BA45 /* ByValInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F8023E91613832300A0BA45 /* ByValInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		0F8335B71639C1E6001443B5 /* ArrayAllocationProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F8335B41639C1E3001443B5 /* ArrayAllocationProfile.cpp */; };
 		0F8335B81639C1EA001443B5 /* ArrayAllocationProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F8335B51639C1E3001443B5 /* ArrayAllocationProfile.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -2636,6 +2638,8 @@
 		0F79085319A290B200F6310C /* DFGStructureRegistrationPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGStructureRegistrationPhase.cpp; path = dfg/DFGStructureRegistrationPhase.cpp; sourceTree = "<group>"; };
 		0F79085419A290B200F6310C /* DFGStructureRegistrationPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGStructureRegistrationPhase.h; path = dfg/DFGStructureRegistrationPhase.h; sourceTree = "<group>"; };
 		0F7C11AC1BC3862C00C74CDB /* CopyBarrier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CopyBarrier.h; sourceTree = "<group>"; };
+		0F7C39FA1C8F629300480151 /* RegExpInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegExpInlines.h; sourceTree = "<group>"; };
+		0F7C39FC1C8F659500480151 /* RegExpObjectInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegExpObjectInlines.h; sourceTree = "<group>"; };
 		0F8023E91613832300A0BA45 /* ByValInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ByValInfo.h; sourceTree = "<group>"; };
 		0F8335B41639C1E3001443B5 /* ArrayAllocationProfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArrayAllocationProfile.cpp; sourceTree = "<group>"; };
 		0F8335B51639C1E3001443B5 /* ArrayAllocationProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArrayAllocationProfile.h; sourceTree = "<group>"; };
@@ -5874,11 +5878,13 @@
 				86F75EFC151C062F007C9BA3 /* RegExpCachedResult.h */,
 				BCD202BD0E1706A7002C7E82 /* RegExpConstructor.cpp */,
 				BCD202BE0E1706A7002C7E82 /* RegExpConstructor.h */,
+				0F7C39FA1C8F629300480151 /* RegExpInlines.h */,
 				A1712B4011C7B235007A5315 /* RegExpKey.h */,
 				86F75EFD151C062F007C9BA3 /* RegExpMatchesArray.cpp */,
 				93CEDDFB0EA91EE600258EBE /* RegExpMatchesArray.h */,
 				F692A87B0255597D01FF60F7 /* RegExpObject.cpp */,
 				F692A87C0255597D01FF60F7 /* RegExpObject.h */,
+				0F7C39FC1C8F659500480151 /* RegExpObjectInlines.h */,
 				BCD202BF0E1706A7002C7E82 /* RegExpPrototype.cpp */,
 				BCD202C00E1706A7002C7E82 /* RegExpPrototype.h */,
 				0FB7F39115ED8E3800F167B2 /* Reject.h */,
@@ -7206,6 +7212,7 @@
 				0FBC0AE81496C7C700D4FBDD /* DFGExitProfile.h in Headers */,
 				A78A9775179738B8009DF744 /* DFGFailedFinalizer.h in Headers */,
 				A7BFF3C0179868940002F462 /* DFGFiltrationResult.h in Headers */,
+				0F7C39FB1C8F629300480151 /* RegExpInlines.h in Headers */,
 				A78A9777179738B8009DF744 /* DFGFinalizer.h in Headers */,
 				0F2BDC16151C5D4F00CD8910 /* DFGFixupPhase.h in Headers */,
 				0F9D339717FFC4E60073C2BC /* DFGFlushedAt.h in Headers */,
@@ -7925,6 +7932,7 @@
 				A709F2F017A0AC0400512E98 /* SlowPathCall.h in Headers */,
 				933040040E6A749400786E6A /* SmallStrings.h in Headers */,
 				BC18C4640E16F5CD00B34460 /* SourceCode.h in Headers */,
+				0F7C39FD1C8F659500480151 /* RegExpObjectInlines.h in Headers */,
 				BC18C4630E16F5CD00B34460 /* SourceProvider.h in Headers */,
 				E49DC16C12EF294E00184A1F /* SourceProviderCache.h in Headers */,
 				E49DC16D12EF295300184A1F /* SourceProviderCacheItem.h in Headers */,

Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.cpp (197795 => 197796)


--- trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2016-03-08 21:02:09 UTC (rev 197795)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2016-03-08 21:15:07 UTC (rev 197796)
@@ -624,7 +624,7 @@
     VM& vm = globalObject->vm();
     NativeCallFrameTracer tracer(&vm, exec);
     
-    return JSValue::encode(regExpObject->exec(exec, globalObject, argument));
+    return JSValue::encode(regExpObject->execInline(exec, globalObject, argument));
 }
         
 EncodedJSValue JIT_OPERATION operationRegExpExec(ExecState* exec, JSGlobalObject* globalObject, RegExpObject* regExpObject, EncodedJSValue encodedArgument)
@@ -637,7 +637,7 @@
     JSString* input = argument.toStringOrNull(exec);
     if (!input)
         return JSValue::encode(jsUndefined());
-    return JSValue::encode(regExpObject->exec(exec, globalObject, input));
+    return JSValue::encode(regExpObject->execInline(exec, globalObject, input));
 }
         
 EncodedJSValue JIT_OPERATION operationRegExpExecGeneric(ExecState* exec, JSGlobalObject* globalObject, EncodedJSValue encodedBase, EncodedJSValue encodedArgument)
@@ -662,7 +662,7 @@
     VM& vm = globalObject->vm();
     NativeCallFrameTracer tracer(&vm, exec);
 
-    return regExpObject->test(exec, globalObject, input);
+    return regExpObject->testInline(exec, globalObject, input);
 }
 
 size_t JIT_OPERATION operationRegExpTest(ExecState* exec, JSGlobalObject* globalObject, RegExpObject* regExpObject, EncodedJSValue encodedArgument)
@@ -675,7 +675,7 @@
     JSString* input = argument.toStringOrNull(exec);
     if (!input)
         return false;
-    return regExpObject->test(exec, globalObject, input);
+    return regExpObject->testInline(exec, globalObject, input);
 }
 
 size_t JIT_OPERATION operationRegExpTestGeneric(ExecState* exec, JSGlobalObject* globalObject, EncodedJSValue encodedBase, EncodedJSValue encodedArgument)

Modified: trunk/Source/_javascript_Core/runtime/RegExp.cpp (197795 => 197796)


--- trunk/Source/_javascript_Core/runtime/RegExp.cpp	2016-03-08 21:02:09 UTC (rev 197795)
+++ trunk/Source/_javascript_Core/runtime/RegExp.cpp	2016-03-08 21:15:07 UTC (rev 197796)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2001, 2004 Harri Porten ([email protected])
- *  Copyright (c) 2007, 2008 Apple Inc. All rights reserved.
+ *  Copyright (c) 2007, 2008, 2016 Apple Inc. All rights reserved.
  *  Copyright (C) 2009 Torch Mobile, Inc.
  *  Copyright (C) 2010 Peter Varga ([email protected]), University of Szeged
  *
@@ -26,18 +26,11 @@
 #include "Lexer.h"
 #include "JSCInlines.h"
 #include "RegExpCache.h"
+#include "RegExpInlines.h"
 #include "Yarr.h"
 #include "YarrJIT.h"
 #include <wtf/Assertions.h>
 
-#define REGEXP_FUNC_TEST_DATA_GEN 0
-
-#if REGEXP_FUNC_TEST_DATA_GEN
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#endif
-
 namespace JSC {
 
 const ClassInfo RegExp::s_info = { "RegExp", 0, 0, CREATE_METHOD_TABLE(RegExp) };
@@ -81,33 +74,6 @@
 }
 
 #if REGEXP_FUNC_TEST_DATA_GEN
-class RegExpFunctionalTestCollector {
-    // This class is not thread safe.
-protected:
-    static const char* const s_fileName;
-
-public:
-    static RegExpFunctionalTestCollector* get();
-
-    ~RegExpFunctionalTestCollector();
-
-    void outputOneTest(RegExp*, String, int, int*, int);
-    void clearRegExp(RegExp* regExp)
-    {
-        if (regExp == m_lastRegExp)
-            m_lastRegExp = 0;
-    }
-
-private:
-    RegExpFunctionalTestCollector();
-
-    void outputEscapedString(const String&, bool escapeSlash = false);
-
-    static RegExpFunctionalTestCollector* s_instance;
-    FILE* m_file;
-    RegExp* m_lastRegExp;
-};
-
 const char* const RegExpFunctionalTestCollector::s_fileName = "/tmp/RegExpTestsData";
 RegExpFunctionalTestCollector* RegExpFunctionalTestCollector::s_instance = 0;
 
@@ -320,89 +286,9 @@
     m_regExpBytecode = Yarr::byteCompile(pattern, &vm->m_regExpAllocator);
 }
 
-void RegExp::compileIfNecessary(VM& vm, Yarr::YarrCharSize charSize)
-{
-    if (hasCode()) {
-#if ENABLE(YARR_JIT)
-        if (m_state != JITCode)
-            return;
-        if ((charSize == Yarr::Char8) && (m_regExpJITCode.has8BitCode()))
-            return;
-        if ((charSize == Yarr::Char16) && (m_regExpJITCode.has16BitCode()))
-            return;
-#else
-        return;
-#endif
-    }
-
-    compile(&vm, charSize);
-}
-
 int RegExp::match(VM& vm, const String& s, unsigned startOffset, Vector<int, 32>& ovector)
 {
-#if ENABLE(REGEXP_TRACING)
-    m_rtMatchCallCount++;
-    m_rtMatchTotalSubjectStringLen += (double)(s.length() - startOffset);
-#endif
-
-    ASSERT(m_state != ParseError);
-    compileIfNecessary(vm, s.is8Bit() ? Yarr::Char8 : Yarr::Char16);
-
-    int offsetVectorSize = (m_numSubpatterns + 1) * 2;
-    ovector.resize(offsetVectorSize);
-    int* offsetVector = ovector.data();
-
-    int result;
-#if ENABLE(YARR_JIT)
-    if (m_state == JITCode) {
-        if (s.is8Bit())
-            result = m_regExpJITCode.execute(s.characters8(), startOffset, s.length(), offsetVector).start;
-        else
-            result = m_regExpJITCode.execute(s.characters16(), startOffset, s.length(), offsetVector).start;
-#if ENABLE(YARR_JIT_DEBUG)
-        matchCompareWithInterpreter(s, startOffset, offsetVector, result);
-#endif
-    } else
-#endif
-        result = Yarr::interpret(m_regExpBytecode.get(), s, startOffset, reinterpret_cast<unsigned*>(offsetVector));
-
-    // FIXME: The YARR engine should handle unsigned or size_t length matches.
-    // The YARR Interpreter is "unsigned" clean, while the YARR JIT hasn't been addressed.
-    // The offset vector handling needs to change as well.
-    // Right now we convert a match where the offsets overflowed into match failure.
-    // There are two places in WebCore that call the interpreter directly that need to
-    // have their offsets changed to int as well. They are yarr/RegularExpression.cpp
-    // and inspector/ContentSearchUtilities.cpp
-    if (s.length() > INT_MAX) {
-        bool overflowed = false;
-
-        if (result < -1)
-            overflowed = true;
-
-        for (unsigned i = 0; i <= m_numSubpatterns; i++) {
-            if ((offsetVector[i*2] < -1) || ((offsetVector[i*2] >= 0) && (offsetVector[i*2+1] < -1))) {
-                overflowed = true;
-                offsetVector[i*2] = -1;
-                offsetVector[i*2+1] = -1;
-            }
-        }
-
-        if (overflowed)
-            result = -1;
-    }
-
-    ASSERT(result >= -1);
-
-#if REGEXP_FUNC_TEST_DATA_GEN
-    RegExpFunctionalTestCollector::get()->outputOneTest(this, s, startOffset, offsetVector, result);
-#endif
-
-#if ENABLE(REGEXP_TRACING)
-    if (result != -1)
-        m_rtMatchFoundCount++;
-#endif
-
-    return result;
+    return matchInline(vm, s, startOffset, ovector);
 }
 
 void RegExp::compileMatchOnly(VM* vm, Yarr::YarrCharSize charSize)
@@ -439,65 +325,9 @@
     m_regExpBytecode = Yarr::byteCompile(pattern, &vm->m_regExpAllocator);
 }
 
-void RegExp::compileIfNecessaryMatchOnly(VM& vm, Yarr::YarrCharSize charSize)
-{
-    if (hasCode()) {
-#if ENABLE(YARR_JIT)
-        if (m_state != JITCode)
-            return;
-        if ((charSize == Yarr::Char8) && (m_regExpJITCode.has8BitCodeMatchOnly()))
-            return;
-        if ((charSize == Yarr::Char16) && (m_regExpJITCode.has16BitCodeMatchOnly()))
-            return;
-#else
-        return;
-#endif
-    }
-
-    compileMatchOnly(&vm, charSize);
-}
-
 MatchResult RegExp::match(VM& vm, const String& s, unsigned startOffset)
 {
-#if ENABLE(REGEXP_TRACING)
-    m_rtMatchOnlyCallCount++;
-    m_rtMatchOnlyTotalSubjectStringLen += (double)(s.length() - startOffset);
-#endif
-
-    ASSERT(m_state != ParseError);
-    compileIfNecessaryMatchOnly(vm, s.is8Bit() ? Yarr::Char8 : Yarr::Char16);
-
-#if ENABLE(YARR_JIT)
-    if (m_state == JITCode) {
-        MatchResult result = s.is8Bit() ?
-            m_regExpJITCode.execute(s.characters8(), startOffset, s.length()) :
-            m_regExpJITCode.execute(s.characters16(), startOffset, s.length());
-#if ENABLE(REGEXP_TRACING)
-        if (!result)
-            m_rtMatchOnlyFoundCount++;
-#endif
-        return result;
-    }
-#endif
-
-    int offsetVectorSize = (m_numSubpatterns + 1) * 2;
-    int* offsetVector;
-    Vector<int, 32> nonReturnedOvector;
-    nonReturnedOvector.resize(offsetVectorSize);
-    offsetVector = nonReturnedOvector.data();
-    int r = Yarr::interpret(m_regExpBytecode.get(), s, startOffset, reinterpret_cast<unsigned*>(offsetVector));
-#if REGEXP_FUNC_TEST_DATA_GEN
-    RegExpFunctionalTestCollector::get()->outputOneTest(this, s, startOffset, offsetVector, result);
-#endif
-
-    if (r >= 0) {
-#if ENABLE(REGEXP_TRACING)
-        m_rtMatchOnlyFoundCount++;
-#endif
-        return MatchResult(r, reinterpret_cast<unsigned*>(offsetVector)[1]);
-    }
-
-    return MatchResult::failed();
+    return matchInline(vm, s, startOffset);
 }
 
 void RegExp::deleteCode()

Modified: trunk/Source/_javascript_Core/runtime/RegExp.h (197795 => 197796)


--- trunk/Source/_javascript_Core/runtime/RegExp.h	2016-03-08 21:02:09 UTC (rev 197795)
+++ trunk/Source/_javascript_Core/runtime/RegExp.h	2016-03-08 21:15:07 UTC (rev 197796)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2000 Harri Porten ([email protected])
- *  Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
+ *  Copyright (C) 2007, 2008, 2009, 2016 Apple Inc. All rights reserved.
  *  Copyright (C) 2009 Torch Mobile, Inc.
  *
  *  This library is free software; you can redistribute it and/or
@@ -64,6 +64,11 @@
 
     JS_EXPORT_PRIVATE int match(VM&, const String&, unsigned startOffset, Vector<int, 32>& ovector);
     JS_EXPORT_PRIVATE MatchResult match(VM&, const String&, unsigned startOffset);
+
+    // Call these versions of the match functions if you're desperate for performance.
+    int matchInline(VM&, const String&, unsigned startOffset, Vector<int, 32>& ovector);
+    MatchResult matchInline(VM&, const String&, unsigned startOffset);
+    
     unsigned numSubpatterns() const { return m_numSubpatterns; }
 
     bool hasCode()

Added: trunk/Source/_javascript_Core/runtime/RegExpInlines.h (0 => 197796)


--- trunk/Source/_javascript_Core/runtime/RegExpInlines.h	                        (rev 0)
+++ trunk/Source/_javascript_Core/runtime/RegExpInlines.h	2016-03-08 21:15:07 UTC (rev 197796)
@@ -0,0 +1,219 @@
+/*
+ *  Copyright (C) 1999-2001, 2004 Harri Porten ([email protected])
+ *  Copyright (c) 2007, 2008, 2016 Apple Inc. All rights reserved.
+ *  Copyright (C) 2009 Torch Mobile, Inc.
+ *  Copyright (C) 2010 Peter Varga ([email protected]), University of Szeged
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef RegExpInlines_h
+#define RegExpInlines_h
+
+#include "RegExp.h"
+#include "JSCInlines.h"
+#include "Yarr.h"
+#include "YarrJIT.h"
+
+#define REGEXP_FUNC_TEST_DATA_GEN 0
+
+#if REGEXP_FUNC_TEST_DATA_GEN
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#endif
+
+namespace JSC {
+
+#if REGEXP_FUNC_TEST_DATA_GEN
+class RegExpFunctionalTestCollector {
+    // This class is not thread safe.
+protected:
+    static const char* const s_fileName;
+
+public:
+    static RegExpFunctionalTestCollector* get();
+
+    ~RegExpFunctionalTestCollector();
+
+    void outputOneTest(RegExp*, String, int, int*, int);
+    void clearRegExp(RegExp* regExp)
+    {
+        if (regExp == m_lastRegExp)
+            m_lastRegExp = 0;
+    }
+
+private:
+    RegExpFunctionalTestCollector();
+
+    void outputEscapedString(const String&, bool escapeSlash = false);
+
+    static RegExpFunctionalTestCollector* s_instance;
+    FILE* m_file;
+    RegExp* m_lastRegExp;
+};
+#endif // REGEXP_FUNC_TEST_DATA_GEN
+
+ALWAYS_INLINE void RegExp::compileIfNecessary(VM& vm, Yarr::YarrCharSize charSize)
+{
+    if (hasCode()) {
+#if ENABLE(YARR_JIT)
+        if (m_state != JITCode)
+            return;
+        if ((charSize == Yarr::Char8) && (m_regExpJITCode.has8BitCode()))
+            return;
+        if ((charSize == Yarr::Char16) && (m_regExpJITCode.has16BitCode()))
+            return;
+#else
+        return;
+#endif
+    }
+
+    compile(&vm, charSize);
+}
+
+ALWAYS_INLINE int RegExp::matchInline(VM& vm, const String& s, unsigned startOffset, Vector<int, 32>& ovector)
+{
+#if ENABLE(REGEXP_TRACING)
+    m_rtMatchCallCount++;
+    m_rtMatchTotalSubjectStringLen += (double)(s.length() - startOffset);
+#endif
+
+    ASSERT(m_state != ParseError);
+    compileIfNecessary(vm, s.is8Bit() ? Yarr::Char8 : Yarr::Char16);
+
+    int offsetVectorSize = (m_numSubpatterns + 1) * 2;
+    ovector.resize(offsetVectorSize);
+    int* offsetVector = ovector.data();
+
+    int result;
+#if ENABLE(YARR_JIT)
+    if (m_state == JITCode) {
+        if (s.is8Bit())
+            result = m_regExpJITCode.execute(s.characters8(), startOffset, s.length(), offsetVector).start;
+        else
+            result = m_regExpJITCode.execute(s.characters16(), startOffset, s.length(), offsetVector).start;
+#if ENABLE(YARR_JIT_DEBUG)
+        matchCompareWithInterpreter(s, startOffset, offsetVector, result);
+#endif
+    } else
+#endif
+        result = Yarr::interpret(m_regExpBytecode.get(), s, startOffset, reinterpret_cast<unsigned*>(offsetVector));
+
+    // FIXME: The YARR engine should handle unsigned or size_t length matches.
+    // The YARR Interpreter is "unsigned" clean, while the YARR JIT hasn't been addressed.
+    // The offset vector handling needs to change as well.
+    // Right now we convert a match where the offsets overflowed into match failure.
+    // There are two places in WebCore that call the interpreter directly that need to
+    // have their offsets changed to int as well. They are yarr/RegularExpression.cpp
+    // and inspector/ContentSearchUtilities.cpp
+    if (s.length() > INT_MAX) {
+        bool overflowed = false;
+
+        if (result < -1)
+            overflowed = true;
+
+        for (unsigned i = 0; i <= m_numSubpatterns; i++) {
+            if ((offsetVector[i*2] < -1) || ((offsetVector[i*2] >= 0) && (offsetVector[i*2+1] < -1))) {
+                overflowed = true;
+                offsetVector[i*2] = -1;
+                offsetVector[i*2+1] = -1;
+            }
+        }
+
+        if (overflowed)
+            result = -1;
+    }
+
+    ASSERT(result >= -1);
+
+#if REGEXP_FUNC_TEST_DATA_GEN
+    RegExpFunctionalTestCollector::get()->outputOneTest(this, s, startOffset, offsetVector, result);
+#endif
+
+#if ENABLE(REGEXP_TRACING)
+    if (result != -1)
+        m_rtMatchFoundCount++;
+#endif
+
+    return result;
+}
+
+ALWAYS_INLINE void RegExp::compileIfNecessaryMatchOnly(VM& vm, Yarr::YarrCharSize charSize)
+{
+    if (hasCode()) {
+#if ENABLE(YARR_JIT)
+        if (m_state != JITCode)
+            return;
+        if ((charSize == Yarr::Char8) && (m_regExpJITCode.has8BitCodeMatchOnly()))
+            return;
+        if ((charSize == Yarr::Char16) && (m_regExpJITCode.has16BitCodeMatchOnly()))
+            return;
+#else
+        return;
+#endif
+    }
+
+    compileMatchOnly(&vm, charSize);
+}
+
+ALWAYS_INLINE MatchResult RegExp::matchInline(VM& vm, const String& s, unsigned startOffset)
+{
+#if ENABLE(REGEXP_TRACING)
+    m_rtMatchOnlyCallCount++;
+    m_rtMatchOnlyTotalSubjectStringLen += (double)(s.length() - startOffset);
+#endif
+
+    ASSERT(m_state != ParseError);
+    compileIfNecessaryMatchOnly(vm, s.is8Bit() ? Yarr::Char8 : Yarr::Char16);
+
+#if ENABLE(YARR_JIT)
+    if (m_state == JITCode) {
+        MatchResult result = s.is8Bit() ?
+            m_regExpJITCode.execute(s.characters8(), startOffset, s.length()) :
+            m_regExpJITCode.execute(s.characters16(), startOffset, s.length());
+#if ENABLE(REGEXP_TRACING)
+        if (!result)
+            m_rtMatchOnlyFoundCount++;
+#endif
+        return result;
+    }
+#endif
+
+    int offsetVectorSize = (m_numSubpatterns + 1) * 2;
+    int* offsetVector;
+    Vector<int, 32> nonReturnedOvector;
+    nonReturnedOvector.resize(offsetVectorSize);
+    offsetVector = nonReturnedOvector.data();
+    int r = Yarr::interpret(m_regExpBytecode.get(), s, startOffset, reinterpret_cast<unsigned*>(offsetVector));
+#if REGEXP_FUNC_TEST_DATA_GEN
+    RegExpFunctionalTestCollector::get()->outputOneTest(this, s, startOffset, offsetVector, result);
+#endif
+
+    if (r >= 0) {
+#if ENABLE(REGEXP_TRACING)
+        m_rtMatchOnlyFoundCount++;
+#endif
+        return MatchResult(r, reinterpret_cast<unsigned*>(offsetVector)[1]);
+    }
+
+    return MatchResult::failed();
+}
+
+} // namespace JSC
+
+#endif // RegExpInlines_h
+

Modified: trunk/Source/_javascript_Core/runtime/RegExpMatchesArray.cpp (197795 => 197796)


--- trunk/Source/_javascript_Core/runtime/RegExpMatchesArray.cpp	2016-03-08 21:02:09 UTC (rev 197795)
+++ trunk/Source/_javascript_Core/runtime/RegExpMatchesArray.cpp	2016-03-08 21:15:07 UTC (rev 197796)
@@ -26,90 +26,8 @@
 #include "config.h"
 #include "RegExpMatchesArray.h"
 
-#include "ButterflyInlines.h"
-#include "JSCInlines.h"
-
 namespace JSC {
 
-static const PropertyOffset indexPropertyOffset = 100;
-static const PropertyOffset inputPropertyOffset = 101;
-
-static 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);
-}
-
-JSArray* createRegExpMatchesArray(
-    ExecState* exec, JSGlobalObject* globalObject, JSString* input, RegExp* regExp,
-    unsigned startOffset, MatchResult& result)
-{
-    SamplingRegion samplingRegion("createRegExpMatchesArray");
-    
-    VM& vm = globalObject->vm();
-    
-    Vector<int, 32> subpatternResults;
-    int position = regExp->match(vm, input->value(exec), 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, indexPropertyOffset, jsNumber(result.start));
-    array->putDirect(vm, inputPropertyOffset, input);
-
-    return array;
-}
-
 JSArray* createEmptyRegExpMatchesArray(JSGlobalObject* globalObject, JSString* input, RegExp* regExp)
 {
     VM& vm = globalObject->vm();
@@ -139,8 +57,8 @@
         }
     }
 
-    array->putDirect(vm, indexPropertyOffset, jsNumber(-1));
-    array->putDirect(vm, inputPropertyOffset, input);
+    array->putDirect(vm, RegExpMatchesArrayIndexPropertyOffset, jsNumber(-1));
+    array->putDirect(vm, RegExpMatchesArrayInputPropertyOffset, input);
     return array;
 }
 
@@ -149,9 +67,9 @@
     Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(indexingType);
     PropertyOffset offset;
     structure = Structure::addPropertyTransition(vm, structure, vm.propertyNames->index, 0, offset);
-    ASSERT(offset == indexPropertyOffset);
+    ASSERT(offset == RegExpMatchesArrayIndexPropertyOffset);
     structure = Structure::addPropertyTransition(vm, structure, vm.propertyNames->input, 0, offset);
-    ASSERT(offset == inputPropertyOffset);
+    ASSERT(offset == RegExpMatchesArrayInputPropertyOffset);
     return structure;
 }
 

Modified: trunk/Source/_javascript_Core/runtime/RegExpMatchesArray.h (197795 => 197796)


--- trunk/Source/_javascript_Core/runtime/RegExpMatchesArray.h	2016-03-08 21:02:09 UTC (rev 197795)
+++ trunk/Source/_javascript_Core/runtime/RegExpMatchesArray.h	2016-03-08 21:15:07 UTC (rev 197796)
@@ -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*);

Modified: trunk/Source/_javascript_Core/runtime/RegExpObject.cpp (197795 => 197796)


--- trunk/Source/_javascript_Core/runtime/RegExpObject.cpp	2016-03-08 21:02:09 UTC (rev 197795)
+++ trunk/Source/_javascript_Core/runtime/RegExpObject.cpp	2016-03-08 21:15:07 UTC (rev 197796)
@@ -32,6 +32,7 @@
 #include "JSCInlines.h"
 #include "RegExpConstructor.h"
 #include "RegExpMatchesArray.h"
+#include "RegExpObjectInlines.h"
 #include "RegExpPrototype.h"
 #include <wtf/text/StringBuilder.h>
 
@@ -159,77 +160,15 @@
     Base::put(cell, exec, propertyName, value, slot);
 }
 
-ALWAYS_INLINE unsigned getLastIndexAsUnsigned(
-    ExecState* exec, RegExpObject* regExpObject, const String& input)
-{
-    JSValue jsLastIndex = regExpObject->getLastIndex();
-    unsigned lastIndex;
-    if (LIKELY(jsLastIndex.isUInt32())) {
-        lastIndex = jsLastIndex.asUInt32();
-        if (lastIndex > input.length()) {
-            regExpObject->setLastIndex(exec, 0);
-            return UINT_MAX;
-        }
-    } else {
-        double doubleLastIndex = jsLastIndex.toInteger(exec);
-        if (doubleLastIndex < 0 || doubleLastIndex > input.length()) {
-            regExpObject->setLastIndex(exec, 0);
-            return UINT_MAX;
-        }
-        lastIndex = static_cast<unsigned>(doubleLastIndex);
-    }
-    return lastIndex;
-}
-
 JSValue RegExpObject::exec(ExecState* exec, JSGlobalObject* globalObject, JSString* string)
 {
-    RegExp* regExp = this->regExp();
-    RegExpConstructor* regExpConstructor = globalObject->regExpConstructor();
-    String input = string->value(exec); // FIXME: Handle errors. https://bugs.webkit.org/show_bug.cgi?id=155145
-    VM& vm = globalObject->vm();
-
-    if (!regExp->global()) {
-        MatchResult result;
-        JSArray* array = createRegExpMatchesArray(exec, globalObject, string, regExp, 0, result);
-        if (!array)
-            return jsNull();
-        regExpConstructor->recordMatch(vm, regExp, string, result);
-        return array;
-    }
-
-    unsigned lastIndex = getLastIndexAsUnsigned(exec, this, input);
-    if (lastIndex == UINT_MAX)
-        return jsNull();
-    
-    MatchResult result;
-    JSArray* array =
-        createRegExpMatchesArray(exec, globalObject, string, regExp, lastIndex, result);
-    if (!array) {
-        setLastIndex(exec, 0);
-        return jsNull();
-    }
-    setLastIndex(exec, result.end);
-    regExpConstructor->recordMatch(vm, regExp, string, result);
-    return array;
+    return execInline(exec, globalObject, string);
 }
 
 // Shared implementation used by test and exec.
 MatchResult RegExpObject::match(ExecState* exec, JSGlobalObject* globalObject, JSString* string)
 {
-    RegExp* regExp = this->regExp();
-    RegExpConstructor* regExpConstructor = globalObject->regExpConstructor();
-    String input = string->value(exec); // FIXME: Handle errors. https://bugs.webkit.org/show_bug.cgi?id=155145
-    VM& vm = globalObject->vm();
-    if (!regExp->global())
-        return regExpConstructor->performMatch(vm, regExp, string, input, 0);
-
-    unsigned lastIndex = getLastIndexAsUnsigned(exec, this, input);
-    if (lastIndex == UINT_MAX)
-        return MatchResult::failed();
-    
-    MatchResult result = regExpConstructor->performMatch(vm, regExp, string, input, lastIndex);
-    setLastIndex(exec, result.end);
-    return result;
+    return matchInline(exec, globalObject, string);
 }
 
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/runtime/RegExpObject.h (197795 => 197796)


--- trunk/Source/_javascript_Core/runtime/RegExpObject.h	2016-03-08 21:02:09 UTC (rev 197795)
+++ trunk/Source/_javascript_Core/runtime/RegExpObject.h	2016-03-08 21:15:07 UTC (rev 197796)
@@ -67,7 +67,9 @@
     }
 
     bool test(ExecState* exec, JSGlobalObject* globalObject, JSString* string) { return !!match(exec, globalObject, string); }
+    bool testInline(ExecState* exec, JSGlobalObject* globalObject, JSString* string) { return !!matchInline(exec, globalObject, string); }
     JSValue exec(ExecState*, JSGlobalObject*, JSString*);
+    JSValue execInline(ExecState*, JSGlobalObject*, JSString*);
 
     static bool getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&);
     static void put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&);
@@ -103,6 +105,7 @@
 
 private:
     MatchResult match(ExecState*, JSGlobalObject*, JSString*);
+    MatchResult matchInline(ExecState*, JSGlobalObject*, JSString*);
 
     WriteBarrier<RegExp> m_regExp;
     WriteBarrier<Unknown> m_lastIndex;

Added: trunk/Source/_javascript_Core/runtime/RegExpObjectInlines.h (0 => 197796)


--- trunk/Source/_javascript_Core/runtime/RegExpObjectInlines.h	                        (rev 0)
+++ trunk/Source/_javascript_Core/runtime/RegExpObjectInlines.h	2016-03-08 21:15:07 UTC (rev 197796)
@@ -0,0 +1,113 @@
+/*
+ *  Copyright (C) 1999-2000 Harri Porten ([email protected])
+ *  Copyright (C) 2003, 2007, 2008, 2012, 2016 Apple Inc. All Rights Reserved.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef RegExpObjectInlines_h
+#define RegExpObjectInlines_h
+
+#include "ButterflyInlines.h"
+#include "Error.h"
+#include "ExceptionHelpers.h"
+#include "JSArray.h"
+#include "JSGlobalObject.h"
+#include "JSString.h"
+#include "JSCInlines.h"
+#include "RegExpConstructor.h"
+#include "RegExpMatchesArray.h"
+#include "RegExpObject.h"
+
+namespace JSC {
+
+ALWAYS_INLINE unsigned getRegExpObjectLastIndexAsUnsigned(
+    ExecState* exec, RegExpObject* regExpObject, const String& input)
+{
+    JSValue jsLastIndex = regExpObject->getLastIndex();
+    unsigned lastIndex;
+    if (LIKELY(jsLastIndex.isUInt32())) {
+        lastIndex = jsLastIndex.asUInt32();
+        if (lastIndex > input.length()) {
+            regExpObject->setLastIndex(exec, 0);
+            return UINT_MAX;
+        }
+    } else {
+        double doubleLastIndex = jsLastIndex.toInteger(exec);
+        if (doubleLastIndex < 0 || doubleLastIndex > input.length()) {
+            regExpObject->setLastIndex(exec, 0);
+            return UINT_MAX;
+        }
+        lastIndex = static_cast<unsigned>(doubleLastIndex);
+    }
+    return lastIndex;
+}
+
+JSValue RegExpObject::execInline(ExecState* exec, JSGlobalObject* globalObject, JSString* string)
+{
+    RegExp* regExp = this->regExp();
+    RegExpConstructor* regExpConstructor = globalObject->regExpConstructor();
+    String input = string->value(exec); // FIXME: Handle errors. https://bugs.webkit.org/show_bug.cgi?id=155145
+    VM& vm = globalObject->vm();
+
+    bool global = regExp->global();
+
+    unsigned lastIndex;
+    if (global) {
+        lastIndex = getRegExpObjectLastIndexAsUnsigned(exec, this, input);
+        if (lastIndex == UINT_MAX)
+            return jsNull();
+    } else
+        lastIndex = 0;
+    
+    MatchResult result;
+    JSArray* array =
+        createRegExpMatchesArray(vm, globalObject, string, input, regExp, lastIndex, result);
+    if (!array) {
+        if (global)
+            setLastIndex(exec, 0);
+        return jsNull();
+    }
+    if (global)
+        setLastIndex(exec, result.end);
+    regExpConstructor->recordMatch(vm, regExp, string, result);
+    return array;
+}
+
+// Shared implementation used by test and exec.
+MatchResult RegExpObject::matchInline(
+    ExecState* exec, JSGlobalObject* globalObject, JSString* string)
+{
+    RegExp* regExp = this->regExp();
+    RegExpConstructor* regExpConstructor = globalObject->regExpConstructor();
+    String input = string->value(exec); // FIXME: Handle errors. https://bugs.webkit.org/show_bug.cgi?id=155145
+    VM& vm = globalObject->vm();
+    if (!regExp->global())
+        return regExpConstructor->performMatch(vm, regExp, string, input, 0);
+
+    unsigned lastIndex = getRegExpObjectLastIndexAsUnsigned(exec, this, input);
+    if (lastIndex == UINT_MAX)
+        return MatchResult::failed();
+    
+    MatchResult result = regExpConstructor->performMatch(vm, regExp, string, input, lastIndex);
+    setLastIndex(exec, result.end);
+    return result;
+}
+
+} // namespace JSC
+
+#endif // RegExpObjectInlines_h
+
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to