<!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>[175365] 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/175365">175365</a></dd>
<dt>Author</dt> <dd>akling@apple.com</dd>
<dt>Date</dt> <dd>2014-10-29 20:54:23 -0700 (Wed, 29 Oct 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>Use plain JSArray for RegExp matches instead of a lazily populated custom object.
&lt;https://webkit.org/b/138191&gt;

Reviewed by Geoffrey Garen.

We're already offering two RegExp matching APIs, one that collects subpattern
matches (exec), and one that simply tests for a match (test).
Given that, it was pretty overkill to lazily populate the resulting array of
matches, since the user could simply use test() if they didn't need them.

This allows the JIT to generate better code for RegExp match arrays, and also
enables some fast paths in the JSC runtime that check if an object isJSArray().

Looks like ~1.5% improvement on Octane/regexp according to run-jsc-benchmarks.

* jit/Repatch.cpp:
(JSC::tryCacheGetByID):
* runtime/JSArray.h:
(JSC::createArrayButterflyWithExactLength): Deleted.
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::init):
* runtime/RegExpCachedResult.cpp:
(JSC::RegExpCachedResult::visitChildren):
(JSC::RegExpCachedResult::lastResult):
(JSC::RegExpCachedResult::leftContext):
(JSC::RegExpCachedResult::rightContext):
* runtime/RegExpCachedResult.h:
(JSC::RegExpCachedResult::RegExpCachedResult):
(JSC::RegExpCachedResult::record):
(JSC::RegExpCachedResult::input):
* runtime/RegExpConstructor.cpp:
(JSC::RegExpConstructor::getBackref):
(JSC::RegExpConstructor::getLastParen):
(JSC::RegExpConstructor::getLeftContext):
(JSC::RegExpConstructor::getRightContext):
* runtime/RegExpMatchesArray.cpp:
(JSC::createRegExpMatchesArray):
(JSC::RegExpMatchesArray::RegExpMatchesArray): Deleted.
(JSC::RegExpMatchesArray::create): Deleted.
(JSC::RegExpMatchesArray::finishCreation): Deleted.
(JSC::RegExpMatchesArray::visitChildren): Deleted.
(JSC::RegExpMatchesArray::reifyAllProperties): Deleted.
(JSC::RegExpMatchesArray::reifyMatchProperty): Deleted.
(JSC::RegExpMatchesArray::leftContext): Deleted.
(JSC::RegExpMatchesArray::rightContext): Deleted.
* runtime/RegExpMatchesArray.h:
(JSC::RegExpMatchesArray::createStructure): Deleted.
(JSC::RegExpMatchesArray::reifyAllPropertiesIfNecessary): Deleted.
(JSC::RegExpMatchesArray::reifyMatchPropertyIfNecessary): Deleted.
(JSC::RegExpMatchesArray::getOwnPropertySlot): Deleted.
(JSC::RegExpMatchesArray::getOwnPropertySlotByIndex): Deleted.
(JSC::RegExpMatchesArray::put): Deleted.
(JSC::RegExpMatchesArray::putByIndex): Deleted.
(JSC::RegExpMatchesArray::deleteProperty): Deleted.
(JSC::RegExpMatchesArray::deletePropertyByIndex): Deleted.
(JSC::RegExpMatchesArray::getOwnPropertyNames): Deleted.
(JSC::RegExpMatchesArray::defineOwnProperty): Deleted.
(JSC::isRegExpMatchesArray): Deleted.
* runtime/RegExpObject.cpp:
(JSC::RegExpObject::exec):
* runtime/StringPrototype.cpp:
(JSC::stringProtoFuncMatch):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCorejitRepatchcpp">trunk/Source/JavaScriptCore/jit/Repatch.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSArrayh">trunk/Source/JavaScriptCore/runtime/JSArray.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSGlobalObjectcpp">trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeRegExpCachedResultcpp">trunk/Source/JavaScriptCore/runtime/RegExpCachedResult.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeRegExpCachedResulth">trunk/Source/JavaScriptCore/runtime/RegExpCachedResult.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeRegExpConstructorcpp">trunk/Source/JavaScriptCore/runtime/RegExpConstructor.cpp</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="#trunkSourceJavaScriptCoreruntimeStringPrototypecpp">trunk/Source/JavaScriptCore/runtime/StringPrototype.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (175364 => 175365)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2014-10-30 03:36:52 UTC (rev 175364)
+++ trunk/Source/JavaScriptCore/ChangeLog        2014-10-30 03:54:23 UTC (rev 175365)
</span><span class="lines">@@ -1,3 +1,68 @@
</span><ins>+2014-10-29  Andreas Kling  &lt;akling@apple.com&gt;
+
+        Use plain JSArray for RegExp matches instead of a lazily populated custom object.
+        &lt;https://webkit.org/b/138191&gt;
+
+        Reviewed by Geoffrey Garen.
+
+        We're already offering two RegExp matching APIs, one that collects subpattern
+        matches (exec), and one that simply tests for a match (test).
+        Given that, it was pretty overkill to lazily populate the resulting array of
+        matches, since the user could simply use test() if they didn't need them.
+
+        This allows the JIT to generate better code for RegExp match arrays, and also
+        enables some fast paths in the JSC runtime that check if an object isJSArray().
+
+        Looks like ~1.5% improvement on Octane/regexp according to run-jsc-benchmarks.
+
+        * jit/Repatch.cpp:
+        (JSC::tryCacheGetByID):
+        * runtime/JSArray.h:
+        (JSC::createArrayButterflyWithExactLength): Deleted.
+        * runtime/JSGlobalObject.cpp:
+        (JSC::JSGlobalObject::init):
+        * runtime/RegExpCachedResult.cpp:
+        (JSC::RegExpCachedResult::visitChildren):
+        (JSC::RegExpCachedResult::lastResult):
+        (JSC::RegExpCachedResult::leftContext):
+        (JSC::RegExpCachedResult::rightContext):
+        * runtime/RegExpCachedResult.h:
+        (JSC::RegExpCachedResult::RegExpCachedResult):
+        (JSC::RegExpCachedResult::record):
+        (JSC::RegExpCachedResult::input):
+        * runtime/RegExpConstructor.cpp:
+        (JSC::RegExpConstructor::getBackref):
+        (JSC::RegExpConstructor::getLastParen):
+        (JSC::RegExpConstructor::getLeftContext):
+        (JSC::RegExpConstructor::getRightContext):
+        * runtime/RegExpMatchesArray.cpp:
+        (JSC::createRegExpMatchesArray):
+        (JSC::RegExpMatchesArray::RegExpMatchesArray): Deleted.
+        (JSC::RegExpMatchesArray::create): Deleted.
+        (JSC::RegExpMatchesArray::finishCreation): Deleted.
+        (JSC::RegExpMatchesArray::visitChildren): Deleted.
+        (JSC::RegExpMatchesArray::reifyAllProperties): Deleted.
+        (JSC::RegExpMatchesArray::reifyMatchProperty): Deleted.
+        (JSC::RegExpMatchesArray::leftContext): Deleted.
+        (JSC::RegExpMatchesArray::rightContext): Deleted.
+        * runtime/RegExpMatchesArray.h:
+        (JSC::RegExpMatchesArray::createStructure): Deleted.
+        (JSC::RegExpMatchesArray::reifyAllPropertiesIfNecessary): Deleted.
+        (JSC::RegExpMatchesArray::reifyMatchPropertyIfNecessary): Deleted.
+        (JSC::RegExpMatchesArray::getOwnPropertySlot): Deleted.
+        (JSC::RegExpMatchesArray::getOwnPropertySlotByIndex): Deleted.
+        (JSC::RegExpMatchesArray::put): Deleted.
+        (JSC::RegExpMatchesArray::putByIndex): Deleted.
+        (JSC::RegExpMatchesArray::deleteProperty): Deleted.
+        (JSC::RegExpMatchesArray::deletePropertyByIndex): Deleted.
+        (JSC::RegExpMatchesArray::getOwnPropertyNames): Deleted.
+        (JSC::RegExpMatchesArray::defineOwnProperty): Deleted.
+        (JSC::isRegExpMatchesArray): Deleted.
+        * runtime/RegExpObject.cpp:
+        (JSC::RegExpObject::exec):
+        * runtime/StringPrototype.cpp:
+        (JSC::stringProtoFuncMatch):
+
</ins><span class="cx"> 2014-10-29  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Web Inspector: Fix Type Dependency Issues
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitRepatchcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/Repatch.cpp (175364 => 175365)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/Repatch.cpp        2014-10-30 03:36:52 UTC (rev 175364)
+++ trunk/Source/JavaScriptCore/jit/Repatch.cpp        2014-10-30 03:54:23 UTC (rev 175365)
</span><span class="lines">@@ -638,7 +638,7 @@
</span><span class="cx">     CodeBlock* codeBlock = exec-&gt;codeBlock();
</span><span class="cx">     VM* vm = &amp;exec-&gt;vm();
</span><span class="cx"> 
</span><del>-    if ((isJSArray(baseValue) || isRegExpMatchesArray(baseValue) || isJSString(baseValue)) &amp;&amp; propertyName == exec-&gt;propertyNames().length) {
</del><ins>+    if ((isJSArray(baseValue) || isJSString(baseValue)) &amp;&amp; propertyName == exec-&gt;propertyNames().length) {
</ins><span class="cx">         GPRReg baseGPR = static_cast&lt;GPRReg&gt;(stubInfo.patch.baseGPR);
</span><span class="cx"> #if USE(JSVALUE32_64)
</span><span class="cx">         GPRReg resultTagGPR = static_cast&lt;GPRReg&gt;(stubInfo.patch.valueTagGPR);
</span><span class="lines">@@ -647,7 +647,7 @@
</span><span class="cx"> 
</span><span class="cx">         MacroAssembler stubJit;
</span><span class="cx"> 
</span><del>-        if (isJSArray(baseValue) || isRegExpMatchesArray(baseValue)) {
</del><ins>+        if (isJSArray(baseValue)) {
</ins><span class="cx">             GPRReg scratchGPR = TempRegisterSet(stubInfo.patch.usedRegisters).getFreeGPR();
</span><span class="cx">             bool needToRestoreScratch = false;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSArrayh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSArray.h (175364 => 175365)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSArray.h        2014-10-30 03:36:52 UTC (rev 175364)
+++ trunk/Source/JavaScriptCore/runtime/JSArray.h        2014-10-30 03:54:23 UTC (rev 175365)
</span><span class="lines">@@ -190,18 +190,6 @@
</span><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline Butterfly* createArrayButterflyWithExactLength(VM&amp; vm, JSCell* intendedOwner, unsigned initialLength)
-{
-    Butterfly* butterfly = Butterfly::create(
-        vm, intendedOwner, 0, 0, true, indexingHeaderForArray(initialLength, initialLength),
-        ArrayStorage::sizeFor(initialLength));
-    ArrayStorage* storage = butterfly-&gt;arrayStorage();
-    storage-&gt;m_indexBias = 0;
-    storage-&gt;m_sparseMap.clear();
-    storage-&gt;m_numValuesInVector = 0;
-    return butterfly;
-}
-
</del><span class="cx"> inline Butterfly* createArrayButterfly(VM&amp; vm, JSCell* intendedOwner, unsigned initialLength)
</span><span class="cx"> {
</span><span class="cx">     Butterfly* butterfly = Butterfly::create(
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSGlobalObjectcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp (175364 => 175365)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp        2014-10-30 03:36:52 UTC (rev 175364)
+++ trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp        2014-10-30 03:54:23 UTC (rev 175365)
</span><span class="lines">@@ -288,9 +288,9 @@
</span><span class="cx">     m_originalArrayStructureForIndexingShape[SlowPutArrayStorageShape &gt;&gt; IndexingShapeShift].set(vm, this, JSArray::createStructure(vm, this, m_arrayPrototype.get(), ArrayWithSlowPutArrayStorage));
</span><span class="cx">     for (unsigned i = 0; i &lt; NumberOfIndexingShapes; ++i)
</span><span class="cx">         m_arrayStructureForIndexingShapeDuringAllocation[i] = m_originalArrayStructureForIndexingShape[i];
</span><ins>+
+    m_regExpMatchesArrayStructure.set(vm, this, Structure::create(vm, this, m_arrayPrototype.get(), TypeInfo(ObjectType, StructureFlags), JSArray::info(), ArrayWithSlowPutArrayStorage));
</ins><span class="cx">     
</span><del>-    m_regExpMatchesArrayStructure.set(vm, this, RegExpMatchesArray::createStructure(vm, this, m_arrayPrototype.get()));
-    
</del><span class="cx">     RegExp* emptyRegex = RegExp::create(vm, &quot;&quot;, NoFlags);
</span><span class="cx">     
</span><span class="cx">     m_regExpPrototype.set(vm, this, RegExpPrototype::create(vm, RegExpPrototype::createStructure(vm, this, m_objectPrototype.get()), emptyRegex));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeRegExpCachedResultcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/RegExpCachedResult.cpp (175364 => 175365)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/RegExpCachedResult.cpp        2014-10-30 03:36:52 UTC (rev 175364)
+++ trunk/Source/JavaScriptCore/runtime/RegExpCachedResult.cpp        2014-10-30 03:54:23 UTC (rev 175365)
</span><span class="lines">@@ -37,18 +37,40 @@
</span><span class="cx">     visitor.append(&amp;m_lastRegExp);
</span><span class="cx">     visitor.append(&amp;m_reifiedInput);
</span><span class="cx">     visitor.append(&amp;m_reifiedResult);
</span><ins>+    visitor.append(&amp;m_reifiedLeftContext);
+    visitor.append(&amp;m_reifiedRightContext);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-RegExpMatchesArray* RegExpCachedResult::lastResult(ExecState* exec, JSObject* owner)
</del><ins>+JSArray* RegExpCachedResult::lastResult(ExecState* exec, JSObject* owner)
</ins><span class="cx"> {
</span><del>-    if (m_result) {
</del><ins>+    if (!m_reified) {
</ins><span class="cx">         m_reifiedInput.set(exec-&gt;vm(), owner, m_lastInput.get());
</span><del>-        m_reifiedResult.set(exec-&gt;vm(), owner, RegExpMatchesArray::create(exec, m_lastInput.get(), m_lastRegExp.get(), m_result));
-        m_result = MatchResult::failed();
</del><ins>+        m_reifiedResult.set(exec-&gt;vm(), owner, createRegExpMatchesArray(exec, m_lastInput.get(), m_lastRegExp.get(), m_result));
+        m_reified = true;
</ins><span class="cx">     }
</span><span class="cx">     return m_reifiedResult.get();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+JSString* RegExpCachedResult::leftContext(ExecState* exec, JSObject* owner)
+{
+    // Make sure we're reified.
+    lastResult(exec, owner);
+    if (!m_reifiedLeftContext)
+        m_reifiedLeftContext.set(exec-&gt;vm(), owner, m_result.start ? jsSubstring(exec, m_reifiedInput.get(), 0, m_result.start) : jsEmptyString(exec));
+    return m_reifiedLeftContext.get();
+}
+
+JSString* RegExpCachedResult::rightContext(ExecState* exec, JSObject* owner)
+{
+    // Make sure we're reified.
+    lastResult(exec, owner);
+    if (!m_reifiedRightContext) {
+        unsigned length = m_reifiedInput-&gt;length();
+        m_reifiedRightContext.set(exec-&gt;vm(), owner, m_result.end != length ? jsSubstring(exec, m_reifiedInput.get(), m_result.end, length - m_result.end) : jsEmptyString(exec));
+    }
+    return m_reifiedRightContext.get();
+}
+
</ins><span class="cx"> void RegExpCachedResult::setInput(ExecState* exec, JSObject* owner, JSString* input)
</span><span class="cx"> {
</span><span class="cx">     // Make sure we're reified, otherwise m_reifiedInput will be ignored.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeRegExpCachedResulth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/RegExpCachedResult.h (175364 => 175365)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/RegExpCachedResult.h        2014-10-30 03:36:52 UTC (rev 175364)
+++ trunk/Source/JavaScriptCore/runtime/RegExpCachedResult.h        2014-10-30 03:54:23 UTC (rev 175365)
</span><span class="lines">@@ -30,8 +30,8 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><ins>+class JSArray;
</ins><span class="cx"> class JSString;
</span><del>-class RegExpMatchesArray;
</del><span class="cx"> 
</span><span class="cx"> // RegExpCachedResult is used to track the cached results of the last
</span><span class="cx"> // match, stores on the RegExp constructor (e.g. $&amp;, $_, $1, $2 ...).
</span><span class="lines">@@ -46,6 +46,7 @@
</span><span class="cx"> public:
</span><span class="cx">     RegExpCachedResult(VM&amp; vm, JSObject* owner, RegExp* emptyRegExp)
</span><span class="cx">         : m_result(0, 0)
</span><ins>+        , m_reified(false)
</ins><span class="cx">     {
</span><span class="cx">         m_lastInput.set(vm, owner, jsEmptyString(&amp;vm));
</span><span class="cx">         m_lastRegExp.set(vm, owner, emptyRegExp);
</span><span class="lines">@@ -55,28 +56,34 @@
</span><span class="cx">     {
</span><span class="cx">         m_lastRegExp.set(vm, owner, regExp);
</span><span class="cx">         m_lastInput.set(vm, owner, input);
</span><ins>+        m_reifiedLeftContext.clear();
+        m_reifiedRightContext.clear();
</ins><span class="cx">         m_result = result;
</span><ins>+        m_reified = false;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    RegExpMatchesArray* lastResult(ExecState*, JSObject* owner);
</del><ins>+    JSArray* lastResult(ExecState*, JSObject* owner);
</ins><span class="cx">     void setInput(ExecState*, JSObject* owner, JSString*);
</span><span class="cx"> 
</span><ins>+    JSString* leftContext(ExecState*, JSObject* owner);
+    JSString* rightContext(ExecState*, JSObject* owner);
+
</ins><span class="cx">     JSString* input()
</span><span class="cx">     {
</span><del>-        // If m_result showas a match then we're in a lazy state, so m_lastInput
-        // is the most recent value of the input property. If not then we have
-        // reified, in which case m_reifiedInput will contain the correct value.
-        return m_result ? m_lastInput.get() : m_reifiedInput.get();
</del><ins>+        return m_reified ? m_reifiedInput.get() : m_lastInput.get();
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     void visitChildren(SlotVisitor&amp;);
</span><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     MatchResult m_result;
</span><ins>+    bool m_reified;
</ins><span class="cx">     WriteBarrier&lt;JSString&gt; m_lastInput;
</span><span class="cx">     WriteBarrier&lt;RegExp&gt; m_lastRegExp;
</span><del>-    WriteBarrier&lt;RegExpMatchesArray&gt; m_reifiedResult;
</del><ins>+    WriteBarrier&lt;JSArray&gt; m_reifiedResult;
</ins><span class="cx">     WriteBarrier&lt;JSString&gt; m_reifiedInput;
</span><ins>+    WriteBarrier&lt;JSString&gt; m_reifiedLeftContext;
+    WriteBarrier&lt;JSString&gt; m_reifiedRightContext;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeRegExpConstructorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/RegExpConstructor.cpp (175364 => 175365)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/RegExpConstructor.cpp        2014-10-30 03:36:52 UTC (rev 175364)
+++ trunk/Source/JavaScriptCore/runtime/RegExpConstructor.cpp        2014-10-30 03:54:23 UTC (rev 175365)
</span><span class="lines">@@ -116,7 +116,7 @@
</span><span class="cx"> 
</span><span class="cx"> JSValue RegExpConstructor::getBackref(ExecState* exec, unsigned i)
</span><span class="cx"> {
</span><del>-    RegExpMatchesArray* array = m_cachedResult.lastResult(exec, this);
</del><ins>+    JSArray* array = m_cachedResult.lastResult(exec, this);
</ins><span class="cx"> 
</span><span class="cx">     if (i &lt; array-&gt;length()) {
</span><span class="cx">         JSValue result = JSValue(array).get(exec, i);
</span><span class="lines">@@ -129,7 +129,7 @@
</span><span class="cx"> 
</span><span class="cx"> JSValue RegExpConstructor::getLastParen(ExecState* exec)
</span><span class="cx"> {
</span><del>-    RegExpMatchesArray* array = m_cachedResult.lastResult(exec, this);
</del><ins>+    JSArray* array = m_cachedResult.lastResult(exec, this);
</ins><span class="cx">     unsigned length = array-&gt;length();
</span><span class="cx">     if (length &gt; 1) {
</span><span class="cx">         JSValue result = JSValue(array).get(exec, length - 1);
</span><span class="lines">@@ -142,12 +142,12 @@
</span><span class="cx"> 
</span><span class="cx"> JSValue RegExpConstructor::getLeftContext(ExecState* exec)
</span><span class="cx"> {
</span><del>-    return m_cachedResult.lastResult(exec, this)-&gt;leftContext(exec);
</del><ins>+    return m_cachedResult.leftContext(exec, this);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> JSValue RegExpConstructor::getRightContext(ExecState* exec)
</span><span class="cx"> {
</span><del>-    return m_cachedResult.lastResult(exec, this)-&gt;rightContext(exec);
</del><ins>+    return m_cachedResult.rightContext(exec, this);
</ins><span class="cx"> }
</span><span class="cx">     
</span><span class="cx"> bool RegExpConstructor::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot&amp; slot)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeRegExpMatchesArraycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/RegExpMatchesArray.cpp (175364 => 175365)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/RegExpMatchesArray.cpp        2014-10-30 03:36:52 UTC (rev 175364)
+++ trunk/Source/JavaScriptCore/runtime/RegExpMatchesArray.cpp        2014-10-30 03:54:23 UTC (rev 175365)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2012 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2012-2014 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -31,93 +31,37 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><del>-const ClassInfo RegExpMatchesArray::s_info = {&quot;Array&quot;, &amp;JSArray::s_info, 0, CREATE_METHOD_TABLE(RegExpMatchesArray)};
-
-RegExpMatchesArray::RegExpMatchesArray(VM&amp; vm, Butterfly* butterfly, JSGlobalObject* globalObject, JSString* input, RegExp* regExp, MatchResult result)
-    : JSArray(vm, globalObject-&gt;regExpMatchesArrayStructure(), butterfly)
-    , m_result(result)
-    , m_state(ReifiedNone)
</del><ins>+JSArray* createRegExpMatchesArray(ExecState* exec, JSString* input, RegExp* regExp, MatchResult result)
</ins><span class="cx"> {
</span><del>-    m_input.set(vm, this, input);
-    m_regExp.set(vm, this, regExp);
-}
-
-RegExpMatchesArray* RegExpMatchesArray::create(ExecState* exec, JSString* input, RegExp* regExp, MatchResult result)
-{
</del><span class="cx">     ASSERT(result);
</span><span class="cx">     VM&amp; vm = exec-&gt;vm();
</span><del>-    Butterfly* butterfly = createArrayButterflyWithExactLength(vm, 0, regExp-&gt;numSubpatterns() + 1);
-    RegExpMatchesArray* array = new (NotNull, allocateCell&lt;RegExpMatchesArray&gt;(vm.heap)) RegExpMatchesArray(vm, butterfly, exec-&gt;lexicalGlobalObject(), input, regExp, result);
-    array-&gt;finishCreation(vm);
-    return array;
-}
</del><ins>+    JSArray* array = JSArray::tryCreateUninitialized(vm, exec-&gt;lexicalGlobalObject()-&gt;regExpMatchesArrayStructure(), regExp-&gt;numSubpatterns() + 1);
+    RELEASE_ASSERT(array);
</ins><span class="cx"> 
</span><del>-void RegExpMatchesArray::finishCreation(VM&amp; vm)
-{
-    Base::finishCreation(vm);
-}
-
-void RegExpMatchesArray::visitChildren(JSCell* cell, SlotVisitor&amp; visitor)
-{
-    RegExpMatchesArray* thisObject = jsCast&lt;RegExpMatchesArray*&gt;(cell);
-    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
-    Base::visitChildren(thisObject, visitor);
-    visitor.append(&amp;thisObject-&gt;m_input);
-    visitor.append(&amp;thisObject-&gt;m_regExp);
-}
-
-void RegExpMatchesArray::reifyAllProperties(ExecState* exec)
-{
-    ASSERT(m_state != ReifiedAll);
-    ASSERT(m_result);

</del><span class="cx">     SamplingRegion samplingRegion(&quot;Reifying substring properties&quot;);
</span><del>-    
-    reifyMatchPropertyIfNecessary(exec);
</del><span class="cx"> 
</span><del>-    if (unsigned numSubpatterns = m_regExp-&gt;numSubpatterns()) {
</del><ins>+    array-&gt;putDirectIndex(exec, 0, jsSubstring(exec, input, result.start, result.end - result.start));
+
+    if (unsigned numSubpatterns = regExp-&gt;numSubpatterns()) {
</ins><span class="cx">         Vector&lt;int, 32&gt; subpatternResults;
</span><del>-        int position = m_regExp-&gt;match(exec-&gt;vm(), m_input-&gt;value(exec), m_result.start, subpatternResults);
-        ASSERT_UNUSED(position, position &gt;= 0 &amp;&amp; static_cast&lt;size_t&gt;(position) == m_result.start);
-        ASSERT(m_result.start == static_cast&lt;size_t&gt;(subpatternResults[0]));
-        ASSERT(m_result.end == static_cast&lt;size_t&gt;(subpatternResults[1]));
</del><ins>+        int position = regExp-&gt;match(exec-&gt;vm(), input-&gt;value(exec), result.start, subpatternResults);
+        ASSERT_UNUSED(position, position &gt;= 0 &amp;&amp; static_cast&lt;size_t&gt;(position) == result.start);
+        ASSERT(result.start == static_cast&lt;size_t&gt;(subpatternResults[0]));
+        ASSERT(result.end == static_cast&lt;size_t&gt;(subpatternResults[1]));
</ins><span class="cx"> 
</span><span class="cx">         for (unsigned i = 1; i &lt;= numSubpatterns; ++i) {
</span><span class="cx">             int start = subpatternResults[2 * i];
</span><span class="cx">             if (start &gt;= 0)
</span><del>-                putDirectIndex(exec, i, jsSubstring(exec, m_input.get(), start, subpatternResults[2 * i + 1] - start));
</del><ins>+                array-&gt;putDirectIndex(exec, i, jsSubstring(exec, input, start, subpatternResults[2 * i + 1] - start));
</ins><span class="cx">             else
</span><del>-                putDirectIndex(exec, i, jsUndefined());
</del><ins>+                array-&gt;putDirectIndex(exec, i, jsUndefined());
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    putDirect(exec-&gt;vm(), exec-&gt;propertyNames().index, jsNumber(m_result.start));
-    putDirect(exec-&gt;vm(), exec-&gt;propertyNames().input, m_input.get());
</del><ins>+    array-&gt;putDirect(exec-&gt;vm(), exec-&gt;propertyNames().index, jsNumber(result.start));
+    array-&gt;putDirect(exec-&gt;vm(), exec-&gt;propertyNames().input, input);
</ins><span class="cx"> 
</span><del>-    m_state = ReifiedAll;
</del><ins>+    return array;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void RegExpMatchesArray::reifyMatchProperty(ExecState* exec)
-{
-    ASSERT(m_state == ReifiedNone);
-    ASSERT(m_result);
-    putDirectIndex(exec, 0, jsSubstring(exec, m_input.get(), m_result.start, m_result.end - m_result.start));
-    m_state = ReifiedMatch;
-}
-
-JSString* RegExpMatchesArray::leftContext(ExecState* exec)
-{
-    if (!m_result.start)
-        return jsEmptyString(exec);
-    return jsSubstring(exec, m_input.get(), 0, m_result.start);
-}
-
-JSString* RegExpMatchesArray::rightContext(ExecState* exec)
-{
-    unsigned length = m_input-&gt;length();
-    if (m_result.end == length)
-        return jsEmptyString(exec);
-    return jsSubstring(exec, m_input.get(), m_result.end, length - m_result.end);
-}
-
</del><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeRegExpMatchesArrayh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/RegExpMatchesArray.h (175364 => 175365)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/RegExpMatchesArray.h        2014-10-30 03:36:52 UTC (rev 175364)
+++ trunk/Source/JavaScriptCore/runtime/RegExpMatchesArray.h        2014-10-30 03:54:23 UTC (rev 175365)
</span><span class="lines">@@ -26,120 +26,8 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><del>-class RegExpMatchesArray : public JSArray {
-private:
-    RegExpMatchesArray(VM&amp;, Butterfly*, JSGlobalObject*, JSString*, RegExp*, MatchResult);
</del><ins>+JSArray* createRegExpMatchesArray(ExecState*, JSString*, RegExp*, MatchResult);
</ins><span class="cx"> 
</span><del>-    enum ReifiedState { ReifiedNone, ReifiedMatch, ReifiedAll };
-
-public:
-    typedef JSArray Base;
-
-    static RegExpMatchesArray* create(ExecState*, JSString*, RegExp*, MatchResult);
-
-    JSString* leftContext(ExecState*);
-    JSString* rightContext(ExecState*);
-
-    DECLARE_INFO;
-
-    static Structure* createStructure(VM&amp; vm, JSGlobalObject* globalObject, JSValue prototype)
-    {
-        return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info(), ArrayWithSlowPutArrayStorage);
-    }
-
-    static void visitChildren(JSCell*, SlotVisitor&amp;);
-
-protected:
-    void finishCreation(VM&amp;);
-
-    static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesGetPropertyNames | Base::StructureFlags;
-
-private:
-    ALWAYS_INLINE void reifyAllPropertiesIfNecessary(ExecState* exec)
-    {
-        if (m_state != ReifiedAll)
-            reifyAllProperties(exec);
-    }
-
-    ALWAYS_INLINE void reifyMatchPropertyIfNecessary(ExecState* exec)
-    {
-        if (m_state == ReifiedNone)
-            reifyMatchProperty(exec);
-    }
-
-    static bool getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot&amp; slot)
-    {
-        RegExpMatchesArray* thisObject = jsCast&lt;RegExpMatchesArray*&gt;(object);
-        thisObject-&gt;reifyAllPropertiesIfNecessary(exec);
-        return JSArray::getOwnPropertySlot(thisObject, exec, propertyName, slot);
-    }
-
-    static bool getOwnPropertySlotByIndex(JSObject* object, ExecState* exec, unsigned propertyName, PropertySlot&amp; slot)
-    {
-        RegExpMatchesArray* thisObject = jsCast&lt;RegExpMatchesArray*&gt;(object);
-        if (propertyName)
-            thisObject-&gt;reifyAllPropertiesIfNecessary(exec);
-        else
-            thisObject-&gt;reifyMatchPropertyIfNecessary(exec);
-        return JSArray::getOwnPropertySlotByIndex(thisObject, exec, propertyName, slot);
-    }
-
-    static void put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue v, PutPropertySlot&amp; slot)
-    {
-        RegExpMatchesArray* thisObject = jsCast&lt;RegExpMatchesArray*&gt;(cell);
-        thisObject-&gt;reifyAllPropertiesIfNecessary(exec);
-        JSArray::put(thisObject, exec, propertyName, v, slot);
-    }
-
-    static void putByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, JSValue v, bool shouldThrow)
-    {
-        RegExpMatchesArray* thisObject = jsCast&lt;RegExpMatchesArray*&gt;(cell);
-        thisObject-&gt;reifyAllPropertiesIfNecessary(exec);
-        JSArray::putByIndex(thisObject, exec, propertyName, v, shouldThrow);
-    }
-
-    static bool deleteProperty(JSCell* cell, ExecState* exec, PropertyName propertyName)
-    {
-        RegExpMatchesArray* thisObject = jsCast&lt;RegExpMatchesArray*&gt;(cell);
-        thisObject-&gt;reifyAllPropertiesIfNecessary(exec);
-        return JSArray::deleteProperty(thisObject, exec, propertyName);
-    }
-
-    static bool deletePropertyByIndex(JSCell* cell, ExecState* exec, unsigned propertyName)
-    {
-        RegExpMatchesArray* thisObject = jsCast&lt;RegExpMatchesArray*&gt;(cell);
-        thisObject-&gt;reifyAllPropertiesIfNecessary(exec);
-        return JSArray::deletePropertyByIndex(thisObject, exec, propertyName);
-    }
-
-    static void getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray&amp; arr, EnumerationMode mode = ExcludeDontEnumProperties)
-    {
-        RegExpMatchesArray* thisObject = jsCast&lt;RegExpMatchesArray*&gt;(object);
-        thisObject-&gt;reifyAllPropertiesIfNecessary(exec);
-        JSArray::getOwnPropertyNames(thisObject, exec, arr, mode);
-    }
-
-    static bool defineOwnProperty(JSObject* object, ExecState* exec, PropertyName propertyName, const PropertyDescriptor&amp; descriptor, bool shouldThrow)
-    {
-        RegExpMatchesArray* thisObject = jsCast&lt;RegExpMatchesArray*&gt;(object);
-        thisObject-&gt;reifyAllPropertiesIfNecessary(exec);
-        return JSArray::defineOwnProperty(object, exec, propertyName, descriptor, shouldThrow);
-    }
-
-    void reifyAllProperties(ExecState*);
-    void reifyMatchProperty(ExecState*);
-
-    WriteBarrier&lt;JSString&gt; m_input;
-    WriteBarrier&lt;RegExp&gt; m_regExp;
-    MatchResult m_result;
-    ReifiedState m_state;
-};
-
-inline bool isRegExpMatchesArray(JSValue value)
-{
-    return value.isCell() &amp;&amp; value.asCell()-&gt;classInfo() == RegExpMatchesArray::info();
</del><span class="cx"> }
</span><span class="cx"> 
</span><del>-}
-
</del><span class="cx"> #endif // RegExpMatchesArray_h
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeRegExpObjectcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/RegExpObject.cpp (175364 => 175365)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/RegExpObject.cpp        2014-10-30 03:36:52 UTC (rev 175364)
+++ trunk/Source/JavaScriptCore/runtime/RegExpObject.cpp        2014-10-30 03:54:23 UTC (rev 175365)
</span><span class="lines">@@ -302,7 +302,7 @@
</span><span class="cx"> JSValue RegExpObject::exec(ExecState* exec, JSString* string)
</span><span class="cx"> {
</span><span class="cx">     if (MatchResult result = match(exec, string))
</span><del>-        return RegExpMatchesArray::create(exec, string, regExp(), result);
</del><ins>+        return createRegExpMatchesArray(exec, string, regExp(), result);
</ins><span class="cx">     return jsNull();
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeStringPrototypecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/StringPrototype.cpp (175364 => 175365)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/StringPrototype.cpp        2014-10-30 03:36:52 UTC (rev 175364)
+++ trunk/Source/JavaScriptCore/runtime/StringPrototype.cpp        2014-10-30 03:54:23 UTC (rev 175365)
</span><span class="lines">@@ -864,7 +864,7 @@
</span><span class="cx">     MatchResult result = regExpConstructor-&gt;performMatch(*vm, regExp, string, s, 0);
</span><span class="cx">     // case without 'g' flag is handled like RegExp.prototype.exec
</span><span class="cx">     if (!global)
</span><del>-        return JSValue::encode(result ? RegExpMatchesArray::create(exec, string, regExp, result) : jsNull());
</del><ins>+        return JSValue::encode(result ? createRegExpMatchesArray(exec, string, regExp, result) : jsNull());
</ins><span class="cx"> 
</span><span class="cx">     // return array of matches
</span><span class="cx">     MarkedArgumentBuffer list;
</span></span></pre>
</div>
</div>

</body>
</html>