<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[197796] trunk/Source/JavaScriptCore</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/197796">197796</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2016-03-08 13:15:07 -0800 (Tue, 08 Mar 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Regexp matching should incur less call overhead
https://bugs.webkit.org/show_bug.cgi?id=155181

Reviewed by Geoffrey Garen.

Previously we had DFG/FTL code call into the DFGOperation, which then called in to
RegExpObject, which then called into createRegExpMatchesArray, which then called into
RegExp, which then called the code generated by Yarr.

Now we have DFG/FTL code call into the DFGOperation, which does all of the things and calls
into code generated by Yarr.

This is another tiny Octane/regexp speed-up.

* JavaScriptCore.xcodeproj/project.pbxproj:
* dfg/DFGOperations.cpp:
* runtime/RegExp.cpp:
(JSC::regExpFlags):
(JSC::RegExp::compile):
(JSC::RegExp::match):
(JSC::RegExp::compileMatchOnly):
(JSC::RegExp::deleteCode):
(JSC::RegExpFunctionalTestCollector::clearRegExp): Deleted.
(JSC::RegExp::compileIfNecessary): Deleted.
(JSC::RegExp::compileIfNecessaryMatchOnly): Deleted.
* runtime/RegExp.h:
* runtime/RegExpInlines.h: Added.
(JSC::RegExpFunctionalTestCollector::clearRegExp):
(JSC::RegExp::compileIfNecessary):
(JSC::RegExp::matchInline):
(JSC::RegExp::compileIfNecessaryMatchOnly):
* runtime/RegExpMatchesArray.cpp:
(JSC::createEmptyRegExpMatchesArray):
(JSC::createStructureImpl):
(JSC::tryCreateUninitializedRegExpMatchesArray): Deleted.
(JSC::createRegExpMatchesArray): Deleted.
* runtime/RegExpMatchesArray.h:
(JSC::tryCreateUninitializedRegExpMatchesArray):
(JSC::createRegExpMatchesArray):
* runtime/RegExpObject.cpp:
(JSC::RegExpObject::put):
(JSC::RegExpObject::exec):
(JSC::RegExpObject::match):
(JSC::getLastIndexAsUnsigned): Deleted.
* runtime/RegExpObject.h:
(JSC::RegExpObject::getLastIndex):
(JSC::RegExpObject::test):
(JSC::RegExpObject::testInline):
* runtime/RegExpObjectInlines.h: Added.
(JSC::getRegExpObjectLastIndexAsUnsigned):
(JSC::RegExpObject::execInline):
(JSC::RegExpObject::matchInline):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj">trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGOperationscpp">trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeRegExpcpp">trunk/Source/JavaScriptCore/runtime/RegExp.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeRegExph">trunk/Source/JavaScriptCore/runtime/RegExp.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeRegExpMatchesArraycpp">trunk/Source/JavaScriptCore/runtime/RegExpMatchesArray.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeRegExpMatchesArrayh">trunk/Source/JavaScriptCore/runtime/RegExpMatchesArray.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeRegExpObjectcpp">trunk/Source/JavaScriptCore/runtime/RegExpObject.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeRegExpObjecth">trunk/Source/JavaScriptCore/runtime/RegExpObject.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreruntimeRegExpInlinesh">trunk/Source/JavaScriptCore/runtime/RegExpInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeRegExpObjectInlinesh">trunk/Source/JavaScriptCore/runtime/RegExpObjectInlines.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (197795 => 197796)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-03-08 21:02:09 UTC (rev 197795)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-03-08 21:15:07 UTC (rev 197796)
</span><span class="lines">@@ -1,3 +1,58 @@
</span><ins>+2016-03-08  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        Regexp matching should incur less call overhead
+        https://bugs.webkit.org/show_bug.cgi?id=155181
+
+        Reviewed by Geoffrey Garen.
+
+        Previously we had DFG/FTL code call into the DFGOperation, which then called in to
+        RegExpObject, which then called into createRegExpMatchesArray, which then called into
+        RegExp, which then called the code generated by Yarr.
+
+        Now we have DFG/FTL code call into the DFGOperation, which does all of the things and calls
+        into code generated by Yarr.
+
+        This is another tiny Octane/regexp speed-up.
+
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * dfg/DFGOperations.cpp:
+        * runtime/RegExp.cpp:
+        (JSC::regExpFlags):
+        (JSC::RegExp::compile):
+        (JSC::RegExp::match):
+        (JSC::RegExp::compileMatchOnly):
+        (JSC::RegExp::deleteCode):
+        (JSC::RegExpFunctionalTestCollector::clearRegExp): Deleted.
+        (JSC::RegExp::compileIfNecessary): Deleted.
+        (JSC::RegExp::compileIfNecessaryMatchOnly): Deleted.
+        * runtime/RegExp.h:
+        * runtime/RegExpInlines.h: Added.
+        (JSC::RegExpFunctionalTestCollector::clearRegExp):
+        (JSC::RegExp::compileIfNecessary):
+        (JSC::RegExp::matchInline):
+        (JSC::RegExp::compileIfNecessaryMatchOnly):
+        * runtime/RegExpMatchesArray.cpp:
+        (JSC::createEmptyRegExpMatchesArray):
+        (JSC::createStructureImpl):
+        (JSC::tryCreateUninitializedRegExpMatchesArray): Deleted.
+        (JSC::createRegExpMatchesArray): Deleted.
+        * runtime/RegExpMatchesArray.h:
+        (JSC::tryCreateUninitializedRegExpMatchesArray):
+        (JSC::createRegExpMatchesArray):
+        * runtime/RegExpObject.cpp:
+        (JSC::RegExpObject::put):
+        (JSC::RegExpObject::exec):
+        (JSC::RegExpObject::match):
+        (JSC::getLastIndexAsUnsigned): Deleted.
+        * runtime/RegExpObject.h:
+        (JSC::RegExpObject::getLastIndex):
+        (JSC::RegExpObject::test):
+        (JSC::RegExpObject::testInline):
+        * runtime/RegExpObjectInlines.h: Added.
+        (JSC::getRegExpObjectLastIndexAsUnsigned):
+        (JSC::RegExpObject::execInline):
+        (JSC::RegExpObject::matchInline):
+
</ins><span class="cx"> 2016-03-08  Mark Lam  &lt;mark.lam@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         synthesizePrototype() and friends need to be followed by exception checks (or equivalent).
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (197795 => 197796)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2016-03-08 21:02:09 UTC (rev 197795)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2016-03-08 21:15:07 UTC (rev 197796)
</span><span class="lines">@@ -486,6 +486,8 @@
</span><span class="cx">                 0F7B294B14C3CD2F007C3DB1 /* DFGCapabilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD82E1F14172C2F00179C94 /* DFGCapabilities.h */; };
</span><span class="cx">                 0F7B294D14C3CD4C007C3DB1 /* DFGCommon.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC0977E1469EBC400CF2442 /* DFGCommon.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0F7C11AD1BC3862C00C74CDB /* CopyBarrier.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F7C11AC1BC3862C00C74CDB /* CopyBarrier.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><ins>+                0F7C39FB1C8F629300480151 /* RegExpInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F7C39FA1C8F629300480151 /* RegExpInlines.h */; };
+                0F7C39FD1C8F659500480151 /* RegExpObjectInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F7C39FC1C8F659500480151 /* RegExpObjectInlines.h */; };
</ins><span class="cx">                 0F8023EA1613832B00A0BA45 /* ByValInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F8023E91613832300A0BA45 /* ByValInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0F8335B71639C1E6001443B5 /* ArrayAllocationProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F8335B41639C1E3001443B5 /* ArrayAllocationProfile.cpp */; };
</span><span class="cx">                 0F8335B81639C1EA001443B5 /* ArrayAllocationProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F8335B51639C1E3001443B5 /* ArrayAllocationProfile.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="lines">@@ -2636,6 +2638,8 @@
</span><span class="cx">                 0F79085319A290B200F6310C /* DFGStructureRegistrationPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGStructureRegistrationPhase.cpp; path = dfg/DFGStructureRegistrationPhase.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F79085419A290B200F6310C /* DFGStructureRegistrationPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGStructureRegistrationPhase.h; path = dfg/DFGStructureRegistrationPhase.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F7C11AC1BC3862C00C74CDB /* CopyBarrier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CopyBarrier.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                0F7C39FA1C8F629300480151 /* RegExpInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegExpInlines.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F7C39FC1C8F659500480151 /* RegExpObjectInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegExpObjectInlines.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 0F8023E91613832300A0BA45 /* ByValInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ByValInfo.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F8335B41639C1E3001443B5 /* ArrayAllocationProfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArrayAllocationProfile.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F8335B51639C1E3001443B5 /* ArrayAllocationProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArrayAllocationProfile.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -5874,11 +5878,13 @@
</span><span class="cx">                                 86F75EFC151C062F007C9BA3 /* RegExpCachedResult.h */,
</span><span class="cx">                                 BCD202BD0E1706A7002C7E82 /* RegExpConstructor.cpp */,
</span><span class="cx">                                 BCD202BE0E1706A7002C7E82 /* RegExpConstructor.h */,
</span><ins>+                                0F7C39FA1C8F629300480151 /* RegExpInlines.h */,
</ins><span class="cx">                                 A1712B4011C7B235007A5315 /* RegExpKey.h */,
</span><span class="cx">                                 86F75EFD151C062F007C9BA3 /* RegExpMatchesArray.cpp */,
</span><span class="cx">                                 93CEDDFB0EA91EE600258EBE /* RegExpMatchesArray.h */,
</span><span class="cx">                                 F692A87B0255597D01FF60F7 /* RegExpObject.cpp */,
</span><span class="cx">                                 F692A87C0255597D01FF60F7 /* RegExpObject.h */,
</span><ins>+                                0F7C39FC1C8F659500480151 /* RegExpObjectInlines.h */,
</ins><span class="cx">                                 BCD202BF0E1706A7002C7E82 /* RegExpPrototype.cpp */,
</span><span class="cx">                                 BCD202C00E1706A7002C7E82 /* RegExpPrototype.h */,
</span><span class="cx">                                 0FB7F39115ED8E3800F167B2 /* Reject.h */,
</span><span class="lines">@@ -7206,6 +7212,7 @@
</span><span class="cx">                                 0FBC0AE81496C7C700D4FBDD /* DFGExitProfile.h in Headers */,
</span><span class="cx">                                 A78A9775179738B8009DF744 /* DFGFailedFinalizer.h in Headers */,
</span><span class="cx">                                 A7BFF3C0179868940002F462 /* DFGFiltrationResult.h in Headers */,
</span><ins>+                                0F7C39FB1C8F629300480151 /* RegExpInlines.h in Headers */,
</ins><span class="cx">                                 A78A9777179738B8009DF744 /* DFGFinalizer.h in Headers */,
</span><span class="cx">                                 0F2BDC16151C5D4F00CD8910 /* DFGFixupPhase.h in Headers */,
</span><span class="cx">                                 0F9D339717FFC4E60073C2BC /* DFGFlushedAt.h in Headers */,
</span><span class="lines">@@ -7925,6 +7932,7 @@
</span><span class="cx">                                 A709F2F017A0AC0400512E98 /* SlowPathCall.h in Headers */,
</span><span class="cx">                                 933040040E6A749400786E6A /* SmallStrings.h in Headers */,
</span><span class="cx">                                 BC18C4640E16F5CD00B34460 /* SourceCode.h in Headers */,
</span><ins>+                                0F7C39FD1C8F659500480151 /* RegExpObjectInlines.h in Headers */,
</ins><span class="cx">                                 BC18C4630E16F5CD00B34460 /* SourceProvider.h in Headers */,
</span><span class="cx">                                 E49DC16C12EF294E00184A1F /* SourceProviderCache.h in Headers */,
</span><span class="cx">                                 E49DC16D12EF295300184A1F /* SourceProviderCacheItem.h in Headers */,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp (197795 => 197796)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp        2016-03-08 21:02:09 UTC (rev 197795)
+++ trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp        2016-03-08 21:15:07 UTC (rev 197796)
</span><span class="lines">@@ -624,7 +624,7 @@
</span><span class="cx">     VM&amp; vm = globalObject-&gt;vm();
</span><span class="cx">     NativeCallFrameTracer tracer(&amp;vm, exec);
</span><span class="cx">     
</span><del>-    return JSValue::encode(regExpObject-&gt;exec(exec, globalObject, argument));
</del><ins>+    return JSValue::encode(regExpObject-&gt;execInline(exec, globalObject, argument));
</ins><span class="cx"> }
</span><span class="cx">         
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationRegExpExec(ExecState* exec, JSGlobalObject* globalObject, RegExpObject* regExpObject, EncodedJSValue encodedArgument)
</span><span class="lines">@@ -637,7 +637,7 @@
</span><span class="cx">     JSString* input = argument.toStringOrNull(exec);
</span><span class="cx">     if (!input)
</span><span class="cx">         return JSValue::encode(jsUndefined());
</span><del>-    return JSValue::encode(regExpObject-&gt;exec(exec, globalObject, input));
</del><ins>+    return JSValue::encode(regExpObject-&gt;execInline(exec, globalObject, input));
</ins><span class="cx"> }
</span><span class="cx">         
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationRegExpExecGeneric(ExecState* exec, JSGlobalObject* globalObject, EncodedJSValue encodedBase, EncodedJSValue encodedArgument)
</span><span class="lines">@@ -662,7 +662,7 @@
</span><span class="cx">     VM&amp; vm = globalObject-&gt;vm();
</span><span class="cx">     NativeCallFrameTracer tracer(&amp;vm, exec);
</span><span class="cx"> 
</span><del>-    return regExpObject-&gt;test(exec, globalObject, input);
</del><ins>+    return regExpObject-&gt;testInline(exec, globalObject, input);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> size_t JIT_OPERATION operationRegExpTest(ExecState* exec, JSGlobalObject* globalObject, RegExpObject* regExpObject, EncodedJSValue encodedArgument)
</span><span class="lines">@@ -675,7 +675,7 @@
</span><span class="cx">     JSString* input = argument.toStringOrNull(exec);
</span><span class="cx">     if (!input)
</span><span class="cx">         return false;
</span><del>-    return regExpObject-&gt;test(exec, globalObject, input);
</del><ins>+    return regExpObject-&gt;testInline(exec, globalObject, input);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> size_t JIT_OPERATION operationRegExpTestGeneric(ExecState* exec, JSGlobalObject* globalObject, EncodedJSValue encodedBase, EncodedJSValue encodedArgument)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeRegExpcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/RegExp.cpp (197795 => 197796)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/RegExp.cpp        2016-03-08 21:02:09 UTC (rev 197795)
+++ trunk/Source/JavaScriptCore/runtime/RegExp.cpp        2016-03-08 21:15:07 UTC (rev 197796)
</span><span class="lines">@@ -1,6 +1,6 @@
</span><span class="cx"> /*
</span><span class="cx">  *  Copyright (C) 1999-2001, 2004 Harri Porten (porten@kde.org)
</span><del>- *  Copyright (c) 2007, 2008 Apple Inc. All rights reserved.
</del><ins>+ *  Copyright (c) 2007, 2008, 2016 Apple Inc. All rights reserved.
</ins><span class="cx">  *  Copyright (C) 2009 Torch Mobile, Inc.
</span><span class="cx">  *  Copyright (C) 2010 Peter Varga (pvarga@inf.u-szeged.hu), University of Szeged
</span><span class="cx">  *
</span><span class="lines">@@ -26,18 +26,11 @@
</span><span class="cx"> #include &quot;Lexer.h&quot;
</span><span class="cx"> #include &quot;JSCInlines.h&quot;
</span><span class="cx"> #include &quot;RegExpCache.h&quot;
</span><ins>+#include &quot;RegExpInlines.h&quot;
</ins><span class="cx"> #include &quot;Yarr.h&quot;
</span><span class="cx"> #include &quot;YarrJIT.h&quot;
</span><span class="cx"> #include &lt;wtf/Assertions.h&gt;
</span><span class="cx"> 
</span><del>-#define REGEXP_FUNC_TEST_DATA_GEN 0
-
-#if REGEXP_FUNC_TEST_DATA_GEN
-#include &lt;stdio.h&gt;
-#include &lt;stdlib.h&gt;
-#include &lt;string.h&gt;
-#endif
-
</del><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="cx"> const ClassInfo RegExp::s_info = { &quot;RegExp&quot;, 0, 0, CREATE_METHOD_TABLE(RegExp) };
</span><span class="lines">@@ -81,33 +74,6 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> #if REGEXP_FUNC_TEST_DATA_GEN
</span><del>-class RegExpFunctionalTestCollector {
-    // This class is not thread safe.
-protected:
-    static const char* const s_fileName;
-
-public:
-    static RegExpFunctionalTestCollector* get();
-
-    ~RegExpFunctionalTestCollector();
-
-    void outputOneTest(RegExp*, String, int, int*, int);
-    void clearRegExp(RegExp* regExp)
-    {
-        if (regExp == m_lastRegExp)
-            m_lastRegExp = 0;
-    }
-
-private:
-    RegExpFunctionalTestCollector();
-
-    void outputEscapedString(const String&amp;, bool escapeSlash = false);
-
-    static RegExpFunctionalTestCollector* s_instance;
-    FILE* m_file;
-    RegExp* m_lastRegExp;
-};
-
</del><span class="cx"> const char* const RegExpFunctionalTestCollector::s_fileName = &quot;/tmp/RegExpTestsData&quot;;
</span><span class="cx"> RegExpFunctionalTestCollector* RegExpFunctionalTestCollector::s_instance = 0;
</span><span class="cx"> 
</span><span class="lines">@@ -320,89 +286,9 @@
</span><span class="cx">     m_regExpBytecode = Yarr::byteCompile(pattern, &amp;vm-&gt;m_regExpAllocator);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void RegExp::compileIfNecessary(VM&amp; vm, Yarr::YarrCharSize charSize)
-{
-    if (hasCode()) {
-#if ENABLE(YARR_JIT)
-        if (m_state != JITCode)
-            return;
-        if ((charSize == Yarr::Char8) &amp;&amp; (m_regExpJITCode.has8BitCode()))
-            return;
-        if ((charSize == Yarr::Char16) &amp;&amp; (m_regExpJITCode.has16BitCode()))
-            return;
-#else
-        return;
-#endif
-    }
-
-    compile(&amp;vm, charSize);
-}
-
</del><span class="cx"> int RegExp::match(VM&amp; vm, const String&amp; s, unsigned startOffset, Vector&lt;int, 32&gt;&amp; ovector)
</span><span class="cx"> {
</span><del>-#if ENABLE(REGEXP_TRACING)
-    m_rtMatchCallCount++;
-    m_rtMatchTotalSubjectStringLen += (double)(s.length() - startOffset);
-#endif
-
-    ASSERT(m_state != ParseError);
-    compileIfNecessary(vm, s.is8Bit() ? Yarr::Char8 : Yarr::Char16);
-
-    int offsetVectorSize = (m_numSubpatterns + 1) * 2;
-    ovector.resize(offsetVectorSize);
-    int* offsetVector = ovector.data();
-
-    int result;
-#if ENABLE(YARR_JIT)
-    if (m_state == JITCode) {
-        if (s.is8Bit())
-            result = m_regExpJITCode.execute(s.characters8(), startOffset, s.length(), offsetVector).start;
-        else
-            result = m_regExpJITCode.execute(s.characters16(), startOffset, s.length(), offsetVector).start;
-#if ENABLE(YARR_JIT_DEBUG)
-        matchCompareWithInterpreter(s, startOffset, offsetVector, result);
-#endif
-    } else
-#endif
-        result = Yarr::interpret(m_regExpBytecode.get(), s, startOffset, reinterpret_cast&lt;unsigned*&gt;(offsetVector));
-
-    // FIXME: The YARR engine should handle unsigned or size_t length matches.
-    // The YARR Interpreter is &quot;unsigned&quot; clean, while the YARR JIT hasn't been addressed.
-    // The offset vector handling needs to change as well.
-    // Right now we convert a match where the offsets overflowed into match failure.
-    // There are two places in WebCore that call the interpreter directly that need to
-    // have their offsets changed to int as well. They are yarr/RegularExpression.cpp
-    // and inspector/ContentSearchUtilities.cpp
-    if (s.length() &gt; INT_MAX) {
-        bool overflowed = false;
-
-        if (result &lt; -1)
-            overflowed = true;
-
-        for (unsigned i = 0; i &lt;= m_numSubpatterns; i++) {
-            if ((offsetVector[i*2] &lt; -1) || ((offsetVector[i*2] &gt;= 0) &amp;&amp; (offsetVector[i*2+1] &lt; -1))) {
-                overflowed = true;
-                offsetVector[i*2] = -1;
-                offsetVector[i*2+1] = -1;
-            }
-        }
-
-        if (overflowed)
-            result = -1;
-    }
-
-    ASSERT(result &gt;= -1);
-
-#if REGEXP_FUNC_TEST_DATA_GEN
-    RegExpFunctionalTestCollector::get()-&gt;outputOneTest(this, s, startOffset, offsetVector, result);
-#endif
-
-#if ENABLE(REGEXP_TRACING)
-    if (result != -1)
-        m_rtMatchFoundCount++;
-#endif
-
-    return result;
</del><ins>+    return matchInline(vm, s, startOffset, ovector);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void RegExp::compileMatchOnly(VM* vm, Yarr::YarrCharSize charSize)
</span><span class="lines">@@ -439,65 +325,9 @@
</span><span class="cx">     m_regExpBytecode = Yarr::byteCompile(pattern, &amp;vm-&gt;m_regExpAllocator);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void RegExp::compileIfNecessaryMatchOnly(VM&amp; vm, Yarr::YarrCharSize charSize)
-{
-    if (hasCode()) {
-#if ENABLE(YARR_JIT)
-        if (m_state != JITCode)
-            return;
-        if ((charSize == Yarr::Char8) &amp;&amp; (m_regExpJITCode.has8BitCodeMatchOnly()))
-            return;
-        if ((charSize == Yarr::Char16) &amp;&amp; (m_regExpJITCode.has16BitCodeMatchOnly()))
-            return;
-#else
-        return;
-#endif
-    }
-
-    compileMatchOnly(&amp;vm, charSize);
-}
-
</del><span class="cx"> MatchResult RegExp::match(VM&amp; vm, const String&amp; s, unsigned startOffset)
</span><span class="cx"> {
</span><del>-#if ENABLE(REGEXP_TRACING)
-    m_rtMatchOnlyCallCount++;
-    m_rtMatchOnlyTotalSubjectStringLen += (double)(s.length() - startOffset);
-#endif
-
-    ASSERT(m_state != ParseError);
-    compileIfNecessaryMatchOnly(vm, s.is8Bit() ? Yarr::Char8 : Yarr::Char16);
-
-#if ENABLE(YARR_JIT)
-    if (m_state == JITCode) {
-        MatchResult result = s.is8Bit() ?
-            m_regExpJITCode.execute(s.characters8(), startOffset, s.length()) :
-            m_regExpJITCode.execute(s.characters16(), startOffset, s.length());
-#if ENABLE(REGEXP_TRACING)
-        if (!result)
-            m_rtMatchOnlyFoundCount++;
-#endif
-        return result;
-    }
-#endif
-
-    int offsetVectorSize = (m_numSubpatterns + 1) * 2;
-    int* offsetVector;
-    Vector&lt;int, 32&gt; nonReturnedOvector;
-    nonReturnedOvector.resize(offsetVectorSize);
-    offsetVector = nonReturnedOvector.data();
-    int r = Yarr::interpret(m_regExpBytecode.get(), s, startOffset, reinterpret_cast&lt;unsigned*&gt;(offsetVector));
-#if REGEXP_FUNC_TEST_DATA_GEN
-    RegExpFunctionalTestCollector::get()-&gt;outputOneTest(this, s, startOffset, offsetVector, result);
-#endif
-
-    if (r &gt;= 0) {
-#if ENABLE(REGEXP_TRACING)
-        m_rtMatchOnlyFoundCount++;
-#endif
-        return MatchResult(r, reinterpret_cast&lt;unsigned*&gt;(offsetVector)[1]);
-    }
-
-    return MatchResult::failed();
</del><ins>+    return matchInline(vm, s, startOffset);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void RegExp::deleteCode()
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeRegExph"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/RegExp.h (197795 => 197796)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/RegExp.h        2016-03-08 21:02:09 UTC (rev 197795)
+++ trunk/Source/JavaScriptCore/runtime/RegExp.h        2016-03-08 21:15:07 UTC (rev 197796)
</span><span class="lines">@@ -1,6 +1,6 @@
</span><span class="cx"> /*
</span><span class="cx">  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
</span><del>- *  Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
</del><ins>+ *  Copyright (C) 2007, 2008, 2009, 2016 Apple Inc. All rights reserved.
</ins><span class="cx">  *  Copyright (C) 2009 Torch Mobile, Inc.
</span><span class="cx">  *
</span><span class="cx">  *  This library is free software; you can redistribute it and/or
</span><span class="lines">@@ -64,6 +64,11 @@
</span><span class="cx"> 
</span><span class="cx">     JS_EXPORT_PRIVATE int match(VM&amp;, const String&amp;, unsigned startOffset, Vector&lt;int, 32&gt;&amp; ovector);
</span><span class="cx">     JS_EXPORT_PRIVATE MatchResult match(VM&amp;, const String&amp;, unsigned startOffset);
</span><ins>+
+    // Call these versions of the match functions if you're desperate for performance.
+    int matchInline(VM&amp;, const String&amp;, unsigned startOffset, Vector&lt;int, 32&gt;&amp; ovector);
+    MatchResult matchInline(VM&amp;, const String&amp;, unsigned startOffset);
+    
</ins><span class="cx">     unsigned numSubpatterns() const { return m_numSubpatterns; }
</span><span class="cx"> 
</span><span class="cx">     bool hasCode()
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeRegExpInlinesh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/runtime/RegExpInlines.h (0 => 197796)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/RegExpInlines.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/runtime/RegExpInlines.h        2016-03-08 21:15:07 UTC (rev 197796)
</span><span class="lines">@@ -0,0 +1,219 @@
</span><ins>+/*
+ *  Copyright (C) 1999-2001, 2004 Harri Porten (porten@kde.org)
+ *  Copyright (c) 2007, 2008, 2016 Apple Inc. All rights reserved.
+ *  Copyright (C) 2009 Torch Mobile, Inc.
+ *  Copyright (C) 2010 Peter Varga (pvarga@inf.u-szeged.hu), University of Szeged
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef RegExpInlines_h
+#define RegExpInlines_h
+
+#include &quot;RegExp.h&quot;
+#include &quot;JSCInlines.h&quot;
+#include &quot;Yarr.h&quot;
+#include &quot;YarrJIT.h&quot;
+
+#define REGEXP_FUNC_TEST_DATA_GEN 0
+
+#if REGEXP_FUNC_TEST_DATA_GEN
+#include &lt;stdio.h&gt;
+#include &lt;stdlib.h&gt;
+#include &lt;string.h&gt;
+#endif
+
+namespace JSC {
+
+#if REGEXP_FUNC_TEST_DATA_GEN
+class RegExpFunctionalTestCollector {
+    // This class is not thread safe.
+protected:
+    static const char* const s_fileName;
+
+public:
+    static RegExpFunctionalTestCollector* get();
+
+    ~RegExpFunctionalTestCollector();
+
+    void outputOneTest(RegExp*, String, int, int*, int);
+    void clearRegExp(RegExp* regExp)
+    {
+        if (regExp == m_lastRegExp)
+            m_lastRegExp = 0;
+    }
+
+private:
+    RegExpFunctionalTestCollector();
+
+    void outputEscapedString(const String&amp;, bool escapeSlash = false);
+
+    static RegExpFunctionalTestCollector* s_instance;
+    FILE* m_file;
+    RegExp* m_lastRegExp;
+};
+#endif // REGEXP_FUNC_TEST_DATA_GEN
+
+ALWAYS_INLINE void RegExp::compileIfNecessary(VM&amp; vm, Yarr::YarrCharSize charSize)
+{
+    if (hasCode()) {
+#if ENABLE(YARR_JIT)
+        if (m_state != JITCode)
+            return;
+        if ((charSize == Yarr::Char8) &amp;&amp; (m_regExpJITCode.has8BitCode()))
+            return;
+        if ((charSize == Yarr::Char16) &amp;&amp; (m_regExpJITCode.has16BitCode()))
+            return;
+#else
+        return;
+#endif
+    }
+
+    compile(&amp;vm, charSize);
+}
+
+ALWAYS_INLINE int RegExp::matchInline(VM&amp; vm, const String&amp; s, unsigned startOffset, Vector&lt;int, 32&gt;&amp; ovector)
+{
+#if ENABLE(REGEXP_TRACING)
+    m_rtMatchCallCount++;
+    m_rtMatchTotalSubjectStringLen += (double)(s.length() - startOffset);
+#endif
+
+    ASSERT(m_state != ParseError);
+    compileIfNecessary(vm, s.is8Bit() ? Yarr::Char8 : Yarr::Char16);
+
+    int offsetVectorSize = (m_numSubpatterns + 1) * 2;
+    ovector.resize(offsetVectorSize);
+    int* offsetVector = ovector.data();
+
+    int result;
+#if ENABLE(YARR_JIT)
+    if (m_state == JITCode) {
+        if (s.is8Bit())
+            result = m_regExpJITCode.execute(s.characters8(), startOffset, s.length(), offsetVector).start;
+        else
+            result = m_regExpJITCode.execute(s.characters16(), startOffset, s.length(), offsetVector).start;
+#if ENABLE(YARR_JIT_DEBUG)
+        matchCompareWithInterpreter(s, startOffset, offsetVector, result);
+#endif
+    } else
+#endif
+        result = Yarr::interpret(m_regExpBytecode.get(), s, startOffset, reinterpret_cast&lt;unsigned*&gt;(offsetVector));
+
+    // FIXME: The YARR engine should handle unsigned or size_t length matches.
+    // The YARR Interpreter is &quot;unsigned&quot; clean, while the YARR JIT hasn't been addressed.
+    // The offset vector handling needs to change as well.
+    // Right now we convert a match where the offsets overflowed into match failure.
+    // There are two places in WebCore that call the interpreter directly that need to
+    // have their offsets changed to int as well. They are yarr/RegularExpression.cpp
+    // and inspector/ContentSearchUtilities.cpp
+    if (s.length() &gt; INT_MAX) {
+        bool overflowed = false;
+
+        if (result &lt; -1)
+            overflowed = true;
+
+        for (unsigned i = 0; i &lt;= m_numSubpatterns; i++) {
+            if ((offsetVector[i*2] &lt; -1) || ((offsetVector[i*2] &gt;= 0) &amp;&amp; (offsetVector[i*2+1] &lt; -1))) {
+                overflowed = true;
+                offsetVector[i*2] = -1;
+                offsetVector[i*2+1] = -1;
+            }
+        }
+
+        if (overflowed)
+            result = -1;
+    }
+
+    ASSERT(result &gt;= -1);
+
+#if REGEXP_FUNC_TEST_DATA_GEN
+    RegExpFunctionalTestCollector::get()-&gt;outputOneTest(this, s, startOffset, offsetVector, result);
+#endif
+
+#if ENABLE(REGEXP_TRACING)
+    if (result != -1)
+        m_rtMatchFoundCount++;
+#endif
+
+    return result;
+}
+
+ALWAYS_INLINE void RegExp::compileIfNecessaryMatchOnly(VM&amp; vm, Yarr::YarrCharSize charSize)
+{
+    if (hasCode()) {
+#if ENABLE(YARR_JIT)
+        if (m_state != JITCode)
+            return;
+        if ((charSize == Yarr::Char8) &amp;&amp; (m_regExpJITCode.has8BitCodeMatchOnly()))
+            return;
+        if ((charSize == Yarr::Char16) &amp;&amp; (m_regExpJITCode.has16BitCodeMatchOnly()))
+            return;
+#else
+        return;
+#endif
+    }
+
+    compileMatchOnly(&amp;vm, charSize);
+}
+
+ALWAYS_INLINE MatchResult RegExp::matchInline(VM&amp; vm, const String&amp; s, unsigned startOffset)
+{
+#if ENABLE(REGEXP_TRACING)
+    m_rtMatchOnlyCallCount++;
+    m_rtMatchOnlyTotalSubjectStringLen += (double)(s.length() - startOffset);
+#endif
+
+    ASSERT(m_state != ParseError);
+    compileIfNecessaryMatchOnly(vm, s.is8Bit() ? Yarr::Char8 : Yarr::Char16);
+
+#if ENABLE(YARR_JIT)
+    if (m_state == JITCode) {
+        MatchResult result = s.is8Bit() ?
+            m_regExpJITCode.execute(s.characters8(), startOffset, s.length()) :
+            m_regExpJITCode.execute(s.characters16(), startOffset, s.length());
+#if ENABLE(REGEXP_TRACING)
+        if (!result)
+            m_rtMatchOnlyFoundCount++;
+#endif
+        return result;
+    }
+#endif
+
+    int offsetVectorSize = (m_numSubpatterns + 1) * 2;
+    int* offsetVector;
+    Vector&lt;int, 32&gt; nonReturnedOvector;
+    nonReturnedOvector.resize(offsetVectorSize);
+    offsetVector = nonReturnedOvector.data();
+    int r = Yarr::interpret(m_regExpBytecode.get(), s, startOffset, reinterpret_cast&lt;unsigned*&gt;(offsetVector));
+#if REGEXP_FUNC_TEST_DATA_GEN
+    RegExpFunctionalTestCollector::get()-&gt;outputOneTest(this, s, startOffset, offsetVector, result);
+#endif
+
+    if (r &gt;= 0) {
+#if ENABLE(REGEXP_TRACING)
+        m_rtMatchOnlyFoundCount++;
+#endif
+        return MatchResult(r, reinterpret_cast&lt;unsigned*&gt;(offsetVector)[1]);
+    }
+
+    return MatchResult::failed();
+}
+
+} // namespace JSC
+
+#endif // RegExpInlines_h
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeRegExpMatchesArraycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/RegExpMatchesArray.cpp (197795 => 197796)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/RegExpMatchesArray.cpp        2016-03-08 21:02:09 UTC (rev 197795)
+++ trunk/Source/JavaScriptCore/runtime/RegExpMatchesArray.cpp        2016-03-08 21:15:07 UTC (rev 197796)
</span><span class="lines">@@ -26,90 +26,8 @@
</span><span class="cx"> #include &quot;config.h&quot;
</span><span class="cx"> #include &quot;RegExpMatchesArray.h&quot;
</span><span class="cx"> 
</span><del>-#include &quot;ButterflyInlines.h&quot;
-#include &quot;JSCInlines.h&quot;
-
</del><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><del>-static const PropertyOffset indexPropertyOffset = 100;
-static const PropertyOffset inputPropertyOffset = 101;
-
-static JSArray* tryCreateUninitializedRegExpMatchesArray(VM&amp; vm, Structure* structure, unsigned initialLength)
-{
-    unsigned vectorLength = std::max(BASE_VECTOR_LEN, initialLength);
-    if (vectorLength &gt; MAX_STORAGE_VECTOR_LENGTH)
-        return 0;
-
-    void* temp;
-    if (!vm.heap.tryAllocateStorage(0, Butterfly::totalSize(0, structure-&gt;outOfLineCapacity(), true, vectorLength * sizeof(EncodedJSValue)), &amp;temp))
-        return 0;
-    Butterfly* butterfly = Butterfly::fromBase(temp, 0, structure-&gt;outOfLineCapacity());
-    butterfly-&gt;setVectorLength(vectorLength);
-    butterfly-&gt;setPublicLength(initialLength);
-
-    return JSArray::createWithButterfly(vm, structure, butterfly);
-}
-
-JSArray* createRegExpMatchesArray(
-    ExecState* exec, JSGlobalObject* globalObject, JSString* input, RegExp* regExp,
-    unsigned startOffset, MatchResult&amp; result)
-{
-    SamplingRegion samplingRegion(&quot;createRegExpMatchesArray&quot;);
-    
-    VM&amp; vm = globalObject-&gt;vm();
-    
-    Vector&lt;int, 32&gt; subpatternResults;
-    int position = regExp-&gt;match(vm, input-&gt;value(exec), startOffset, subpatternResults);
-    if (position == -1) {
-        result = MatchResult::failed();
-        return nullptr;
-    }
-
-    result.start = position;
-    result.end = subpatternResults[1];
-    
-    JSArray* array;
-
-    // FIXME: This should handle array allocation errors gracefully.
-    // https://bugs.webkit.org/show_bug.cgi?id=155144
-    
-    if (UNLIKELY(globalObject-&gt;isHavingABadTime())) {
-        array = JSArray::tryCreateUninitialized(vm, globalObject-&gt;regExpMatchesArrayStructure(), regExp-&gt;numSubpatterns() + 1);
-        
-        array-&gt;initializeIndex(vm, 0, jsSubstringOfResolved(vm, input, result.start, result.end - result.start));
-        
-        if (unsigned numSubpatterns = regExp-&gt;numSubpatterns()) {
-            for (unsigned i = 1; i &lt;= numSubpatterns; ++i) {
-                int start = subpatternResults[2 * i];
-                if (start &gt;= 0)
-                    array-&gt;initializeIndex(vm, i, JSRopeString::createSubstringOfResolved(vm, input, start, subpatternResults[2 * i + 1] - start));
-                else
-                    array-&gt;initializeIndex(vm, i, jsUndefined());
-            }
-        }
-    } else {
-        array = tryCreateUninitializedRegExpMatchesArray(vm, globalObject-&gt;regExpMatchesArrayStructure(), regExp-&gt;numSubpatterns() + 1);
-        RELEASE_ASSERT(array);
-        
-        array-&gt;initializeIndex(vm, 0, jsSubstringOfResolved(vm, input, result.start, result.end - result.start), ArrayWithContiguous);
-        
-        if (unsigned numSubpatterns = regExp-&gt;numSubpatterns()) {
-            for (unsigned i = 1; i &lt;= numSubpatterns; ++i) {
-                int start = subpatternResults[2 * i];
-                if (start &gt;= 0)
-                    array-&gt;initializeIndex(vm, i, JSRopeString::createSubstringOfResolved(vm, input, start, subpatternResults[2 * i + 1] - start), ArrayWithContiguous);
-                else
-                    array-&gt;initializeIndex(vm, i, jsUndefined(), ArrayWithContiguous);
-            }
-        }
-    }
-
-    array-&gt;putDirect(vm, indexPropertyOffset, jsNumber(result.start));
-    array-&gt;putDirect(vm, inputPropertyOffset, input);
-
-    return array;
-}
-
</del><span class="cx"> JSArray* createEmptyRegExpMatchesArray(JSGlobalObject* globalObject, JSString* input, RegExp* regExp)
</span><span class="cx"> {
</span><span class="cx">     VM&amp; vm = globalObject-&gt;vm();
</span><span class="lines">@@ -139,8 +57,8 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    array-&gt;putDirect(vm, indexPropertyOffset, jsNumber(-1));
-    array-&gt;putDirect(vm, inputPropertyOffset, input);
</del><ins>+    array-&gt;putDirect(vm, RegExpMatchesArrayIndexPropertyOffset, jsNumber(-1));
+    array-&gt;putDirect(vm, RegExpMatchesArrayInputPropertyOffset, input);
</ins><span class="cx">     return array;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -149,9 +67,9 @@
</span><span class="cx">     Structure* structure = globalObject-&gt;arrayStructureForIndexingTypeDuringAllocation(indexingType);
</span><span class="cx">     PropertyOffset offset;
</span><span class="cx">     structure = Structure::addPropertyTransition(vm, structure, vm.propertyNames-&gt;index, 0, offset);
</span><del>-    ASSERT(offset == indexPropertyOffset);
</del><ins>+    ASSERT(offset == RegExpMatchesArrayIndexPropertyOffset);
</ins><span class="cx">     structure = Structure::addPropertyTransition(vm, structure, vm.propertyNames-&gt;input, 0, offset);
</span><del>-    ASSERT(offset == inputPropertyOffset);
</del><ins>+    ASSERT(offset == RegExpMatchesArrayInputPropertyOffset);
</ins><span class="cx">     return structure;
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeRegExpMatchesArrayh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/RegExpMatchesArray.h (197795 => 197796)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/RegExpMatchesArray.h        2016-03-08 21:02:09 UTC (rev 197795)
+++ trunk/Source/JavaScriptCore/runtime/RegExpMatchesArray.h        2016-03-08 21:15:07 UTC (rev 197796)
</span><span class="lines">@@ -20,17 +20,96 @@
</span><span class="cx"> #ifndef RegExpMatchesArray_h
</span><span class="cx"> #define RegExpMatchesArray_h
</span><span class="cx"> 
</span><ins>+#include &quot;ButterflyInlines.h&quot;
</ins><span class="cx"> #include &quot;JSArray.h&quot;
</span><ins>+#include &quot;JSCInlines.h&quot;
</ins><span class="cx"> #include &quot;JSGlobalObject.h&quot;
</span><ins>+#include &quot;RegExpInlines.h&quot;
</ins><span class="cx"> #include &quot;RegExpObject.h&quot;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><del>-JSArray* createRegExpMatchesArray(ExecState*, JSGlobalObject*, JSString*, RegExp*, unsigned startOffset, MatchResult&amp;);
</del><ins>+static const PropertyOffset RegExpMatchesArrayIndexPropertyOffset = 100;
+static const PropertyOffset RegExpMatchesArrayInputPropertyOffset = 101;
+
+ALWAYS_INLINE JSArray* tryCreateUninitializedRegExpMatchesArray(VM&amp; vm, Structure* structure, unsigned initialLength)
+{
+    unsigned vectorLength = std::max(BASE_VECTOR_LEN, initialLength);
+    if (vectorLength &gt; MAX_STORAGE_VECTOR_LENGTH)
+        return 0;
+
+    void* temp;
+    if (!vm.heap.tryAllocateStorage(0, Butterfly::totalSize(0, structure-&gt;outOfLineCapacity(), true, vectorLength * sizeof(EncodedJSValue)), &amp;temp))
+        return 0;
+    Butterfly* butterfly = Butterfly::fromBase(temp, 0, structure-&gt;outOfLineCapacity());
+    butterfly-&gt;setVectorLength(vectorLength);
+    butterfly-&gt;setPublicLength(initialLength);
+
+    return JSArray::createWithButterfly(vm, structure, butterfly);
+}
+
+ALWAYS_INLINE JSArray* createRegExpMatchesArray(
+    VM&amp; vm, JSGlobalObject* globalObject, JSString* input, const String&amp; inputValue,
+    RegExp* regExp, unsigned startOffset, MatchResult&amp; result)
+{
+    SamplingRegion samplingRegion(&quot;createRegExpMatchesArray&quot;);
+    
+    Vector&lt;int, 32&gt; subpatternResults;
+    int position = regExp-&gt;matchInline(vm, inputValue, startOffset, subpatternResults);
+    if (position == -1) {
+        result = MatchResult::failed();
+        return nullptr;
+    }
+
+    result.start = position;
+    result.end = subpatternResults[1];
+    
+    JSArray* array;
+
+    // FIXME: This should handle array allocation errors gracefully.
+    // https://bugs.webkit.org/show_bug.cgi?id=155144
+    
+    if (UNLIKELY(globalObject-&gt;isHavingABadTime())) {
+        array = JSArray::tryCreateUninitialized(vm, globalObject-&gt;regExpMatchesArrayStructure(), regExp-&gt;numSubpatterns() + 1);
+        
+        array-&gt;initializeIndex(vm, 0, jsSubstringOfResolved(vm, input, result.start, result.end - result.start));
+        
+        if (unsigned numSubpatterns = regExp-&gt;numSubpatterns()) {
+            for (unsigned i = 1; i &lt;= numSubpatterns; ++i) {
+                int start = subpatternResults[2 * i];
+                if (start &gt;= 0)
+                    array-&gt;initializeIndex(vm, i, JSRopeString::createSubstringOfResolved(vm, input, start, subpatternResults[2 * i + 1] - start));
+                else
+                    array-&gt;initializeIndex(vm, i, jsUndefined());
+            }
+        }
+    } else {
+        array = tryCreateUninitializedRegExpMatchesArray(vm, globalObject-&gt;regExpMatchesArrayStructure(), regExp-&gt;numSubpatterns() + 1);
+        RELEASE_ASSERT(array);
+        
+        array-&gt;initializeIndex(vm, 0, jsSubstringOfResolved(vm, input, result.start, result.end - result.start), ArrayWithContiguous);
+        
+        if (unsigned numSubpatterns = regExp-&gt;numSubpatterns()) {
+            for (unsigned i = 1; i &lt;= numSubpatterns; ++i) {
+                int start = subpatternResults[2 * i];
+                if (start &gt;= 0)
+                    array-&gt;initializeIndex(vm, i, JSRopeString::createSubstringOfResolved(vm, input, start, subpatternResults[2 * i + 1] - start), ArrayWithContiguous);
+                else
+                    array-&gt;initializeIndex(vm, i, jsUndefined(), ArrayWithContiguous);
+            }
+        }
+    }
+
+    array-&gt;putDirect(vm, RegExpMatchesArrayIndexPropertyOffset, jsNumber(result.start));
+    array-&gt;putDirect(vm, RegExpMatchesArrayInputPropertyOffset, input);
+
+    return array;
+}
+
</ins><span class="cx"> inline JSArray* createRegExpMatchesArray(ExecState* exec, JSGlobalObject* globalObject, JSString* string, RegExp* regExp, unsigned startOffset)
</span><span class="cx"> {
</span><span class="cx">     MatchResult ignoredResult;
</span><del>-    return createRegExpMatchesArray(exec, globalObject, string, regExp, startOffset, ignoredResult);
</del><ins>+    return createRegExpMatchesArray(globalObject-&gt;vm(), globalObject, string, string-&gt;value(exec), regExp, startOffset, ignoredResult);
</ins><span class="cx"> }
</span><span class="cx"> JSArray* createEmptyRegExpMatchesArray(JSGlobalObject*, JSString*, RegExp*);
</span><span class="cx"> Structure* createRegExpMatchesArrayStructure(VM&amp;, JSGlobalObject*);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeRegExpObjectcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/RegExpObject.cpp (197795 => 197796)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/RegExpObject.cpp        2016-03-08 21:02:09 UTC (rev 197795)
+++ trunk/Source/JavaScriptCore/runtime/RegExpObject.cpp        2016-03-08 21:15:07 UTC (rev 197796)
</span><span class="lines">@@ -32,6 +32,7 @@
</span><span class="cx"> #include &quot;JSCInlines.h&quot;
</span><span class="cx"> #include &quot;RegExpConstructor.h&quot;
</span><span class="cx"> #include &quot;RegExpMatchesArray.h&quot;
</span><ins>+#include &quot;RegExpObjectInlines.h&quot;
</ins><span class="cx"> #include &quot;RegExpPrototype.h&quot;
</span><span class="cx"> #include &lt;wtf/text/StringBuilder.h&gt;
</span><span class="cx"> 
</span><span class="lines">@@ -159,77 +160,15 @@
</span><span class="cx">     Base::put(cell, exec, propertyName, value, slot);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-ALWAYS_INLINE unsigned getLastIndexAsUnsigned(
-    ExecState* exec, RegExpObject* regExpObject, const String&amp; input)
-{
-    JSValue jsLastIndex = regExpObject-&gt;getLastIndex();
-    unsigned lastIndex;
-    if (LIKELY(jsLastIndex.isUInt32())) {
-        lastIndex = jsLastIndex.asUInt32();
-        if (lastIndex &gt; input.length()) {
-            regExpObject-&gt;setLastIndex(exec, 0);
-            return UINT_MAX;
-        }
-    } else {
-        double doubleLastIndex = jsLastIndex.toInteger(exec);
-        if (doubleLastIndex &lt; 0 || doubleLastIndex &gt; input.length()) {
-            regExpObject-&gt;setLastIndex(exec, 0);
-            return UINT_MAX;
-        }
-        lastIndex = static_cast&lt;unsigned&gt;(doubleLastIndex);
-    }
-    return lastIndex;
-}
-
</del><span class="cx"> JSValue RegExpObject::exec(ExecState* exec, JSGlobalObject* globalObject, JSString* string)
</span><span class="cx"> {
</span><del>-    RegExp* regExp = this-&gt;regExp();
-    RegExpConstructor* regExpConstructor = globalObject-&gt;regExpConstructor();
-    String input = string-&gt;value(exec); // FIXME: Handle errors. https://bugs.webkit.org/show_bug.cgi?id=155145
-    VM&amp; vm = globalObject-&gt;vm();
-
-    if (!regExp-&gt;global()) {
-        MatchResult result;
-        JSArray* array = createRegExpMatchesArray(exec, globalObject, string, regExp, 0, result);
-        if (!array)
-            return jsNull();
-        regExpConstructor-&gt;recordMatch(vm, regExp, string, result);
-        return array;
-    }
-
-    unsigned lastIndex = getLastIndexAsUnsigned(exec, this, input);
-    if (lastIndex == UINT_MAX)
-        return jsNull();
-    
-    MatchResult result;
-    JSArray* array =
-        createRegExpMatchesArray(exec, globalObject, string, regExp, lastIndex, result);
-    if (!array) {
-        setLastIndex(exec, 0);
-        return jsNull();
-    }
-    setLastIndex(exec, result.end);
-    regExpConstructor-&gt;recordMatch(vm, regExp, string, result);
-    return array;
</del><ins>+    return execInline(exec, globalObject, string);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> // Shared implementation used by test and exec.
</span><span class="cx"> MatchResult RegExpObject::match(ExecState* exec, JSGlobalObject* globalObject, JSString* string)
</span><span class="cx"> {
</span><del>-    RegExp* regExp = this-&gt;regExp();
-    RegExpConstructor* regExpConstructor = globalObject-&gt;regExpConstructor();
-    String input = string-&gt;value(exec); // FIXME: Handle errors. https://bugs.webkit.org/show_bug.cgi?id=155145
-    VM&amp; vm = globalObject-&gt;vm();
-    if (!regExp-&gt;global())
-        return regExpConstructor-&gt;performMatch(vm, regExp, string, input, 0);
-
-    unsigned lastIndex = getLastIndexAsUnsigned(exec, this, input);
-    if (lastIndex == UINT_MAX)
-        return MatchResult::failed();
-    
-    MatchResult result = regExpConstructor-&gt;performMatch(vm, regExp, string, input, lastIndex);
-    setLastIndex(exec, result.end);
-    return result;
</del><ins>+    return matchInline(exec, globalObject, string);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeRegExpObjecth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/RegExpObject.h (197795 => 197796)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/RegExpObject.h        2016-03-08 21:02:09 UTC (rev 197795)
+++ trunk/Source/JavaScriptCore/runtime/RegExpObject.h        2016-03-08 21:15:07 UTC (rev 197796)
</span><span class="lines">@@ -67,7 +67,9 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     bool test(ExecState* exec, JSGlobalObject* globalObject, JSString* string) { return !!match(exec, globalObject, string); }
</span><ins>+    bool testInline(ExecState* exec, JSGlobalObject* globalObject, JSString* string) { return !!matchInline(exec, globalObject, string); }
</ins><span class="cx">     JSValue exec(ExecState*, JSGlobalObject*, JSString*);
</span><ins>+    JSValue execInline(ExecState*, JSGlobalObject*, JSString*);
</ins><span class="cx"> 
</span><span class="cx">     static bool getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&amp;);
</span><span class="cx">     static void put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&amp;);
</span><span class="lines">@@ -103,6 +105,7 @@
</span><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     MatchResult match(ExecState*, JSGlobalObject*, JSString*);
</span><ins>+    MatchResult matchInline(ExecState*, JSGlobalObject*, JSString*);
</ins><span class="cx"> 
</span><span class="cx">     WriteBarrier&lt;RegExp&gt; m_regExp;
</span><span class="cx">     WriteBarrier&lt;Unknown&gt; m_lastIndex;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeRegExpObjectInlinesh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/runtime/RegExpObjectInlines.h (0 => 197796)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/RegExpObjectInlines.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/runtime/RegExpObjectInlines.h        2016-03-08 21:15:07 UTC (rev 197796)
</span><span class="lines">@@ -0,0 +1,113 @@
</span><ins>+/*
+ *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *  Copyright (C) 2003, 2007, 2008, 2012, 2016 Apple Inc. All Rights Reserved.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef RegExpObjectInlines_h
+#define RegExpObjectInlines_h
+
+#include &quot;ButterflyInlines.h&quot;
+#include &quot;Error.h&quot;
+#include &quot;ExceptionHelpers.h&quot;
+#include &quot;JSArray.h&quot;
+#include &quot;JSGlobalObject.h&quot;
+#include &quot;JSString.h&quot;
+#include &quot;JSCInlines.h&quot;
+#include &quot;RegExpConstructor.h&quot;
+#include &quot;RegExpMatchesArray.h&quot;
+#include &quot;RegExpObject.h&quot;
+
+namespace JSC {
+
+ALWAYS_INLINE unsigned getRegExpObjectLastIndexAsUnsigned(
+    ExecState* exec, RegExpObject* regExpObject, const String&amp; input)
+{
+    JSValue jsLastIndex = regExpObject-&gt;getLastIndex();
+    unsigned lastIndex;
+    if (LIKELY(jsLastIndex.isUInt32())) {
+        lastIndex = jsLastIndex.asUInt32();
+        if (lastIndex &gt; input.length()) {
+            regExpObject-&gt;setLastIndex(exec, 0);
+            return UINT_MAX;
+        }
+    } else {
+        double doubleLastIndex = jsLastIndex.toInteger(exec);
+        if (doubleLastIndex &lt; 0 || doubleLastIndex &gt; input.length()) {
+            regExpObject-&gt;setLastIndex(exec, 0);
+            return UINT_MAX;
+        }
+        lastIndex = static_cast&lt;unsigned&gt;(doubleLastIndex);
+    }
+    return lastIndex;
+}
+
+JSValue RegExpObject::execInline(ExecState* exec, JSGlobalObject* globalObject, JSString* string)
+{
+    RegExp* regExp = this-&gt;regExp();
+    RegExpConstructor* regExpConstructor = globalObject-&gt;regExpConstructor();
+    String input = string-&gt;value(exec); // FIXME: Handle errors. https://bugs.webkit.org/show_bug.cgi?id=155145
+    VM&amp; vm = globalObject-&gt;vm();
+
+    bool global = regExp-&gt;global();
+
+    unsigned lastIndex;
+    if (global) {
+        lastIndex = getRegExpObjectLastIndexAsUnsigned(exec, this, input);
+        if (lastIndex == UINT_MAX)
+            return jsNull();
+    } else
+        lastIndex = 0;
+    
+    MatchResult result;
+    JSArray* array =
+        createRegExpMatchesArray(vm, globalObject, string, input, regExp, lastIndex, result);
+    if (!array) {
+        if (global)
+            setLastIndex(exec, 0);
+        return jsNull();
+    }
+    if (global)
+        setLastIndex(exec, result.end);
+    regExpConstructor-&gt;recordMatch(vm, regExp, string, result);
+    return array;
+}
+
+// Shared implementation used by test and exec.
+MatchResult RegExpObject::matchInline(
+    ExecState* exec, JSGlobalObject* globalObject, JSString* string)
+{
+    RegExp* regExp = this-&gt;regExp();
+    RegExpConstructor* regExpConstructor = globalObject-&gt;regExpConstructor();
+    String input = string-&gt;value(exec); // FIXME: Handle errors. https://bugs.webkit.org/show_bug.cgi?id=155145
+    VM&amp; vm = globalObject-&gt;vm();
+    if (!regExp-&gt;global())
+        return regExpConstructor-&gt;performMatch(vm, regExp, string, input, 0);
+
+    unsigned lastIndex = getRegExpObjectLastIndexAsUnsigned(exec, this, input);
+    if (lastIndex == UINT_MAX)
+        return MatchResult::failed();
+    
+    MatchResult result = regExpConstructor-&gt;performMatch(vm, regExp, string, input, lastIndex);
+    setLastIndex(exec, result.end);
+    return result;
+}
+
+} // namespace JSC
+
+#endif // RegExpObjectInlines_h
+
</ins></span></pre>
</div>
</div>

</body>
</html>