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
+