Yarr: if we're not using the output array, don't populate it!
https://bugs.webkit.org/show_bug.cgi?id=82519
Reviewed by Sam Weinig.
../JavaScriptCore:
Add a new variant of the match method to RegExp that returns a MatchResult,
and modify YarrJIT to be able to compile code that doesn't use an output vector.
This is a 3% progression on v8-regexp.
* JavaScriptCore.xcodeproj/project.pbxproj:
- Moved MatchResult into its own header.
* assembler/AbstractMacroAssembler.h:
- Added missing include.
* runtime/MatchResult.h: Added.
(MatchResult::MatchResult):
(MatchResult):
(MatchResult::failed):
(MatchResult::operator bool):
(MatchResult::empty):
- Moved MatchResult into its own header.
* runtime/RegExp.cpp:
(JSC::RegExp::compile):
(JSC::RegExp::compileIfNecessary):
(JSC::RegExp::match):
- Changed due to execute & representation changes.
(JSC::RegExp::compileMatchOnly):
(JSC::RegExp::compileIfNecessaryMatchOnly):
- Added helper to compile MatchOnly code.
(JSC::RegExp::invalidateCode):
(JSC::RegExp::matchCompareWithInterpreter):
(JSC::RegExp::printTraceData):
- Changed due representation changes.
* runtime/RegExp.h:
(RegExp):
(JSC::RegExp::hasCode):
- Made YarrCodeBlock a member.
* runtime/RegExpConstructor.h:
(RegExpConstructor):
(JSC::RegExpConstructor::performMatch):
- Added no-ovector form.
* runtime/RegExpMatchesArray.cpp:
(JSC::RegExpMatchesArray::reifyAllProperties):
- Match now takes a reference to ovector, not a pointer.
* runtime/RegExpObject.h:
(JSC):
- Moved MatchResult into its own header.
* runtime/StringPrototype.cpp:
(JSC::stringProtoFuncSplit):
- Match now takes a reference to ovector, not a pointer.
* testRegExp.cpp:
(testOneRegExp):
- Match now takes a reference to ovector, not a pointer.
* yarr/YarrJIT.cpp:
(Yarr):
(YarrGenerator):
(JSC::Yarr::YarrGenerator::initCallFrame):
(JSC::Yarr::YarrGenerator::removeCallFrame):
(JSC::Yarr::YarrGenerator::setSubpatternStart):
(JSC::Yarr::YarrGenerator::setSubpatternEnd):
(JSC::Yarr::YarrGenerator::clearSubpatternStart):
(JSC::Yarr::YarrGenerator::setMatchStart):
(JSC::Yarr::YarrGenerator::getMatchStart):
- Added helper functions to intermediate access to output.
(JSC::Yarr::YarrGenerator::generateDotStarEnclosure):
(JSC::Yarr::YarrGenerator::generate):
(JSC::Yarr::YarrGenerator::backtrack):
(JSC::Yarr::YarrGenerator::generateEnter):
(JSC::Yarr::YarrGenerator::compile):
- Changed to use the new helpers, only generate subpatterns if IncludeSubpatterns.
(JSC::Yarr::jitCompile):
- Needs to template of MatchOnly or IncludeSubpatterns.
* yarr/YarrJIT.h:
(YarrCodeBlock):
(JSC::Yarr::YarrCodeBlock::set8BitCode):
(JSC::Yarr::YarrCodeBlock::set16BitCode):
(JSC::Yarr::YarrCodeBlock::has8BitCodeMatchOnly):
(JSC::Yarr::YarrCodeBlock::has16BitCodeMatchOnly):
(JSC::Yarr::YarrCodeBlock::set8BitCodeMatchOnly):
(JSC::Yarr::YarrCodeBlock::set16BitCodeMatchOnly):
(JSC::Yarr::YarrCodeBlock::execute):
(JSC::Yarr::YarrCodeBlock::clear):
- Added a second set of CodeRefs, so that we can compile RexExps with/without subpattern matching.
../WebCore:
* ForwardingHeaders/runtime/MatchResult.h: Added.
* ForwardingHeaders/yarr/YarrJIT.h: Added.
- Added forwarding headers.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@112454 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog
index 6c71762..088c44b 100644
--- a/Source/JavaScriptCore/ChangeLog
+++ b/Source/JavaScriptCore/ChangeLog
@@ -1,3 +1,89 @@
+2012-03-28 Gavin Barraclough <barraclough@apple.com>
+
+ Yarr: if we're not using the output array, don't populate it!
+ https://bugs.webkit.org/show_bug.cgi?id=82519
+
+ Reviewed by Sam Weinig.
+
+ Add a new variant of the match method to RegExp that returns a MatchResult,
+ and modify YarrJIT to be able to compile code that doesn't use an output vector.
+
+ This is a 3% progression on v8-regexp.
+
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ - Moved MatchResult into its own header.
+ * assembler/AbstractMacroAssembler.h:
+ - Added missing include.
+ * runtime/MatchResult.h: Added.
+ (MatchResult::MatchResult):
+ (MatchResult):
+ (MatchResult::failed):
+ (MatchResult::operator bool):
+ (MatchResult::empty):
+ - Moved MatchResult into its own header.
+ * runtime/RegExp.cpp:
+ (JSC::RegExp::compile):
+ (JSC::RegExp::compileIfNecessary):
+ (JSC::RegExp::match):
+ - Changed due to execute & representation changes.
+ (JSC::RegExp::compileMatchOnly):
+ (JSC::RegExp::compileIfNecessaryMatchOnly):
+ - Added helper to compile MatchOnly code.
+ (JSC::RegExp::invalidateCode):
+ (JSC::RegExp::matchCompareWithInterpreter):
+ (JSC::RegExp::printTraceData):
+ - Changed due representation changes.
+ * runtime/RegExp.h:
+ (RegExp):
+ (JSC::RegExp::hasCode):
+ - Made YarrCodeBlock a member.
+ * runtime/RegExpConstructor.h:
+ (RegExpConstructor):
+ (JSC::RegExpConstructor::performMatch):
+ - Added no-ovector form.
+ * runtime/RegExpMatchesArray.cpp:
+ (JSC::RegExpMatchesArray::reifyAllProperties):
+ - Match now takes a reference to ovector, not a pointer.
+ * runtime/RegExpObject.h:
+ (JSC):
+ - Moved MatchResult into its own header.
+ * runtime/StringPrototype.cpp:
+ (JSC::stringProtoFuncSplit):
+ - Match now takes a reference to ovector, not a pointer.
+ * testRegExp.cpp:
+ (testOneRegExp):
+ - Match now takes a reference to ovector, not a pointer.
+ * yarr/YarrJIT.cpp:
+ (Yarr):
+ (YarrGenerator):
+ (JSC::Yarr::YarrGenerator::initCallFrame):
+ (JSC::Yarr::YarrGenerator::removeCallFrame):
+ (JSC::Yarr::YarrGenerator::setSubpatternStart):
+ (JSC::Yarr::YarrGenerator::setSubpatternEnd):
+ (JSC::Yarr::YarrGenerator::clearSubpatternStart):
+ (JSC::Yarr::YarrGenerator::setMatchStart):
+ (JSC::Yarr::YarrGenerator::getMatchStart):
+ - Added helper functions to intermediate access to output.
+ (JSC::Yarr::YarrGenerator::generateDotStarEnclosure):
+ (JSC::Yarr::YarrGenerator::generate):
+ (JSC::Yarr::YarrGenerator::backtrack):
+ (JSC::Yarr::YarrGenerator::generateEnter):
+ (JSC::Yarr::YarrGenerator::compile):
+ - Changed to use the new helpers, only generate subpatterns if IncludeSubpatterns.
+ (JSC::Yarr::jitCompile):
+ - Needs to template of MatchOnly or IncludeSubpatterns.
+ * yarr/YarrJIT.h:
+ (YarrCodeBlock):
+ (JSC::Yarr::YarrCodeBlock::set8BitCode):
+ (JSC::Yarr::YarrCodeBlock::set16BitCode):
+ (JSC::Yarr::YarrCodeBlock::has8BitCodeMatchOnly):
+ (JSC::Yarr::YarrCodeBlock::has16BitCodeMatchOnly):
+ (JSC::Yarr::YarrCodeBlock::set8BitCodeMatchOnly):
+ (JSC::Yarr::YarrCodeBlock::set16BitCodeMatchOnly):
+ (JSC::Yarr::YarrCodeBlock::execute):
+ (JSC::Yarr::YarrCodeBlock::clear):
+ - Added a second set of CodeRefs, so that we can compile RexExps with/without subpattern matching.
+
2012-03-27 Filip Pizlo <fpizlo@apple.com>
DFG OSR exit should not generate an exit for variables of inlinees if the
diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def
index ea31dae..fb4a492 100644
--- a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def
+++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def
@@ -249,7 +249,7 @@
?lock@Mutex@WTF@@QAEXXZ
?lockAtomicallyInitializedStaticMutex@WTF@@YAXXZ
?lockCount@JSLock@JSC@@SAHXZ
- ?match@RegExp@JSC@@QAEHAAVJSGlobalData@2@ABVUString@2@IPAV?$Vector@H$0CA@@WTF@@@Z
+ ?match@RegExp@JSC@@QAEHAAVJSGlobalData@2@ABVUString@2@IAAV?$Vector@H$0CA@@WTF@@@Z
?materializePropertyMap@Structure@JSC@@AAEXAAVJSGlobalData@2@@Z
?monotonicallyIncreasingTime@WTF@@YANXZ
?monthFromDayInYear@WTF@@YAHH_N@Z
diff --git a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj b/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
index 7c11907..c26a34d 100644
--- a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
+++ b/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
@@ -337,6 +337,7 @@
860161E60F3A83C100F84710 /* MacroAssemblerX86Common.h in Headers */ = {isa = PBXBuildFile; fileRef = 860161E20F3A83C100F84710 /* MacroAssemblerX86Common.h */; };
8604F505143CE1C200B295F5 /* JSGlobalThis.h in Headers */ = {isa = PBXBuildFile; fileRef = 8604F503143CE1C100B295F5 /* JSGlobalThis.h */; settings = {ATTRIBUTES = (Private, ); }; };
860BD801148EA6F200112B2F /* Intrinsic.h in Headers */ = {isa = PBXBuildFile; fileRef = 86BF642A148DB2B5004DE36A /* Intrinsic.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 8612E4CD152389EC00C836BE /* MatchResult.h in Headers */ = {isa = PBXBuildFile; fileRef = 8612E4CB1522918400C836BE /* MatchResult.h */; settings = {ATTRIBUTES = (Private, ); }; };
863B23E00FC6118900703AA4 /* MacroAssemblerCodeRef.h in Headers */ = {isa = PBXBuildFile; fileRef = 863B23DF0FC60E6200703AA4 /* MacroAssemblerCodeRef.h */; settings = {ATTRIBUTES = (Private, ); }; };
863C6D9C1521111A00585E4E /* YarrCanonicalizeUCS2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 863C6D981521111200585E4E /* YarrCanonicalizeUCS2.cpp */; };
8642C510151C06A90046D4EF /* RegExpCachedResult.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86F75EFB151C062F007C9BA3 /* RegExpCachedResult.cpp */; };
@@ -350,7 +351,7 @@
86704B8412DBA33700A9FE7B /* YarrInterpreter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86704B7D12DBA33700A9FE7B /* YarrInterpreter.cpp */; };
86704B8512DBA33700A9FE7B /* YarrInterpreter.h in Headers */ = {isa = PBXBuildFile; fileRef = 86704B7E12DBA33700A9FE7B /* YarrInterpreter.h */; settings = {ATTRIBUTES = (Private, ); }; };
86704B8612DBA33700A9FE7B /* YarrJIT.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86704B7F12DBA33700A9FE7B /* YarrJIT.cpp */; };
- 86704B8712DBA33700A9FE7B /* YarrJIT.h in Headers */ = {isa = PBXBuildFile; fileRef = 86704B8012DBA33700A9FE7B /* YarrJIT.h */; settings = {ATTRIBUTES = (); }; };
+ 86704B8712DBA33700A9FE7B /* YarrJIT.h in Headers */ = {isa = PBXBuildFile; fileRef = 86704B8012DBA33700A9FE7B /* YarrJIT.h */; settings = {ATTRIBUTES = (Private, ); }; };
86704B8812DBA33700A9FE7B /* YarrParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 86704B8112DBA33700A9FE7B /* YarrParser.h */; settings = {ATTRIBUTES = (); }; };
86704B8912DBA33700A9FE7B /* YarrPattern.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86704B8212DBA33700A9FE7B /* YarrPattern.cpp */; };
86704B8A12DBA33700A9FE7B /* YarrPattern.h in Headers */ = {isa = PBXBuildFile; fileRef = 86704B8312DBA33700A9FE7B /* YarrPattern.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -463,7 +464,7 @@
A7521E131429169A003C8D0C /* CardSet.h in Headers */ = {isa = PBXBuildFile; fileRef = A7521E121429169A003C8D0C /* CardSet.h */; settings = {ATTRIBUTES = (Private, ); }; };
A75706DE118A2BCF0057F88F /* JITArithmetic32_64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A75706DD118A2BCF0057F88F /* JITArithmetic32_64.cpp */; };
A766B44F0EE8DCD1009518CA /* ExecutableAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = A7B48DB50EE74CFC00DCBDB6 /* ExecutableAllocator.h */; settings = {ATTRIBUTES = (Private, ); }; };
- A76C51761182748D00715B05 /* JSInterfaceJIT.h in Headers */ = {isa = PBXBuildFile; fileRef = A76C51741182748D00715B05 /* JSInterfaceJIT.h */; };
+ A76C51761182748D00715B05 /* JSInterfaceJIT.h in Headers */ = {isa = PBXBuildFile; fileRef = A76C51741182748D00715B05 /* JSInterfaceJIT.h */; settings = {ATTRIBUTES = (Private, ); }; };
A76F54A313B28AAB00EF2BCE /* JITWriteBarrier.h in Headers */ = {isa = PBXBuildFile; fileRef = A76F54A213B28AAB00EF2BCE /* JITWriteBarrier.h */; };
A781E359141970C700094D90 /* StorageBarrier.h in Headers */ = {isa = PBXBuildFile; fileRef = A781E358141970C700094D90 /* StorageBarrier.h */; settings = {ATTRIBUTES = (Private, ); }; };
A784A26111D16622005776AC /* ASTBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = A7A7EE7411B98B8D0065A14F /* ASTBuilder.h */; };
@@ -976,6 +977,7 @@
8603CEF314C7546400AE59E3 /* CodeProfiling.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeProfiling.h; sourceTree = "<group>"; };
8604F4F2143A6C4400B295F5 /* ChangeLog */ = {isa = PBXFileReference; lastKnownFileType = text; path = ChangeLog; sourceTree = "<group>"; };
8604F503143CE1C100B295F5 /* JSGlobalThis.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSGlobalThis.h; sourceTree = "<group>"; };
+ 8612E4CB1522918400C836BE /* MatchResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MatchResult.h; sourceTree = "<group>"; };
863B23DF0FC60E6200703AA4 /* MacroAssemblerCodeRef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MacroAssemblerCodeRef.h; sourceTree = "<group>"; };
863C6D981521111200585E4E /* YarrCanonicalizeUCS2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = YarrCanonicalizeUCS2.cpp; path = yarr/YarrCanonicalizeUCS2.cpp; sourceTree = "<group>"; };
863C6D991521111200585E4E /* YarrCanonicalizeUCS2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = YarrCanonicalizeUCS2.h; path = yarr/YarrCanonicalizeUCS2.h; sourceTree = "<group>"; };
@@ -1485,15 +1487,12 @@
1429D92C0ED22D7000B89619 /* jit */ = {
isa = PBXGroup;
children = (
- 0F0776BD14FF002800102332 /* JITCompilationEffort.h */,
- 0F4680D014BBC5F800BFE272 /* HostCallReturnValue.cpp */,
- 0F4680D114BBC5F800BFE272 /* HostCallReturnValue.h */,
- 0F46807F14BA572700BFE272 /* JITExceptions.cpp */,
- 0F46808014BA572700BFE272 /* JITExceptions.h */,
0FD82E37141AB14200179C94 /* CompactJITCodeMap.h */,
A7B48DB60EE74CFC00DCBDB6 /* ExecutableAllocator.cpp */,
A7B48DB50EE74CFC00DCBDB6 /* ExecutableAllocator.h */,
86DB64630F95C6FC00D7D921 /* ExecutableAllocatorFixedVMPool.cpp */,
+ 0F4680D014BBC5F800BFE272 /* HostCallReturnValue.cpp */,
+ 0F4680D114BBC5F800BFE272 /* HostCallReturnValue.h */,
1429D92D0ED22D7000B89619 /* JIT.cpp */,
1429D92E0ED22D7000B89619 /* JIT.h */,
86A90ECF0EE7D51F00AB350D /* JITArithmetic.cpp */,
@@ -1501,7 +1500,10 @@
86CC85A20EE79B7400288682 /* JITCall.cpp */,
146FE51111A710430087AE66 /* JITCall32_64.cpp */,
86CCEFDD0F413F8900FD7F9E /* JITCode.h */,
+ 0F0776BD14FF002800102332 /* JITCompilationEffort.h */,
0F21C26614BE5F5E00ADC64B /* JITDriver.h */,
+ 0F46807F14BA572700BFE272 /* JITExceptions.cpp */,
+ 0F46808014BA572700BFE272 /* JITExceptions.h */,
86CC85A00EE79A4700288682 /* JITInlineMethods.h */,
BCDD51E90FB8DF74004A8BDC /* JITOpcodes.cpp */,
A71236E41195F33C00BD2174 /* JITOpcodes32_64.cpp */,
@@ -1851,6 +1853,7 @@
A7E2EA690FB460CF00601F06 /* LiteralParser.h */,
F692A8680255597D01FF60F7 /* Lookup.cpp */,
F692A8690255597D01FF60F7 /* Lookup.h */,
+ 8612E4CB1522918400C836BE /* MatchResult.h */,
F692A86A0255597D01FF60F7 /* MathObject.cpp */,
F692A86B0255597D01FF60F7 /* MathObject.h */,
90213E3B123A40C200D422F3 /* MemoryStatistics.cpp */,
@@ -2512,6 +2515,7 @@
0F2BDC16151C5D4F00CD8910 /* DFGFixupPhase.h in Headers */,
0F2BDC21151E803B00CD8910 /* DFGInsertionSet.h in Headers */,
0F2BDC2C151FDE9100CD8910 /* Operands.h in Headers */,
+ 8612E4CD152389EC00C836BE /* MatchResult.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
diff --git a/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h b/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h
index 5f8a150..269b6be 100644
--- a/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h
+++ b/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h
@@ -26,6 +26,7 @@
#ifndef AbstractMacroAssembler_h
#define AbstractMacroAssembler_h
+#include "AssemblerBuffer.h"
#include "CodeLocation.h"
#include "MacroAssemblerCodeRef.h"
#include <wtf/CryptographicallyRandomNumber.h>
diff --git a/Source/JavaScriptCore/runtime/MatchResult.h b/Source/JavaScriptCore/runtime/MatchResult.h
new file mode 100644
index 0000000..d87c851
--- /dev/null
+++ b/Source/JavaScriptCore/runtime/MatchResult.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef MatchResult_h
+#define MatchResult_h
+
+typedef uint64_t EncodedMatchResult;
+
+struct MatchResult {
+ ALWAYS_INLINE MatchResult(size_t start, size_t end)
+ : start(start)
+ , end(end)
+ {
+ }
+
+ explicit ALWAYS_INLINE MatchResult(EncodedMatchResult encoded)
+ {
+ union u {
+ uint64_t encoded;
+ struct s {
+ size_t start;
+ size_t end;
+ } split;
+ } value;
+ value.encoded = encoded;
+ start = value.split.start;
+ end = value.split.end;
+ }
+
+ ALWAYS_INLINE static MatchResult failed()
+ {
+ return MatchResult(WTF::notFound, 0);
+ }
+
+ ALWAYS_INLINE operator bool()
+ {
+ return start != WTF::notFound;
+ }
+
+ ALWAYS_INLINE bool empty()
+ {
+ return start == end;
+ }
+
+ size_t start;
+ size_t end;
+};
+
+#endif
diff --git a/Source/JavaScriptCore/runtime/RegExp.cpp b/Source/JavaScriptCore/runtime/RegExp.cpp
index 4ad2828..a1f09af 100644
--- a/Source/JavaScriptCore/runtime/RegExp.cpp
+++ b/Source/JavaScriptCore/runtime/RegExp.cpp
@@ -218,10 +218,6 @@
#endif
struct RegExpRepresentation {
-#if ENABLE(YARR_JIT)
- Yarr::YarrCodeBlock m_regExpJITCode;
-#endif
- OwnPtr<Yarr::BytecodePattern> m_regExpBytecode;
};
RegExp::RegExp(JSGlobalData& globalData, const UString& patternString, RegExpFlags flags)
@@ -279,23 +275,22 @@
}
ASSERT(m_numSubpatterns == pattern.m_numSubpatterns);
- if (!m_representation) {
+ if (!hasCode()) {
ASSERT(m_state == NotCompiled);
- m_representation = adoptPtr(new RegExpRepresentation);
globalData->regExpCache()->addToStrongCache(this);
m_state = ByteCode;
}
#if ENABLE(YARR_JIT)
if (!pattern.m_containsBackreferences && globalData->canUseJIT()) {
- Yarr::jitCompile(pattern, charSize, globalData, m_representation->m_regExpJITCode);
+ Yarr::jitCompile(pattern, charSize, globalData, m_regExpJITCode);
#if ENABLE(YARR_JIT_DEBUG)
- if (!m_representation->m_regExpJITCode.isFallBack())
+ if (!m_regExpJITCode.isFallBack())
m_state = JITCode;
else
m_state = ByteCode;
#else
- if (!m_representation->m_regExpJITCode.isFallBack()) {
+ if (!m_regExpJITCode.isFallBack()) {
m_state = JITCode;
return;
}
@@ -305,22 +300,18 @@
UNUSED_PARAM(charSize);
#endif
- m_representation->m_regExpBytecode = Yarr::byteCompile(pattern, &globalData->m_regExpAllocator);
+ m_regExpBytecode = Yarr::byteCompile(pattern, &globalData->m_regExpAllocator);
}
void RegExp::compileIfNecessary(JSGlobalData& globalData, Yarr::YarrCharSize charSize)
{
- // If the state is NotCompiled or ParseError, then there is no representation.
- // If there is a representation, and the state must be either JITCode or ByteCode.
- ASSERT(!!m_representation == (m_state == JITCode || m_state == ByteCode));
-
- if (m_representation) {
+ if (hasCode()) {
#if ENABLE(YARR_JIT)
if (m_state != JITCode)
return;
- if ((charSize == Yarr::Char8) && (m_representation->m_regExpJITCode.has8BitCode()))
+ if ((charSize == Yarr::Char8) && (m_regExpJITCode.has8BitCode()))
return;
- if ((charSize == Yarr::Char16) && (m_representation->m_regExpJITCode.has16BitCode()))
+ if ((charSize == Yarr::Char16) && (m_regExpJITCode.has16BitCode()))
return;
#else
return;
@@ -330,7 +321,7 @@
compile(&globalData, charSize);
}
-int RegExp::match(JSGlobalData& globalData, const UString& s, unsigned startOffset, Vector<int, 32>* ovector)
+int RegExp::match(JSGlobalData& globalData, const UString& s, unsigned startOffset, Vector<int, 32>& ovector)
{
#if ENABLE(REGEXP_TRACING)
m_rtMatchCallCount++;
@@ -340,30 +331,22 @@
compileIfNecessary(globalData, s.is8Bit() ? Yarr::Char8 : Yarr::Char16);
int offsetVectorSize = (m_numSubpatterns + 1) * 2;
- int* offsetVector;
- Vector<int, 32> nonReturnedOvector;
- if (ovector) {
- ovector->resize(offsetVectorSize);
- offsetVector = ovector->data();
- } else {
- nonReturnedOvector.resize(offsetVectorSize);
- offsetVector = nonReturnedOvector.data();
- }
- ASSERT(offsetVector);
+ ovector.resize(offsetVectorSize);
+ int* offsetVector = ovector.data();
int result;
#if ENABLE(YARR_JIT)
if (m_state == JITCode) {
if (s.is8Bit())
- result = Yarr::execute(m_representation->m_regExpJITCode, s.characters8(), startOffset, s.length(), offsetVector);
+ result = m_regExpJITCode.execute(s.characters8(), startOffset, s.length(), offsetVector).start;
else
- result = Yarr::execute(m_representation->m_regExpJITCode, s.characters16(), startOffset, s.length(), offsetVector);
+ 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_representation->m_regExpBytecode.get(), s, startOffset, s.length(), reinterpret_cast<unsigned*>(offsetVector));
+ result = Yarr::interpret(m_regExpBytecode.get(), s, startOffset, s.length(), 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.
@@ -404,12 +387,111 @@
return result;
}
+void RegExp::compileMatchOnly(JSGlobalData* globalData, Yarr::YarrCharSize charSize)
+{
+ Yarr::YarrPattern pattern(m_patternString, ignoreCase(), multiline(), &m_constructionError);
+ if (m_constructionError) {
+ ASSERT_NOT_REACHED();
+ m_state = ParseError;
+ return;
+ }
+ ASSERT(m_numSubpatterns == pattern.m_numSubpatterns);
+
+ if (!hasCode()) {
+ ASSERT(m_state == NotCompiled);
+ globalData->regExpCache()->addToStrongCache(this);
+ m_state = ByteCode;
+ }
+
+#if ENABLE(YARR_JIT)
+ if (!pattern.m_containsBackreferences && globalData->canUseJIT()) {
+ Yarr::jitCompile(pattern, charSize, globalData, m_regExpJITCode, Yarr::MatchOnly);
+#if ENABLE(YARR_JIT_DEBUG)
+ if (!m_regExpJITCode.isFallBack())
+ m_state = JITCode;
+ else
+ m_state = ByteCode;
+#else
+ if (!m_regExpJITCode.isFallBack()) {
+ m_state = JITCode;
+ return;
+ }
+#endif
+ }
+#else
+ UNUSED_PARAM(charSize);
+#endif
+
+ m_regExpBytecode = Yarr::byteCompile(pattern, &globalData->m_regExpAllocator);
+}
+
+void RegExp::compileIfNecessaryMatchOnly(JSGlobalData& globalData, 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(&globalData, charSize);
+}
+
+MatchResult RegExp::match(JSGlobalData& globalData, const UString& s, unsigned startOffset)
+{
+#if ENABLE(REGEXP_TRACING)
+ m_rtMatchCallCount++;
+#endif
+
+ ASSERT(m_state != ParseError);
+ compileIfNecessaryMatchOnly(globalData, 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_rtMatchFoundCount++;
+#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, s.length(), 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_rtMatchFoundCount++;
+#endif
+ return MatchResult(r, reinterpret_cast<unsigned*>(offsetVector)[1]);
+ }
+
+ return MatchResult::failed();
+}
+
void RegExp::invalidateCode()
{
- if (!m_representation)
+ if (!hasCode())
return;
m_state = NotCompiled;
- m_representation.clear();
+ m_regExpJITCode.clear();
+ m_regExpBytecode.clear();
}
#if ENABLE(YARR_JIT_DEBUG)
@@ -428,7 +510,7 @@
for (unsigned j = 0, i = 0; i < m_numSubpatterns + 1; j += 2, i++)
interpreterOffsetVector[j] = -1;
- interpreterResult = Yarr::interpret(m_representation->m_regExpBytecode.get(), s, startOffset, s.length(), interpreterOffsetVector);
+ interpreterResult = Yarr::interpret(m_regExpBytecode.get(), s, startOffset, s.length(), interpreterOffsetVector);
if (jitResult != interpreterResult)
differences++;
@@ -477,7 +559,7 @@
snprintf(formattedPattern, 41, (pattLen <= 38) ? "/%.38s/" : "/%.36s...", rawPattern);
#if ENABLE(YARR_JIT)
- Yarr::YarrCodeBlock& codeBlock = m_representation->m_regExpJITCode;
+ Yarr::YarrCodeBlock& codeBlock = m_regExpJITCode;
const size_t jitAddrSize = 20;
char jitAddr[jitAddrSize];
diff --git a/Source/JavaScriptCore/runtime/RegExp.h b/Source/JavaScriptCore/runtime/RegExp.h
index d0201cb..ad10203 100644
--- a/Source/JavaScriptCore/runtime/RegExp.h
+++ b/Source/JavaScriptCore/runtime/RegExp.h
@@ -22,14 +22,19 @@
#ifndef RegExp_h
#define RegExp_h
-#include "UString.h"
#include "ExecutableAllocator.h"
-#include "Structure.h"
+#include "MatchResult.h"
#include "RegExpKey.h"
+#include "Structure.h"
+#include "UString.h"
#include "yarr/Yarr.h"
#include <wtf/Forward.h>
#include <wtf/RefCounted.h>
+#if ENABLE(YARR_JIT)
+#include "yarr/YarrJIT.h"
+#endif
+
namespace JSC {
struct RegExpRepresentation;
@@ -53,12 +58,13 @@
bool isValid() const { return !m_constructionError && m_flags != InvalidFlags; }
const char* errorMessage() const { return m_constructionError; }
- JS_EXPORT_PRIVATE int match(JSGlobalData&, const UString&, unsigned startOffset, Vector<int, 32>* ovector = 0);
+ JS_EXPORT_PRIVATE int match(JSGlobalData&, const UString&, unsigned startOffset, Vector<int, 32>& ovector);
+ MatchResult match(JSGlobalData&, const UString&, unsigned startOffset);
unsigned numSubpatterns() const { return m_numSubpatterns; }
bool hasCode()
{
- return m_representation;
+ return m_state != NotCompiled;
}
void invalidateCode();
@@ -95,6 +101,9 @@
void compile(JSGlobalData*, Yarr::YarrCharSize);
void compileIfNecessary(JSGlobalData&, Yarr::YarrCharSize);
+ void compileMatchOnly(JSGlobalData*, Yarr::YarrCharSize);
+ void compileIfNecessaryMatchOnly(JSGlobalData&, Yarr::YarrCharSize);
+
#if ENABLE(YARR_JIT_DEBUG)
void matchCompareWithInterpreter(const UString&, int startOffset, int* offsetVector, int jitResult);
#endif
@@ -108,7 +117,10 @@
unsigned m_rtMatchFoundCount;
#endif
- OwnPtr<RegExpRepresentation> m_representation;
+#if ENABLE(YARR_JIT)
+ Yarr::YarrCodeBlock m_regExpJITCode;
+#endif
+ OwnPtr<Yarr::BytecodePattern> m_regExpBytecode;
};
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/RegExpConstructor.h b/Source/JavaScriptCore/runtime/RegExpConstructor.h
index 724dc23..0093f94 100644
--- a/Source/JavaScriptCore/runtime/RegExpConstructor.h
+++ b/Source/JavaScriptCore/runtime/RegExpConstructor.h
@@ -55,7 +55,8 @@
static const ClassInfo s_info;
- MatchResult performMatch(JSGlobalData&, RegExp*, JSString*, const UString&, int startOffset, int** ovector = 0);
+ MatchResult performMatch(JSGlobalData&, RegExp*, JSString*, const UString&, int startOffset, int** ovector);
+ MatchResult performMatch(JSGlobalData&, RegExp*, JSString*, const UString&, int startOffset);
void setMultiline(bool multiline) { m_multiline = multiline; }
bool multiline() const { return m_multiline; }
@@ -102,7 +103,7 @@
*/
ALWAYS_INLINE MatchResult RegExpConstructor::performMatch(JSGlobalData& globalData, RegExp* regExp, JSString* string, const UString& input, int startOffset, int** ovector)
{
- int position = regExp->match(globalData, input, startOffset, &m_ovector);
+ int position = regExp->match(globalData, input, startOffset, m_ovector);
if (ovector)
*ovector = m_ovector.data();
@@ -119,6 +120,13 @@
return MatchResult(position, end);
}
+ ALWAYS_INLINE MatchResult RegExpConstructor::performMatch(JSGlobalData& globalData, RegExp* regExp, JSString* string, const UString& input, int startOffset)
+ {
+ MatchResult result = regExp->match(globalData, input, startOffset);
+ if (result)
+ m_cachedResult.record(globalData, this, regExp, string, result);
+ return result;
+ }
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/RegExpMatchesArray.cpp b/Source/JavaScriptCore/runtime/RegExpMatchesArray.cpp
index ce52453..80f1068 100644
--- a/Source/JavaScriptCore/runtime/RegExpMatchesArray.cpp
+++ b/Source/JavaScriptCore/runtime/RegExpMatchesArray.cpp
@@ -58,7 +58,7 @@
if (unsigned numSubpatterns = m_regExp->numSubpatterns()) {
Vector<int, 32> subpatternResults;
- int position = m_regExp->match(exec->globalData(), m_input->value(exec), m_result.start, &subpatternResults);
+ int position = m_regExp->match(exec->globalData(), m_input->value(exec), m_result.start, subpatternResults);
ASSERT_UNUSED(position, position >= 0 && static_cast<size_t>(position) == m_result.start);
ASSERT(m_result.start == static_cast<size_t>(subpatternResults[0]));
ASSERT(m_result.end == static_cast<size_t>(subpatternResults[1]));
diff --git a/Source/JavaScriptCore/runtime/RegExpObject.h b/Source/JavaScriptCore/runtime/RegExpObject.h
index c3ece6e..a7dd547 100644
--- a/Source/JavaScriptCore/runtime/RegExpObject.h
+++ b/Source/JavaScriptCore/runtime/RegExpObject.h
@@ -26,28 +26,6 @@
namespace JSC {
- struct MatchResult {
- ALWAYS_INLINE MatchResult(size_t start, size_t end)
- : start(start)
- , end(end)
- {
- }
- ALWAYS_INLINE static MatchResult failed()
- {
- return MatchResult(WTF::notFound, 0);
- }
- ALWAYS_INLINE operator bool()
- {
- return start != WTF::notFound;
- }
- ALWAYS_INLINE bool empty()
- {
- return start == end;
- }
- size_t start;
- size_t end;
- };
-
class RegExpObject : public JSNonFinalObject {
public:
typedef JSNonFinalObject Base;
diff --git a/Source/JavaScriptCore/runtime/StringPrototype.cpp b/Source/JavaScriptCore/runtime/StringPrototype.cpp
index 27c4fbd..64014ba 100644
--- a/Source/JavaScriptCore/runtime/StringPrototype.cpp
+++ b/Source/JavaScriptCore/runtime/StringPrototype.cpp
@@ -963,7 +963,7 @@
// c. Call the [[DefineOwnProperty]] internal method of A with arguments "0",
// Property Descriptor {[[Value]]: S, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, and false.
// d. Return A.
- if (reg->match(*globalData, input, 0) < 0)
+ if (!reg->match(*globalData, input, 0))
result->putDirectIndex(exec, 0, jsStringWithReuse(exec, thisValue, input), false);
return JSValue::encode(result);
}
@@ -974,7 +974,7 @@
while (matchPosition < input.length()) {
// a. Call SplitMatch(S, q, R) and let z be its MatchResult result.
Vector<int, 32> ovector;
- int mpos = reg->match(*globalData, input, matchPosition, &ovector);
+ int mpos = reg->match(*globalData, input, matchPosition, ovector);
// b. If z is failure, then let q = q + 1.
if (mpos < 0)
break;
diff --git a/Source/JavaScriptCore/testRegExp.cpp b/Source/JavaScriptCore/testRegExp.cpp
index 435da59..5502ed3 100644
--- a/Source/JavaScriptCore/testRegExp.cpp
+++ b/Source/JavaScriptCore/testRegExp.cpp
@@ -215,7 +215,7 @@
bool result = true;
Vector<int, 32> outVector;
outVector.resize(regExpTest->expectVector.size());
- int matchResult = regexp->match(globalData, regExpTest->subject, regExpTest->offset, &outVector);
+ int matchResult = regexp->match(globalData, regExpTest->subject, regExpTest->offset, outVector);
if (matchResult != regExpTest->result) {
result = false;
diff --git a/Source/JavaScriptCore/yarr/YarrJIT.cpp b/Source/JavaScriptCore/yarr/YarrJIT.cpp
index f93d5ed..95c9952 100644
--- a/Source/JavaScriptCore/yarr/YarrJIT.cpp
+++ b/Source/JavaScriptCore/yarr/YarrJIT.cpp
@@ -37,6 +37,7 @@
namespace JSC { namespace Yarr {
+template<YarrJITCompileMode compileMode>
class YarrGenerator : private MacroAssembler {
friend void jitCompile(JSGlobalData*, YarrCodeBlock& jitObject, const UString& pattern, unsigned& numSubpatterns, const char*& error, bool ignoreCase, bool multiline);
@@ -50,6 +51,7 @@
static const RegisterID regT1 = ARMRegisters::r6;
static const RegisterID returnRegister = ARMRegisters::r0;
+ static const RegisterID returnRegister2 = ARMRegisters::r1;
#elif CPU(MIPS)
static const RegisterID input = MIPSRegisters::a0;
static const RegisterID index = MIPSRegisters::a1;
@@ -60,6 +62,7 @@
static const RegisterID regT1 = MIPSRegisters::t5;
static const RegisterID returnRegister = MIPSRegisters::v0;
+ static const RegisterID returnRegister2 = MIPSRegisters::v1;
#elif CPU(SH4)
static const RegisterID input = SH4Registers::r4;
static const RegisterID index = SH4Registers::r5;
@@ -70,6 +73,7 @@
static const RegisterID regT1 = SH4Registers::r1;
static const RegisterID returnRegister = SH4Registers::r0;
+ static const RegisterID returnRegister2 = SH4Registers::r1;
#elif CPU(X86)
static const RegisterID input = X86Registers::eax;
static const RegisterID index = X86Registers::edx;
@@ -80,6 +84,7 @@
static const RegisterID regT1 = X86Registers::esi;
static const RegisterID returnRegister = X86Registers::eax;
+ static const RegisterID returnRegister2 = X86Registers::edx;
#elif CPU(X86_64)
static const RegisterID input = X86Registers::edi;
static const RegisterID index = X86Registers::esi;
@@ -90,6 +95,7 @@
static const RegisterID regT1 = X86Registers::ebx;
static const RegisterID returnRegister = X86Registers::eax;
+ static const RegisterID returnRegister2 = X86Registers::edx;
#endif
void optimizeAlternative(PatternAlternative* alternative)
@@ -305,6 +311,65 @@
jump(Address(stackPointerRegister, frameLocation * sizeof(void*)));
}
+ void initCallFrame()
+ {
+ unsigned callFrameSize = m_pattern.m_body->m_callFrameSize;
+ if (callFrameSize)
+ subPtr(Imm32(callFrameSize * sizeof(void*)), stackPointerRegister);
+ }
+ void removeCallFrame()
+ {
+ unsigned callFrameSize = m_pattern.m_body->m_callFrameSize;
+ if (callFrameSize)
+ addPtr(Imm32(callFrameSize * sizeof(void*)), stackPointerRegister);
+ }
+
+ // Used to record subpatters, should only be called if compileMode is IncludeSubpatterns.
+ void setSubpatternStart(RegisterID reg, unsigned subpattern)
+ {
+ ASSERT(subpattern);
+ ASSERT(compileMode == IncludeSubpatterns);
+ store32(reg, Address(output, (subpattern << 1) * sizeof(int)));
+ }
+ void setSubpatternEnd(RegisterID reg, unsigned subpattern)
+ {
+ ASSERT(subpattern);
+ ASSERT(compileMode == IncludeSubpatterns);
+ store32(reg, Address(output, ((subpattern << 1) + 1) * sizeof(int)));
+ }
+ void clearSubpatternStart(unsigned subpattern)
+ {
+ ASSERT(subpattern);
+ ASSERT(compileMode == IncludeSubpatterns);
+ store32(TrustedImm32(-1), Address(output, (subpattern << 1) * sizeof(int)));
+ }
+
+ // We use one of three different strategies to track the start of the current match,
+ // while matching.
+ // 1) If the pattern has a fixed size, do nothing! - we calculate the value lazily
+ // at the end of matching. This is irrespective of compileMode, and in this case
+ // these methods should never be called.
+ // 2) If we're compiling IncludeSubpatterns, 'output' contains a pointer to an output
+ // vector, store the match start in the output vector.
+ // 3) If we're compiling MatchOnly, 'output' is unused, store the match start directly
+ // in this register.
+ void setMatchStart(RegisterID reg)
+ {
+ ASSERT(!m_pattern.m_body->m_hasFixedSize);
+ if (compileMode == IncludeSubpatterns)
+ store32(reg, output);
+ else
+ move(reg, output);
+ }
+ void getMatchStart(RegisterID reg)
+ {
+ ASSERT(!m_pattern.m_body->m_hasFixedSize);
+ if (compileMode == IncludeSubpatterns)
+ load32(output, reg);
+ else
+ move(output, reg);
+ }
+
enum YarrOpCode {
// These nodes wrap body alternatives - those in the main disjunction,
// rather than subpatterns or assertions. These are chained together in
@@ -1069,11 +1134,8 @@
JumpList saveStartIndex;
JumpList foundEndingNewLine;
- if (m_pattern.m_body->m_hasFixedSize) {
- move(index, matchPos);
- sub32(Imm32(m_checked), matchPos);
- } else
- load32(Address(output), matchPos);
+ ASSERT(!m_pattern.m_body->m_hasFixedSize);
+ getMatchStart(matchPos);
saveStartIndex.append(branchTest32(Zero, matchPos));
Label findBOLLoop(this);
@@ -1093,7 +1155,8 @@
if (!m_pattern.m_multiline && term->anchors.bolAnchor)
op.m_jumps.append(branchTest32(NonZero, matchPos));
- store32(matchPos, Address(output));
+ ASSERT(!m_pattern.m_body->m_hasFixedSize);
+ setMatchStart(matchPos);
move(index, matchPos);
@@ -1315,8 +1378,7 @@
// If we get here, the prior alternative matched - return success.
// Adjust the stack pointer to remove the pattern's frame.
- if (m_pattern.m_body->m_callFrameSize)
- addPtr(Imm32(m_pattern.m_body->m_callFrameSize * sizeof(void*)), stackPointerRegister);
+ removeCallFrame();
// Load appropriate values into the return register and the first output
// slot, and return. In the case of pattern with a fixed size, we will
@@ -1326,10 +1388,14 @@
move(index, returnRegister);
if (priorAlternative->m_minimumSize)
sub32(Imm32(priorAlternative->m_minimumSize), returnRegister);
- store32(returnRegister, output);
+ if (compileMode == IncludeSubpatterns)
+ store32(returnRegister, output);
} else
- load32(Address(output), returnRegister);
- store32(index, Address(output, 4));
+ getMatchStart(returnRegister);
+ if (compileMode == IncludeSubpatterns)
+ store32(index, Address(output, 4));
+ move(index, returnRegister2);
+
generateReturn();
// This is the divide between the tail of the prior alternative, above, and
@@ -1512,17 +1578,16 @@
// FIXME: could avoid offsetting this value in JIT code, apply
// offsets only afterwards, at the point the results array is
// being accessed.
- if (term->capture()) {
- int offsetId = term->parentheses.subpatternId << 1;
+ if (term->capture() && compileMode == IncludeSubpatterns) {
int inputOffset = term->inputPosition - m_checked;
if (term->quantityType == QuantifierFixedCount)
inputOffset -= term->parentheses.disjunction->m_minimumSize;
if (inputOffset) {
move(index, indexTemporary);
add32(Imm32(inputOffset), indexTemporary);
- store32(indexTemporary, Address(output, offsetId * sizeof(int)));
+ setSubpatternStart(indexTemporary, term->parentheses.subpatternId);
} else
- store32(index, Address(output, offsetId * sizeof(int)));
+ setSubpatternStart(index, term->parentheses.subpatternId);
}
break;
}
@@ -1548,15 +1613,14 @@
// FIXME: could avoid offsetting this value in JIT code, apply
// offsets only afterwards, at the point the results array is
// being accessed.
- if (term->capture()) {
- int offsetId = (term->parentheses.subpatternId << 1) + 1;
+ if (term->capture() && compileMode == IncludeSubpatterns) {
int inputOffset = term->inputPosition - m_checked;
if (inputOffset) {
move(index, indexTemporary);
add32(Imm32(inputOffset), indexTemporary);
- store32(indexTemporary, Address(output, offsetId * sizeof(int)));
+ setSubpatternEnd(indexTemporary, term->parentheses.subpatternId);
} else
- store32(index, Address(output, offsetId * sizeof(int)));
+ setSubpatternEnd(index, term->parentheses.subpatternId);
}
// If the parentheses are quantified Greedy then add a label to jump back
@@ -1646,9 +1710,9 @@
}
case OpMatchFailed:
- if (m_pattern.m_body->m_callFrameSize)
- addPtr(Imm32(m_pattern.m_body->m_callFrameSize * sizeof(void*)), stackPointerRegister);
- move(TrustedImm32(-1), returnRegister);
+ removeCallFrame();
+ move(TrustedImmPtr((void*)WTF::notFound), returnRegister);
+ move(TrustedImm32(0), returnRegister2);
generateReturn();
break;
}
@@ -1743,14 +1807,14 @@
// If the pattern size is not fixed, then store the start index, for use if we match.
if (!m_pattern.m_body->m_hasFixedSize) {
if (alternative->m_minimumSize == 1)
- store32(index, Address(output));
+ setMatchStart(index);
else {
move(index, regT0);
if (alternative->m_minimumSize)
sub32(Imm32(alternative->m_minimumSize - 1), regT0);
else
add32(TrustedImm32(1), regT0);
- store32(regT0, Address(output));
+ setMatchStart(regT0);
}
}
@@ -1836,7 +1900,7 @@
// disjunction is 0, e.g. /a*|b/).
if (needsToUpdateMatchStart && alternative->m_minimumSize == 1) {
// index is already incremented by 1, so just store it now!
- store32(index, Address(output));
+ setMatchStart(index);
needsToUpdateMatchStart = false;
}
@@ -1860,11 +1924,11 @@
if (needsToUpdateMatchStart) {
if (!m_pattern.m_body->m_minimumSize)
- store32(index, Address(output));
+ setMatchStart(index);
else {
move(index, regT0);
sub32(Imm32(m_pattern.m_body->m_minimumSize), regT0);
- store32(regT0, Address(output));
+ setMatchStart(regT0);
}
}
@@ -1886,9 +1950,9 @@
// run any matches, and need to return a failure state from JIT code.
matchFailed.link(this);
- if (m_pattern.m_body->m_callFrameSize)
- addPtr(Imm32(m_pattern.m_body->m_callFrameSize * sizeof(void*)), stackPointerRegister);
- move(TrustedImm32(-1), returnRegister);
+ removeCallFrame();
+ move(TrustedImmPtr((void*)WTF::notFound), returnRegister);
+ move(TrustedImm32(0), returnRegister2);
generateReturn();
break;
}
@@ -2055,12 +2119,12 @@
ASSERT(term->quantityCount == 1);
// We only need to backtrack to thispoint if capturing or greedy.
- if (term->capture() || term->quantityType == QuantifierGreedy) {
+ if ((term->capture() && compileMode == IncludeSubpatterns) || term->quantityType == QuantifierGreedy) {
m_backtrackingState.link(this);
// If capturing, clear the capture (we only need to reset start).
- if (term->capture())
- store32(TrustedImm32(-1), Address(output, (term->parentheses.subpatternId << 1) * sizeof(int)));
+ if (term->capture() && compileMode == IncludeSubpatterns)
+ clearSubpatternStart(term->parentheses.subpatternId);
// If Greedy, jump to the end.
if (term->quantityType == QuantifierGreedy) {
@@ -2450,9 +2514,11 @@
loadPtr(Address(X86Registers::ebp, 2 * sizeof(void*)), input);
loadPtr(Address(X86Registers::ebp, 3 * sizeof(void*)), index);
loadPtr(Address(X86Registers::ebp, 4 * sizeof(void*)), length);
- loadPtr(Address(X86Registers::ebp, 5 * sizeof(void*)), output);
+ if (compileMode == IncludeSubpatterns)
+ loadPtr(Address(X86Registers::ebp, 5 * sizeof(void*)), output);
#else
- loadPtr(Address(X86Registers::ebp, 2 * sizeof(void*)), output);
+ if (compileMode == IncludeSubpatterns)
+ loadPtr(Address(X86Registers::ebp, 2 * sizeof(void*)), output);
#endif
#elif CPU(ARM)
push(ARMRegisters::r4);
@@ -2461,7 +2527,8 @@
#if CPU(ARM_TRADITIONAL)
push(ARMRegisters::r8); // scratch register
#endif
- move(ARMRegisters::r3, output);
+ if (compileMode == IncludeSubpatterns)
+ move(ARMRegisters::r3, output);
#elif CPU(SH4)
push(SH4Registers::r11);
push(SH4Registers::r13);
@@ -2511,18 +2578,20 @@
generateEnter();
Jump hasInput = checkInput();
- move(TrustedImm32(-1), returnRegister);
+ move(TrustedImmPtr((void*)WTF::notFound), returnRegister);
+ move(TrustedImm32(0), returnRegister2);
generateReturn();
hasInput.link(this);
- for (unsigned i = 0; i < m_pattern.m_numSubpatterns + 1; ++i)
- store32(TrustedImm32(-1), Address(output, (i << 1) * sizeof(int)));
+ if (compileMode == IncludeSubpatterns) {
+ for (unsigned i = 0; i < m_pattern.m_numSubpatterns + 1; ++i)
+ store32(TrustedImm32(-1), Address(output, (i << 1) * sizeof(int)));
+ }
if (!m_pattern.m_body->m_hasFixedSize)
- store32(index, Address(output));
+ setMatchStart(index);
- if (m_pattern.m_body->m_callFrameSize)
- subPtr(Imm32(m_pattern.m_body->m_callFrameSize * sizeof(void*)), stackPointerRegister);
+ initCallFrame();
// Compile the pattern to the internal 'YarrOp' representation.
opCompileBody(m_pattern.m_body);
@@ -2540,10 +2609,18 @@
// Link & finalize the code.
LinkBuffer linkBuffer(*globalData, this, REGEXP_CODE_ID);
m_backtrackingState.linkDataLabels(linkBuffer);
- if (m_charSize == Char8)
- jitObject.set8BitCode(linkBuffer.finalizeCode());
- else
- jitObject.set16BitCode(linkBuffer.finalizeCode());
+
+ if (compileMode == MatchOnly) {
+ if (m_charSize == Char8)
+ jitObject.set8BitCodeMatchOnly(linkBuffer.finalizeCode());
+ else
+ jitObject.set16BitCodeMatchOnly(linkBuffer.finalizeCode());
+ } else {
+ if (m_charSize == Char8)
+ jitObject.set8BitCode(linkBuffer.finalizeCode());
+ else
+ jitObject.set16BitCode(linkBuffer.finalizeCode());
+ }
jitObject.setFallBack(m_shouldFallBack);
}
@@ -2577,9 +2654,12 @@
BacktrackingState m_backtrackingState;
};
-void jitCompile(YarrPattern& pattern, YarrCharSize charSize, JSGlobalData* globalData, YarrCodeBlock& jitObject)
+void jitCompile(YarrPattern& pattern, YarrCharSize charSize, JSGlobalData* globalData, YarrCodeBlock& jitObject, YarrJITCompileMode mode)
{
- YarrGenerator(pattern, charSize).compile(globalData, jitObject);
+ if (mode == MatchOnly)
+ YarrGenerator<MatchOnly>(pattern, charSize).compile(globalData, jitObject);
+ else
+ YarrGenerator<IncludeSubpatterns>(pattern, charSize).compile(globalData, jitObject);
}
}}
diff --git a/Source/JavaScriptCore/yarr/YarrJIT.h b/Source/JavaScriptCore/yarr/YarrJIT.h
index 38ae76c..71928e7 100644
--- a/Source/JavaScriptCore/yarr/YarrJIT.h
+++ b/Source/JavaScriptCore/yarr/YarrJIT.h
@@ -29,7 +29,8 @@
#if ENABLE(YARR_JIT)
#include "JSGlobalData.h"
-#include "MacroAssembler.h"
+#include "MacroAssemblerCodeRef.h"
+#include "MatchResult.h"
#include "UString.h"
#include "Yarr.h"
#include "YarrPattern.h"
@@ -48,8 +49,17 @@
namespace Yarr {
class YarrCodeBlock {
- typedef int (*YarrJITCode8)(const LChar* input, unsigned start, unsigned length, int* output) YARR_CALL;
- typedef int (*YarrJITCode16)(const UChar* input, unsigned start, unsigned length, int* output) YARR_CALL;
+#if CPU(X86_64)
+ typedef MatchResult (*YarrJITCode8)(const LChar* input, unsigned start, unsigned length, int* output) YARR_CALL;
+ typedef MatchResult (*YarrJITCode16)(const UChar* input, unsigned start, unsigned length, int* output) YARR_CALL;
+ typedef MatchResult (*YarrJITCodeMatchOnly8)(const LChar* input, unsigned start, unsigned length) YARR_CALL;
+ typedef MatchResult (*YarrJITCodeMatchOnly16)(const UChar* input, unsigned start, unsigned length) YARR_CALL;
+#else
+ typedef EncodedMatchResult (*YarrJITCode8)(const LChar* input, unsigned start, unsigned length, int* output) YARR_CALL;
+ typedef EncodedMatchResult (*YarrJITCode16)(const UChar* input, unsigned start, unsigned length, int* output) YARR_CALL;
+ typedef EncodedMatchResult (*YarrJITCodeMatchOnly8)(const LChar* input, unsigned start, unsigned length) YARR_CALL;
+ typedef EncodedMatchResult (*YarrJITCodeMatchOnly16)(const UChar* input, unsigned start, unsigned length) YARR_CALL;
+#endif
public:
YarrCodeBlock()
@@ -63,43 +73,67 @@
void setFallBack(bool fallback) { m_needFallBack = fallback; }
bool isFallBack() { return m_needFallBack; }
+
bool has8BitCode() { return m_ref8.size(); }
bool has16BitCode() { return m_ref16.size(); }
- void set8BitCode(MacroAssembler::CodeRef ref) { m_ref8 = ref; }
- void set16BitCode(MacroAssembler::CodeRef ref) { m_ref16 = ref; }
+ void set8BitCode(MacroAssemblerCodeRef ref) { m_ref8 = ref; }
+ void set16BitCode(MacroAssemblerCodeRef ref) { m_ref16 = ref; }
- int execute(const LChar* input, unsigned start, unsigned length, int* output)
+ bool has8BitCodeMatchOnly() { return m_matchOnly8.size(); }
+ bool has16BitCodeMatchOnly() { return m_matchOnly16.size(); }
+ void set8BitCodeMatchOnly(MacroAssemblerCodeRef matchOnly) { m_matchOnly8 = matchOnly; }
+ void set16BitCodeMatchOnly(MacroAssemblerCodeRef matchOnly) { m_matchOnly16 = matchOnly; }
+
+ MatchResult execute(const LChar* input, unsigned start, unsigned length, int* output)
{
ASSERT(has8BitCode());
- return reinterpret_cast<YarrJITCode8>(m_ref8.code().executableAddress())(input, start, length, output);
+ return MatchResult(reinterpret_cast<YarrJITCode8>(m_ref8.code().executableAddress())(input, start, length, output));
}
- int execute(const UChar* input, unsigned start, unsigned length, int* output)
+ MatchResult execute(const UChar* input, unsigned start, unsigned length, int* output)
{
ASSERT(has16BitCode());
- return reinterpret_cast<YarrJITCode16>(m_ref16.code().executableAddress())(input, start, length, output);
+ return MatchResult(reinterpret_cast<YarrJITCode16>(m_ref16.code().executableAddress())(input, start, length, output));
}
+
+ MatchResult execute(const LChar* input, unsigned start, unsigned length)
+ {
+ ASSERT(has8BitCodeMatchOnly());
+ return MatchResult(reinterpret_cast<YarrJITCodeMatchOnly8>(m_matchOnly8.code().executableAddress())(input, start, length));
+ }
+
+ MatchResult execute(const UChar* input, unsigned start, unsigned length)
+ {
+ ASSERT(has16BitCodeMatchOnly());
+ return MatchResult(reinterpret_cast<YarrJITCodeMatchOnly16>(m_matchOnly16.code().executableAddress())(input, start, length));
+ }
+
#if ENABLE(REGEXP_TRACING)
void *getAddr() { return m_ref.code().executableAddress(); }
#endif
+ void clear()
+ {
+ m_ref8 = MacroAssemblerCodeRef();
+ m_ref16 = MacroAssemblerCodeRef();
+ m_matchOnly8 = MacroAssemblerCodeRef();
+ m_matchOnly16 = MacroAssemblerCodeRef();
+ m_needFallBack = false;
+ }
+
private:
- MacroAssembler::CodeRef m_ref8;
- MacroAssembler::CodeRef m_ref16;
+ MacroAssemblerCodeRef m_ref8;
+ MacroAssemblerCodeRef m_ref16;
+ MacroAssemblerCodeRef m_matchOnly8;
+ MacroAssemblerCodeRef m_matchOnly16;
bool m_needFallBack;
};
-void jitCompile(YarrPattern&, YarrCharSize, JSGlobalData*, YarrCodeBlock& jitObject);
-
-inline int execute(YarrCodeBlock& jitObject, const LChar* input, unsigned start, unsigned length, int* output)
-{
- return jitObject.execute(input, start, length, output);
-}
-
-inline int execute(YarrCodeBlock& jitObject, const UChar* input, unsigned start, unsigned length, int* output)
-{
- return jitObject.execute(input, start, length, output);
-}
+enum YarrJITCompileMode {
+ MatchOnly,
+ IncludeSubpatterns
+};
+void jitCompile(YarrPattern&, YarrCharSize, JSGlobalData*, YarrCodeBlock& jitObject, YarrJITCompileMode = IncludeSubpatterns);
} } // namespace JSC::Yarr
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index 35032d9..92a56db 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,14 @@
+2012-03-28 Gavin Barraclough <barraclough@apple.com>
+
+ Yarr: if we're not using the output array, don't populate it!
+ https://bugs.webkit.org/show_bug.cgi?id=82519
+
+ Reviewed by Sam Weinig.
+
+ * ForwardingHeaders/runtime/MatchResult.h: Added.
+ * ForwardingHeaders/yarr/YarrJIT.h: Added.
+ - Added forwarding headers.
+
2012-03-23 David Hyatt <hyatt@apple.com>
https://bugs.webkit.org/show_bug.cgi?id=81685
diff --git a/Source/WebCore/ForwardingHeaders/runtime/MatchResult.h b/Source/WebCore/ForwardingHeaders/runtime/MatchResult.h
new file mode 100644
index 0000000..ea70d33
--- /dev/null
+++ b/Source/WebCore/ForwardingHeaders/runtime/MatchResult.h
@@ -0,0 +1,4 @@
+#ifndef WebCore_FWD_MatchResult_h
+#define WebCore_FWD_MatchResult_h
+#include <JavaScriptCore/MatchResult.h>
+#endif
diff --git a/Source/WebCore/ForwardingHeaders/yarr/YarrJIT.h b/Source/WebCore/ForwardingHeaders/yarr/YarrJIT.h
new file mode 100644
index 0000000..4bafeab
--- /dev/null
+++ b/Source/WebCore/ForwardingHeaders/yarr/YarrJIT.h
@@ -0,0 +1,5 @@
+#ifndef WebCore_FWD_YarrJIT_h
+#define WebCore_FWD_YarrJIT_h
+#include <JavaScriptCore/YarrJIT.h>
+#endif
+