<!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>[203206] 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/203206">203206</a></dd>
<dt>Author</dt> <dd>msaboff@apple.com</dd>
<dt>Date</dt> <dd>2016-07-13 18:20:11 -0700 (Wed, 13 Jul 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>YARR uses mixture of int and unsigned values to index into subject string
https://bugs.webkit.org/show_bug.cgi?id=159744

Reviewed by Benjamin Poulain.

In most cases, we refer to characters in subject strings using a negative index from the number of
&quot;checked&quot; characters in a subject string.  The required length is compared against the actual length
and then we use that required length as the checked amount.  For example, when matching the string of
4 digits in the RegExp /abc \d{4}/, we know that need 8 characters in the subject string.  We refer
to the digits part of the expression from an already checked index of 8 and use negative offsets of
-4 through -1.  In many cases we used a signed int for the negative offsets.  There are other cases
where we used unsigned values as the amount of negative offset to use when accessing subject characters.

Changed all occurrances of character offsets to unsigned or Checked Arithmetic unsigned values.  Note
that the pre-existing Checked class is used in other places to check for under/overflow with arithmetic
operations.  Those unsigned offsets are always the number of characters before (negative) from the
current checked character offset.  Also added some asserts for cases where arithmetic is not protected
by other checks or with Checked&lt;&gt; wrapped values.

In the case of the JIT, subject characters are accessed using base with scaled index and offset
addressing.  The MacroAssembler provides this addressing using the BaseIndex struct.  The offset for
this struct is a 32 bit signed quantity.  Since we only care about negative offsets, we really only
have 31 bits.  Changed the generation of a BaseOffset address to handle the case when the offset and
scaled combination will exceed the 31 bits of negative offset.  This is done by moving the base value
into a temp register and biasing the temp base and offset to smaller values so that we can emit
instructions that can reference characters without exceeding the 31 bits of negative offset.

To abstract the character address generation, put the base with scaled index and offset into
one function and used that function everywhere the YARR JIT wants to access subject characters.
Also consilidated a few cases where we were generating inline what readCharacter() does.  Usually
this was due to using a different index register.

Added a new regression test.

* tests/stress/regress-159744.js: Added regression test.
(testRegExp):
* yarr/YarrInterpreter.cpp:
(JSC::Yarr::Interpreter::recordParenthesesMatch):
(JSC::Yarr::Interpreter::resetMatches):
(JSC::Yarr::Interpreter::matchParenthesesOnceEnd):
(JSC::Yarr::Interpreter::backtrackParenthesesOnceEnd):
(JSC::Yarr::ByteCompiler::closeBodyAlternative):
(JSC::Yarr::ByteCompiler::atomParenthesesSubpatternEnd):
(JSC::Yarr::ByteCompiler::atomParenthesesOnceEnd):
(JSC::Yarr::ByteCompiler::atomParenthesesTerminalEnd):
(JSC::Yarr::ByteCompiler::emitDisjunction):
* yarr/YarrInterpreter.h:
(JSC::Yarr::ByteTerm::ByteTerm):
(JSC::Yarr::ByteTerm::BOL):
(JSC::Yarr::ByteTerm::UncheckInput):
(JSC::Yarr::ByteTerm::EOL):
(JSC::Yarr::ByteTerm::WordBoundary):
(JSC::Yarr::ByteTerm::BackReference):
* yarr/YarrJIT.cpp:
(JSC::Yarr::YarrGenerator::notAtEndOfInput):
(JSC::Yarr::YarrGenerator::negativeOffsetIndexedAddress):
(JSC::Yarr::YarrGenerator::readCharacter):
(JSC::Yarr::YarrGenerator::jumpIfCharNotEquals):
(JSC::Yarr::YarrGenerator::storeToFrame):
(JSC::Yarr::YarrGenerator::generateAssertionBOL):
(JSC::Yarr::YarrGenerator::backtrackAssertionBOL):
(JSC::Yarr::YarrGenerator::generateAssertionEOL):
(JSC::Yarr::YarrGenerator::matchAssertionWordchar):
(JSC::Yarr::YarrGenerator::generateAssertionWordBoundary):
(JSC::Yarr::YarrGenerator::generatePatternCharacterOnce):
(JSC::Yarr::YarrGenerator::generatePatternCharacterFixed):
(JSC::Yarr::YarrGenerator::generatePatternCharacterGreedy):
(JSC::Yarr::YarrGenerator::backtrackPatternCharacterNonGreedy):
(JSC::Yarr::YarrGenerator::generateCharacterClassOnce):
(JSC::Yarr::YarrGenerator::generateCharacterClassFixed):
(JSC::Yarr::YarrGenerator::generateCharacterClassGreedy):
(JSC::Yarr::YarrGenerator::backtrackCharacterClassNonGreedy):
(JSC::Yarr::YarrGenerator::generate):
(JSC::Yarr::YarrGenerator::backtrack):
(JSC::Yarr::YarrGenerator::YarrGenerator):
* yarr/YarrPattern.h:
(JSC::Yarr::PatternTerm::PatternTerm):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreyarrYarrInterpretercpp">trunk/Source/JavaScriptCore/yarr/YarrInterpreter.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreyarrYarrInterpreterh">trunk/Source/JavaScriptCore/yarr/YarrInterpreter.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreyarrYarrJITcpp">trunk/Source/JavaScriptCore/yarr/YarrJIT.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreyarrYarrPatternh">trunk/Source/JavaScriptCore/yarr/YarrPattern.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoretestsstressregress159744js">trunk/Source/JavaScriptCore/tests/stress/regress-159744.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (203205 => 203206)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-07-14 00:52:00 UTC (rev 203205)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-07-14 01:20:11 UTC (rev 203206)
</span><span class="lines">@@ -1,3 +1,83 @@
</span><ins>+2016-07-13  Michael Saboff  &lt;msaboff@apple.com&gt;
+
+        YARR uses mixture of int and unsigned values to index into subject string
+        https://bugs.webkit.org/show_bug.cgi?id=159744
+
+        Reviewed by Benjamin Poulain.
+
+        In most cases, we refer to characters in subject strings using a negative index from the number of
+        &quot;checked&quot; characters in a subject string.  The required length is compared against the actual length
+        and then we use that required length as the checked amount.  For example, when matching the string of
+        4 digits in the RegExp /abc \d{4}/, we know that need 8 characters in the subject string.  We refer
+        to the digits part of the expression from an already checked index of 8 and use negative offsets of
+        -4 through -1.  In many cases we used a signed int for the negative offsets.  There are other cases
+        where we used unsigned values as the amount of negative offset to use when accessing subject characters.
+
+        Changed all occurrances of character offsets to unsigned or Checked Arithmetic unsigned values.  Note
+        that the pre-existing Checked class is used in other places to check for under/overflow with arithmetic
+        operations.  Those unsigned offsets are always the number of characters before (negative) from the
+        current checked character offset.  Also added some asserts for cases where arithmetic is not protected
+        by other checks or with Checked&lt;&gt; wrapped values.
+
+        In the case of the JIT, subject characters are accessed using base with scaled index and offset
+        addressing.  The MacroAssembler provides this addressing using the BaseIndex struct.  The offset for
+        this struct is a 32 bit signed quantity.  Since we only care about negative offsets, we really only
+        have 31 bits.  Changed the generation of a BaseOffset address to handle the case when the offset and
+        scaled combination will exceed the 31 bits of negative offset.  This is done by moving the base value
+        into a temp register and biasing the temp base and offset to smaller values so that we can emit
+        instructions that can reference characters without exceeding the 31 bits of negative offset.
+
+        To abstract the character address generation, put the base with scaled index and offset into
+        one function and used that function everywhere the YARR JIT wants to access subject characters.
+        Also consilidated a few cases where we were generating inline what readCharacter() does.  Usually
+        this was due to using a different index register.
+
+        Added a new regression test.
+
+        * tests/stress/regress-159744.js: Added regression test.
+        (testRegExp):
+        * yarr/YarrInterpreter.cpp:
+        (JSC::Yarr::Interpreter::recordParenthesesMatch):
+        (JSC::Yarr::Interpreter::resetMatches):
+        (JSC::Yarr::Interpreter::matchParenthesesOnceEnd):
+        (JSC::Yarr::Interpreter::backtrackParenthesesOnceEnd):
+        (JSC::Yarr::ByteCompiler::closeBodyAlternative):
+        (JSC::Yarr::ByteCompiler::atomParenthesesSubpatternEnd):
+        (JSC::Yarr::ByteCompiler::atomParenthesesOnceEnd):
+        (JSC::Yarr::ByteCompiler::atomParenthesesTerminalEnd):
+        (JSC::Yarr::ByteCompiler::emitDisjunction):
+        * yarr/YarrInterpreter.h:
+        (JSC::Yarr::ByteTerm::ByteTerm):
+        (JSC::Yarr::ByteTerm::BOL):
+        (JSC::Yarr::ByteTerm::UncheckInput):
+        (JSC::Yarr::ByteTerm::EOL):
+        (JSC::Yarr::ByteTerm::WordBoundary):
+        (JSC::Yarr::ByteTerm::BackReference):
+        * yarr/YarrJIT.cpp:
+        (JSC::Yarr::YarrGenerator::notAtEndOfInput):
+        (JSC::Yarr::YarrGenerator::negativeOffsetIndexedAddress):
+        (JSC::Yarr::YarrGenerator::readCharacter):
+        (JSC::Yarr::YarrGenerator::jumpIfCharNotEquals):
+        (JSC::Yarr::YarrGenerator::storeToFrame):
+        (JSC::Yarr::YarrGenerator::generateAssertionBOL):
+        (JSC::Yarr::YarrGenerator::backtrackAssertionBOL):
+        (JSC::Yarr::YarrGenerator::generateAssertionEOL):
+        (JSC::Yarr::YarrGenerator::matchAssertionWordchar):
+        (JSC::Yarr::YarrGenerator::generateAssertionWordBoundary):
+        (JSC::Yarr::YarrGenerator::generatePatternCharacterOnce):
+        (JSC::Yarr::YarrGenerator::generatePatternCharacterFixed):
+        (JSC::Yarr::YarrGenerator::generatePatternCharacterGreedy):
+        (JSC::Yarr::YarrGenerator::backtrackPatternCharacterNonGreedy):
+        (JSC::Yarr::YarrGenerator::generateCharacterClassOnce):
+        (JSC::Yarr::YarrGenerator::generateCharacterClassFixed):
+        (JSC::Yarr::YarrGenerator::generateCharacterClassGreedy):
+        (JSC::Yarr::YarrGenerator::backtrackCharacterClassNonGreedy):
+        (JSC::Yarr::YarrGenerator::generate):
+        (JSC::Yarr::YarrGenerator::backtrack):
+        (JSC::Yarr::YarrGenerator::YarrGenerator):
+        * yarr/YarrPattern.h:
+        (JSC::Yarr::PatternTerm::PatternTerm):
+
</ins><span class="cx"> 2016-07-13  Keith Miller  &lt;keith_miller@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Crashes with detached ArrayBuffers
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressregress159744js"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/regress-159744.js (0 => 203206)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/regress-159744.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/regress-159744.js        2016-07-14 01:20:11 UTC (rev 203206)
</span><span class="lines">@@ -0,0 +1,15 @@
</span><ins>+// Regression test for 159744.  This test should not crash or throw an exception.
+
+function testRegExp(pattern, flags, string, result)
+{
+    let r = new RegExp(pattern, flags);
+    if (r.exec(string) !== result)
+        throw(&quot;Expected &quot; + r + &quot;exec(\&quot;&quot; + string + &quot;\&quot;) to return &quot; + result + &quot;.&quot;);
+}
+
+testRegExp(&quot;((?=$))??(?:\\1){34359738368,}&quot;, &quot;gm&quot;, &quot;abc\nabc\nabc\nabc\n&quot;, null);
+testRegExp(&quot;(\\w+)(?:\\s(\\1)){1100000000,}&quot;, &quot;i&quot;, &quot;word Word WORD WoRd&quot;, null);
+testRegExp(&quot;\\d{4,}.{1073741825}&quot;, &quot;&quot;, &quot;1234567\u1234&quot;, null);
+testRegExp(&quot;(?:abcd){2148473648,}&quot;, &quot;&quot;, &quot;abcdabcdabcd&quot;, null);
+testRegExp(&quot;(?:abcd){2148473648,}&quot;, &quot;y&quot;, &quot;abcdabcdabcd&quot;, null);
+testRegExp(&quot;(ab){1073741825,}(xy){1073741825,}&quot;, &quot;&quot;, &quot;abxyabxy&quot;, null);
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreyarrYarrInterpretercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/yarr/YarrInterpreter.cpp (203205 => 203206)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/yarr/YarrInterpreter.cpp        2016-07-14 00:52:00 UTC (rev 203205)
+++ trunk/Source/JavaScriptCore/yarr/YarrInterpreter.cpp        2016-07-14 01:20:11 UTC (rev 203206)
</span><span class="lines">@@ -675,8 +675,8 @@
</span><span class="cx">     {
</span><span class="cx">         if (term.capture()) {
</span><span class="cx">             unsigned subpatternId = term.atom.subpatternId;
</span><del>-            output[(subpatternId &lt;&lt; 1)] = context-&gt;getDisjunctionContext(term)-&gt;matchBegin + term.inputPosition;
-            output[(subpatternId &lt;&lt; 1) + 1] = context-&gt;getDisjunctionContext(term)-&gt;matchEnd + term.inputPosition;
</del><ins>+            output[(subpatternId &lt;&lt; 1)] = context-&gt;getDisjunctionContext(term)-&gt;matchBegin - term.inputPosition;
+            output[(subpatternId &lt;&lt; 1) + 1] = context-&gt;getDisjunctionContext(term)-&gt;matchEnd - term.inputPosition;
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx">     void resetMatches(ByteTerm&amp; term, ParenthesesDisjunctionContext* context)
</span><span class="lines">@@ -742,7 +742,7 @@
</span><span class="cx"> 
</span><span class="cx">         if (term.capture()) {
</span><span class="cx">             unsigned subpatternId = term.atom.subpatternId;
</span><del>-            output[(subpatternId &lt;&lt; 1) + 1] = input.getPos() + term.inputPosition;
</del><ins>+            output[(subpatternId &lt;&lt; 1) + 1] = input.getPos() - term.inputPosition;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (term.atom.quantityType == QuantifierFixedCount)
</span><span class="lines">@@ -806,7 +806,7 @@
</span><span class="cx">                     ASSERT((&amp;term - term.atom.parenthesesWidth)-&gt;type == ByteTerm::TypeParenthesesSubpatternOnceBegin);
</span><span class="cx">                     ASSERT((&amp;term - term.atom.parenthesesWidth)-&gt;inputPosition == term.inputPosition);
</span><span class="cx">                     unsigned subpatternId = term.atom.subpatternId;
</span><del>-                    output[subpatternId &lt;&lt; 1] = input.getPos() + term.inputPosition;
</del><ins>+                    output[subpatternId &lt;&lt; 1] = input.getPos() - term.inputPosition;
</ins><span class="cx">                 }
</span><span class="cx">                 context-&gt;term -= term.atom.parenthesesWidth;
</span><span class="cx">                 return true;
</span><span class="lines">@@ -1811,7 +1811,7 @@
</span><span class="cx">         m_bodyDisjunction-&gt;terms[endIndex].frameLocation = frameLocation;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void atomParenthesesSubpatternEnd(unsigned lastSubpatternId, int inputPosition, unsigned frameLocation, Checked&lt;unsigned&gt; quantityCount, QuantifierType quantityType, unsigned callFrameSize = 0)
</del><ins>+    void atomParenthesesSubpatternEnd(unsigned lastSubpatternId, unsigned inputPosition, unsigned frameLocation, Checked&lt;unsigned&gt; quantityCount, QuantifierType quantityType, unsigned callFrameSize = 0)
</ins><span class="cx">     {
</span><span class="cx">         unsigned beginTerm = popParenthesesStack();
</span><span class="cx">         closeAlternative(beginTerm + 1);
</span><span class="lines">@@ -1845,7 +1845,7 @@
</span><span class="cx">         m_bodyDisjunction-&gt;terms[beginTerm].frameLocation = frameLocation;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void atomParenthesesOnceEnd(int inputPosition, unsigned frameLocation, Checked&lt;unsigned&gt; quantityCount, QuantifierType quantityType)
</del><ins>+    void atomParenthesesOnceEnd(unsigned inputPosition, unsigned frameLocation, Checked&lt;unsigned&gt; quantityCount, QuantifierType quantityType)
</ins><span class="cx">     {
</span><span class="cx">         unsigned beginTerm = popParenthesesStack();
</span><span class="cx">         closeAlternative(beginTerm + 1);
</span><span class="lines">@@ -1867,7 +1867,7 @@
</span><span class="cx">         m_bodyDisjunction-&gt;terms[endTerm].atom.quantityType = quantityType;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void atomParenthesesTerminalEnd(int inputPosition, unsigned frameLocation, Checked&lt;unsigned&gt; quantityCount, QuantifierType quantityType)
</del><ins>+    void atomParenthesesTerminalEnd(unsigned inputPosition, unsigned frameLocation, Checked&lt;unsigned&gt; quantityCount, QuantifierType quantityType)
</ins><span class="cx">     {
</span><span class="cx">         unsigned beginTerm = popParenthesesStack();
</span><span class="cx">         closeAlternative(beginTerm + 1);
</span><span class="lines">@@ -1983,18 +1983,21 @@
</span><span class="cx">                             disjunctionAlreadyCheckedCount = term.parentheses.disjunction-&gt;m_minimumSize;
</span><span class="cx">                         else
</span><span class="cx">                             alternativeFrameLocation += YarrStackSpaceForBackTrackInfoParenthesesOnce;
</span><del>-                        unsigned delegateEndInputOffset = term.inputPosition - currentCountAlreadyChecked;
-                        atomParenthesesOnceBegin(term.parentheses.subpatternId, term.capture(), disjunctionAlreadyCheckedCount - delegateEndInputOffset, term.frameLocation, alternativeFrameLocation);
</del><ins>+                        ASSERT(currentCountAlreadyChecked &gt;= term.inputPosition);
+                        unsigned delegateEndInputOffset = currentCountAlreadyChecked - term.inputPosition;
+                        atomParenthesesOnceBegin(term.parentheses.subpatternId, term.capture(), disjunctionAlreadyCheckedCount + delegateEndInputOffset, term.frameLocation, alternativeFrameLocation);
</ins><span class="cx">                         emitDisjunction(term.parentheses.disjunction, currentCountAlreadyChecked, disjunctionAlreadyCheckedCount);
</span><span class="cx">                         atomParenthesesOnceEnd(delegateEndInputOffset, term.frameLocation, term.quantityCount, term.quantityType);
</span><span class="cx">                     } else if (term.parentheses.isTerminal) {
</span><del>-                        unsigned delegateEndInputOffset = term.inputPosition - currentCountAlreadyChecked;
-                        atomParenthesesTerminalBegin(term.parentheses.subpatternId, term.capture(), disjunctionAlreadyCheckedCount - delegateEndInputOffset, term.frameLocation, term.frameLocation + YarrStackSpaceForBackTrackInfoParenthesesOnce);
</del><ins>+                        ASSERT(currentCountAlreadyChecked &gt;= term.inputPosition);
+                        unsigned delegateEndInputOffset = currentCountAlreadyChecked - term.inputPosition;
+                        atomParenthesesTerminalBegin(term.parentheses.subpatternId, term.capture(), disjunctionAlreadyCheckedCount + delegateEndInputOffset, term.frameLocation, term.frameLocation + YarrStackSpaceForBackTrackInfoParenthesesOnce);
</ins><span class="cx">                         emitDisjunction(term.parentheses.disjunction, currentCountAlreadyChecked, disjunctionAlreadyCheckedCount);
</span><span class="cx">                         atomParenthesesTerminalEnd(delegateEndInputOffset, term.frameLocation, term.quantityCount, term.quantityType);
</span><span class="cx">                     } else {
</span><del>-                        unsigned delegateEndInputOffset = term.inputPosition - currentCountAlreadyChecked;
-                        atomParenthesesSubpatternBegin(term.parentheses.subpatternId, term.capture(), disjunctionAlreadyCheckedCount - delegateEndInputOffset, term.frameLocation, 0);
</del><ins>+                        ASSERT(currentCountAlreadyChecked &gt;= term.inputPosition);
+                        unsigned delegateEndInputOffset = currentCountAlreadyChecked - term.inputPosition;
+                        atomParenthesesSubpatternBegin(term.parentheses.subpatternId, term.capture(), disjunctionAlreadyCheckedCount + delegateEndInputOffset, term.frameLocation, 0);
</ins><span class="cx">                         emitDisjunction(term.parentheses.disjunction, currentCountAlreadyChecked, 0);
</span><span class="cx">                         atomParenthesesSubpatternEnd(term.parentheses.lastSubpatternId, delegateEndInputOffset, term.frameLocation, term.quantityCount, term.quantityType, term.parentheses.disjunction-&gt;m_callFrameSize);
</span><span class="cx">                     }
</span><span class="lines">@@ -2004,8 +2007,8 @@
</span><span class="cx">                 case PatternTerm::TypeParentheticalAssertion: {
</span><span class="cx">                     unsigned alternativeFrameLocation = term.frameLocation + YarrStackSpaceForBackTrackInfoParentheticalAssertion;
</span><span class="cx"> 
</span><del>-                    ASSERT(currentCountAlreadyChecked &gt;= static_cast&lt;unsigned&gt;(term.inputPosition));
-                    unsigned positiveInputOffset = currentCountAlreadyChecked - static_cast&lt;unsigned&gt;(term.inputPosition);
</del><ins>+                    ASSERT(currentCountAlreadyChecked &gt;= term.inputPosition);
+                    unsigned positiveInputOffset = currentCountAlreadyChecked - term.inputPosition;
</ins><span class="cx">                     unsigned uncheckAmount = 0;
</span><span class="cx">                     if (positiveInputOffset &gt; term.parentheses.disjunction-&gt;m_minimumSize) {
</span><span class="cx">                         uncheckAmount = positiveInputOffset - term.parentheses.disjunction-&gt;m_minimumSize;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreyarrYarrInterpreterh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/yarr/YarrInterpreter.h (203205 => 203206)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/yarr/YarrInterpreter.h        2016-07-14 00:52:00 UTC (rev 203205)
+++ trunk/Source/JavaScriptCore/yarr/YarrInterpreter.h        2016-07-14 01:20:11 UTC (rev 203206)
</span><span class="lines">@@ -106,7 +106,7 @@
</span><span class="cx">     bool m_invert : 1;
</span><span class="cx">     unsigned inputPosition;
</span><span class="cx"> 
</span><del>-    ByteTerm(UChar32 ch, int inputPos, unsigned frameLocation, Checked&lt;unsigned&gt; quantityCount, QuantifierType quantityType)
</del><ins>+    ByteTerm(UChar32 ch, unsigned inputPos, unsigned frameLocation, Checked&lt;unsigned&gt; quantityCount, QuantifierType quantityType)
</ins><span class="cx">         : frameLocation(frameLocation)
</span><span class="cx">         , m_capture(false)
</span><span class="cx">         , m_invert(false)
</span><span class="lines">@@ -129,7 +129,7 @@
</span><span class="cx">         inputPosition = inputPos;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    ByteTerm(UChar32 lo, UChar32 hi, int inputPos, unsigned frameLocation, Checked&lt;unsigned&gt; quantityCount, QuantifierType quantityType)
</del><ins>+    ByteTerm(UChar32 lo, UChar32 hi, unsigned inputPos, unsigned frameLocation, Checked&lt;unsigned&gt; quantityCount, QuantifierType quantityType)
</ins><span class="cx">         : frameLocation(frameLocation)
</span><span class="cx">         , m_capture(false)
</span><span class="cx">         , m_invert(false)
</span><span class="lines">@@ -153,7 +153,7 @@
</span><span class="cx">         inputPosition = inputPos;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    ByteTerm(CharacterClass* characterClass, bool invert, int inputPos)
</del><ins>+    ByteTerm(CharacterClass* characterClass, bool invert, unsigned inputPos)
</ins><span class="cx">         : type(ByteTerm::TypeCharacterClass)
</span><span class="cx">         , m_capture(false)
</span><span class="cx">         , m_invert(invert)
</span><span class="lines">@@ -164,7 +164,7 @@
</span><span class="cx">         inputPosition = inputPos;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    ByteTerm(Type type, unsigned subpatternId, ByteDisjunction* parenthesesInfo, bool capture, int inputPos)
</del><ins>+    ByteTerm(Type type, unsigned subpatternId, ByteDisjunction* parenthesesInfo, bool capture, unsigned inputPos)
</ins><span class="cx">         : type(type)
</span><span class="cx">         , m_capture(capture)
</span><span class="cx">         , m_invert(false)
</span><span class="lines">@@ -185,7 +185,7 @@
</span><span class="cx">         atom.quantityCount = 1;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    ByteTerm(Type type, unsigned subpatternId, bool capture, bool invert, int inputPos)
</del><ins>+    ByteTerm(Type type, unsigned subpatternId, bool capture, bool invert, unsigned inputPos)
</ins><span class="cx">         : type(type)
</span><span class="cx">         , m_capture(capture)
</span><span class="cx">         , m_invert(invert)
</span><span class="lines">@@ -196,7 +196,7 @@
</span><span class="cx">         inputPosition = inputPos;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    static ByteTerm BOL(int inputPos)
</del><ins>+    static ByteTerm BOL(unsigned inputPos)
</ins><span class="cx">     {
</span><span class="cx">         ByteTerm term(TypeAssertionBOL);
</span><span class="cx">         term.inputPosition = inputPos;
</span><span class="lines">@@ -217,7 +217,7 @@
</span><span class="cx">         return term;
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    static ByteTerm EOL(int inputPos)
</del><ins>+    static ByteTerm EOL(unsigned inputPos)
</ins><span class="cx">     {
</span><span class="cx">         ByteTerm term(TypeAssertionEOL);
</span><span class="cx">         term.inputPosition = inputPos;
</span><span class="lines">@@ -224,7 +224,7 @@
</span><span class="cx">         return term;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    static ByteTerm WordBoundary(bool invert, int inputPos)
</del><ins>+    static ByteTerm WordBoundary(bool invert, unsigned inputPos)
</ins><span class="cx">     {
</span><span class="cx">         ByteTerm term(TypeAssertionWordBoundary, invert);
</span><span class="cx">         term.inputPosition = inputPos;
</span><span class="lines">@@ -231,7 +231,7 @@
</span><span class="cx">         return term;
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    static ByteTerm BackReference(unsigned subpatternId, int inputPos)
</del><ins>+    static ByteTerm BackReference(unsigned subpatternId, unsigned inputPos)
</ins><span class="cx">     {
</span><span class="cx">         return ByteTerm(TypeBackReference, subpatternId, false, false, inputPos);
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreyarrYarrJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/yarr/YarrJIT.cpp (203205 => 203206)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/yarr/YarrJIT.cpp        2016-07-14 00:52:00 UTC (rev 203205)
+++ trunk/Source/JavaScriptCore/yarr/YarrJIT.cpp        2016-07-14 01:20:11 UTC (rev 203206)
</span><span class="lines">@@ -285,10 +285,51 @@
</span><span class="cx">         return branch32(NotEqual, index, length);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    Jump jumpIfCharNotEquals(UChar32 ch, int inputPosition, RegisterID character)
</del><ins>+    BaseIndex negativeOffsetIndexedAddress(Checked&lt;unsigned&gt; negativeCharacterOffset, RegisterID tempReg, RegisterID indexReg = index)
</ins><span class="cx">     {
</span><del>-        readCharacter(inputPosition, character);
</del><ins>+        RegisterID base = input;
</ins><span class="cx"> 
</span><ins>+        // BaseIndex() addressing can take a int32_t offset. Given that we can have a regular
+        // expression that has unsigned character offsets, BaseIndex's signed offset is insufficient
+        // for addressing in extreme cases where we might underflow. Therefore we check to see if
+        // negativeCharacterOffset will underflow directly or after converting for 16 bit characters.
+        // If so, we do our own address calculating by adjusting the base, using the result register
+        // as a temp address register.
+        unsigned maximumNegativeOffsetForCharacterSize = m_charSize == Char8 ? 0x7fffffff : 0x3fffffff;
+        unsigned offsetAdjustAmount = 0x40000000;
+        if (negativeCharacterOffset.unsafeGet() &gt; maximumNegativeOffsetForCharacterSize) {
+            base = tempReg;
+            move(input, base);
+            while (negativeCharacterOffset.unsafeGet() &gt; maximumNegativeOffsetForCharacterSize) {
+                subPtr(TrustedImm32(offsetAdjustAmount), base);
+                if (m_charSize != Char8)
+                    subPtr(TrustedImm32(offsetAdjustAmount), base);
+                negativeCharacterOffset -= offsetAdjustAmount;
+            }
+        }
+
+        Checked&lt;int32_t&gt; characterOffset(-static_cast&lt;int32_t&gt;(negativeCharacterOffset.unsafeGet()));
+
+        if (m_charSize == Char8)
+            return BaseIndex(input, indexReg, TimesOne, (characterOffset * static_cast&lt;int32_t&gt;(sizeof(char))).unsafeGet());
+
+        return BaseIndex(input, indexReg, TimesTwo, (characterOffset * static_cast&lt;int32_t&gt;(sizeof(UChar))).unsafeGet());
+    }
+
+    void readCharacter(Checked&lt;unsigned&gt; negativeCharacterOffset, RegisterID resultReg, RegisterID indexReg = index)
+    {
+        BaseIndex address = negativeOffsetIndexedAddress(negativeCharacterOffset, resultReg, indexReg);
+
+        if (m_charSize == Char8)
+            load8(address, resultReg);
+        else
+            load16Unaligned(address, resultReg);
+    }
+
+    Jump jumpIfCharNotEquals(UChar32 ch, Checked&lt;unsigned&gt; negativeCharacterOffset, RegisterID character)
+    {
+        readCharacter(negativeCharacterOffset, character);
+
</ins><span class="cx">         // For case-insesitive compares, non-ascii characters that have different
</span><span class="cx">         // upper &amp; lower case representations are converted to a character class.
</span><span class="cx">         ASSERT(!m_pattern.ignoreCase() || isASCIIAlpha(ch) || isCanonicallyUnique(ch));
</span><span class="lines">@@ -299,15 +340,7 @@
</span><span class="cx"> 
</span><span class="cx">         return branch32(NotEqual, character, Imm32(ch));
</span><span class="cx">     }
</span><del>-
-    void readCharacter(int inputPosition, RegisterID reg)
-    {
-        if (m_charSize == Char8)
-            load8(BaseIndex(input, index, TimesOne, inputPosition * sizeof(char)), reg);
-        else
-            load16(BaseIndex(input, index, TimesTwo, inputPosition * sizeof(UChar)), reg);
-    }
-
</del><ins>+    
</ins><span class="cx">     void storeToFrame(RegisterID reg, unsigned frameLocation)
</span><span class="cx">     {
</span><span class="cx">         poke(reg, frameLocation);
</span><span class="lines">@@ -493,9 +526,9 @@
</span><span class="cx">         bool m_isDeadCode;
</span><span class="cx"> 
</span><span class="cx">         // Currently used in the case of some of the more complex management of
</span><del>-        // 'm_checked', to cache the offset used in this alternative, to avoid
</del><ins>+        // 'm_checkedOffset', to cache the offset used in this alternative, to avoid
</ins><span class="cx">         // recalculating it.
</span><del>-        int m_checkAdjust;
</del><ins>+        Checked&lt;unsigned&gt; m_checkAdjust;
</ins><span class="cx"> 
</span><span class="cx">         // Used by OpNestedAlternativeNext/End to hold the pointer to the
</span><span class="cx">         // value that will be pushed into the pattern's frame to return to,
</span><span class="lines">@@ -645,9 +678,9 @@
</span><span class="cx"> 
</span><span class="cx">             JumpList matchDest;
</span><span class="cx">             if (!term-&gt;inputPosition)
</span><del>-                matchDest.append(branch32(Equal, index, Imm32(m_checked)));
</del><ins>+                matchDest.append(branch32(Equal, index, Imm32(m_checkedOffset.unsafeGet())));
</ins><span class="cx"> 
</span><del>-            readCharacter((term-&gt;inputPosition - m_checked) - 1, character);
</del><ins>+            readCharacter(m_checkedOffset - term-&gt;inputPosition + 1, character);
</ins><span class="cx">             matchCharacterClass(character, matchDest, m_pattern.newlineCharacterClass());
</span><span class="cx">             op.m_jumps.append(jump());
</span><span class="cx"> 
</span><span class="lines">@@ -657,7 +690,7 @@
</span><span class="cx">             if (term-&gt;inputPosition)
</span><span class="cx">                 op.m_jumps.append(jump());
</span><span class="cx">             else
</span><del>-                op.m_jumps.append(branch32(NotEqual, index, Imm32(m_checked)));
</del><ins>+                op.m_jumps.append(branch32(NotEqual, index, Imm32(m_checkedOffset.unsafeGet())));
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx">     void backtrackAssertionBOL(size_t opIndex)
</span><span class="lines">@@ -674,16 +707,16 @@
</span><span class="cx">             const RegisterID character = regT0;
</span><span class="cx"> 
</span><span class="cx">             JumpList matchDest;
</span><del>-            if (term-&gt;inputPosition == m_checked)
</del><ins>+            if (term-&gt;inputPosition == m_checkedOffset.unsafeGet())
</ins><span class="cx">                 matchDest.append(atEndOfInput());
</span><span class="cx"> 
</span><del>-            readCharacter(term-&gt;inputPosition - m_checked, character);
</del><ins>+            readCharacter(m_checkedOffset - term-&gt;inputPosition, character);
</ins><span class="cx">             matchCharacterClass(character, matchDest, m_pattern.newlineCharacterClass());
</span><span class="cx">             op.m_jumps.append(jump());
</span><span class="cx"> 
</span><span class="cx">             matchDest.link(this);
</span><span class="cx">         } else {
</span><del>-            if (term-&gt;inputPosition == m_checked)
</del><ins>+            if (term-&gt;inputPosition == m_checkedOffset.unsafeGet())
</ins><span class="cx">                 op.m_jumps.append(notAtEndOfInput());
</span><span class="cx">             // Erk, really should poison out these alternatives early. :-/
</span><span class="cx">             else
</span><span class="lines">@@ -703,10 +736,10 @@
</span><span class="cx"> 
</span><span class="cx">         const RegisterID character = regT0;
</span><span class="cx"> 
</span><del>-        if (term-&gt;inputPosition == m_checked)
</del><ins>+        if (term-&gt;inputPosition == m_checkedOffset.unsafeGet())
</ins><span class="cx">             nextIsNotWordChar.append(atEndOfInput());
</span><span class="cx"> 
</span><del>-        readCharacter((term-&gt;inputPosition - m_checked), character);
</del><ins>+        readCharacter(m_checkedOffset - term-&gt;inputPosition, character);
</ins><span class="cx">         matchCharacterClass(character, nextIsWordChar, m_pattern.wordcharCharacterClass());
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -720,8 +753,8 @@
</span><span class="cx">         Jump atBegin;
</span><span class="cx">         JumpList matchDest;
</span><span class="cx">         if (!term-&gt;inputPosition)
</span><del>-            atBegin = branch32(Equal, index, Imm32(m_checked));
-        readCharacter((term-&gt;inputPosition - m_checked) - 1, character);
</del><ins>+            atBegin = branch32(Equal, index, Imm32(m_checkedOffset.unsafeGet()));
+        readCharacter(m_checkedOffset - term-&gt;inputPosition + 1, character);
</ins><span class="cx">         matchCharacterClass(character, matchDest, m_pattern.wordcharCharacterClass());
</span><span class="cx">         if (!term-&gt;inputPosition)
</span><span class="cx">             atBegin.link(this);
</span><span class="lines">@@ -782,7 +815,7 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         const RegisterID character = regT0;
</span><del>-        int maxCharactersAtOnce = m_charSize == Char8 ? 4 : 2;
</del><ins>+        unsigned maxCharactersAtOnce = m_charSize == Char8 ? 4 : 2;
</ins><span class="cx">         unsigned ignoreCaseMask = 0;
</span><span class="cx"> #if CPU(BIG_ENDIAN)
</span><span class="cx">         int allCharacters = ch &lt;&lt; (m_charSize == Char8 ? 24 : 16);
</span><span class="lines">@@ -789,8 +822,8 @@
</span><span class="cx"> #else
</span><span class="cx">         int allCharacters = ch;
</span><span class="cx"> #endif
</span><del>-        int numberCharacters;
-        int startTermPosition = term-&gt;inputPosition;
</del><ins>+        unsigned numberCharacters;
+        unsigned startTermPosition = term-&gt;inputPosition;
</ins><span class="cx"> 
</span><span class="cx">         // For case-insesitive compares, non-ascii characters that have different
</span><span class="cx">         // upper &amp; lower case representations are converted to a character class.
</span><span class="lines">@@ -841,25 +874,22 @@
</span><span class="cx">         if (m_charSize == Char8) {
</span><span class="cx">             switch (numberCharacters) {
</span><span class="cx">             case 1:
</span><del>-                op.m_jumps.append(jumpIfCharNotEquals(ch, startTermPosition - m_checked, character));
</del><ins>+                op.m_jumps.append(jumpIfCharNotEquals(ch, m_checkedOffset - startTermPosition, character));
</ins><span class="cx">                 return;
</span><span class="cx">             case 2: {
</span><del>-                BaseIndex address(input, index, TimesOne, (startTermPosition - m_checked) * sizeof(LChar));
-                load16Unaligned(address, character);
</del><ins>+                load16Unaligned(negativeOffsetIndexedAddress(m_checkedOffset - startTermPosition, character), character);
</ins><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx">             case 3: {
</span><del>-                BaseIndex highAddress(input, index, TimesOne, (startTermPosition - m_checked) * sizeof(LChar));
-                load16Unaligned(highAddress, character);
</del><ins>+                load16Unaligned(negativeOffsetIndexedAddress(m_checkedOffset - startTermPosition, character), character);
</ins><span class="cx">                 if (ignoreCaseMask)
</span><span class="cx">                     or32(Imm32(ignoreCaseMask), character);
</span><span class="cx">                 op.m_jumps.append(branch32(NotEqual, character, Imm32((allCharacters &amp; 0xffff) | ignoreCaseMask)));
</span><del>-                op.m_jumps.append(jumpIfCharNotEquals(allCharacters &gt;&gt; 16, startTermPosition + 2 - m_checked, character));
</del><ins>+                op.m_jumps.append(jumpIfCharNotEquals(allCharacters &gt;&gt; 16, m_checkedOffset - startTermPosition - 2, character));
</ins><span class="cx">                 return;
</span><span class="cx">             }
</span><span class="cx">             case 4: {
</span><del>-                BaseIndex address(input, index, TimesOne, (startTermPosition - m_checked) * sizeof(LChar));
-                load32WithUnalignedHalfWords(address, character);
</del><ins>+                load32WithUnalignedHalfWords(negativeOffsetIndexedAddress(m_checkedOffset- startTermPosition, character), character);
</ins><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx">             }
</span><span class="lines">@@ -866,11 +896,10 @@
</span><span class="cx">         } else {
</span><span class="cx">             switch (numberCharacters) {
</span><span class="cx">             case 1:
</span><del>-                op.m_jumps.append(jumpIfCharNotEquals(ch, term-&gt;inputPosition - m_checked, character));
</del><ins>+                op.m_jumps.append(jumpIfCharNotEquals(ch, m_checkedOffset - term-&gt;inputPosition, character));
</ins><span class="cx">                 return;
</span><span class="cx">             case 2:
</span><del>-                BaseIndex address(input, index, TimesTwo, (term-&gt;inputPosition - m_checked) * sizeof(UChar));
-                load32WithUnalignedHalfWords(address, character);
</del><ins>+                load32WithUnalignedHalfWords(negativeOffsetIndexedAddress(m_checkedOffset- term-&gt;inputPosition, character), character);
</ins><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx">         }
</span><span class="lines">@@ -898,13 +927,7 @@
</span><span class="cx">         sub32(Imm32(term-&gt;quantityCount.unsafeGet()), countRegister);
</span><span class="cx"> 
</span><span class="cx">         Label loop(this);
</span><del>-        BaseIndex address(input, countRegister, m_charScale, (Checked&lt;int&gt;(term-&gt;inputPosition - m_checked + Checked&lt;int64_t&gt;(term-&gt;quantityCount)) * static_cast&lt;int&gt;(m_charSize == Char8 ? sizeof(char) : sizeof(UChar))).unsafeGet());
-
-        if (m_charSize == Char8)
-            load8(address, character);
-        else
-            load16(address, character);
-
</del><ins>+        readCharacter(m_checkedOffset - term-&gt;inputPosition - term-&gt;quantityCount, character, countRegister);
</ins><span class="cx">         // For case-insesitive compares, non-ascii characters that have different
</span><span class="cx">         // upper &amp; lower case representations are converted to a character class.
</span><span class="cx">         ASSERT(!m_pattern.ignoreCase() || isASCIIAlpha(ch) || isCanonicallyUnique(ch));
</span><span class="lines">@@ -938,7 +961,7 @@
</span><span class="cx">             JumpList failures;
</span><span class="cx">             Label loop(this);
</span><span class="cx">             failures.append(atEndOfInput());
</span><del>-            failures.append(jumpIfCharNotEquals(ch, term-&gt;inputPosition - m_checked, character));
</del><ins>+            failures.append(jumpIfCharNotEquals(ch, m_checkedOffset - term-&gt;inputPosition, character));
</ins><span class="cx"> 
</span><span class="cx">             add32(TrustedImm32(1), countRegister);
</span><span class="cx">             add32(TrustedImm32(1), index);
</span><span class="lines">@@ -999,7 +1022,7 @@
</span><span class="cx">             nonGreedyFailures.append(atEndOfInput());
</span><span class="cx">             if (term-&gt;quantityCount != quantifyInfinite)
</span><span class="cx">                 nonGreedyFailures.append(branch32(Equal, countRegister, Imm32(term-&gt;quantityCount.unsafeGet())));
</span><del>-            nonGreedyFailures.append(jumpIfCharNotEquals(ch, term-&gt;inputPosition - m_checked, character));
</del><ins>+            nonGreedyFailures.append(jumpIfCharNotEquals(ch, m_checkedOffset - term-&gt;inputPosition, character));
</ins><span class="cx"> 
</span><span class="cx">             add32(TrustedImm32(1), countRegister);
</span><span class="cx">             add32(TrustedImm32(1), index);
</span><span class="lines">@@ -1020,7 +1043,7 @@
</span><span class="cx">         const RegisterID character = regT0;
</span><span class="cx"> 
</span><span class="cx">         JumpList matchDest;
</span><del>-        readCharacter(term-&gt;inputPosition - m_checked, character);
</del><ins>+        readCharacter(m_checkedOffset - term-&gt;inputPosition, character);
</ins><span class="cx">         matchCharacterClass(character, matchDest, term-&gt;characterClass);
</span><span class="cx"> 
</span><span class="cx">         if (term-&gt;invert())
</span><span class="lines">@@ -1048,10 +1071,7 @@
</span><span class="cx"> 
</span><span class="cx">         Label loop(this);
</span><span class="cx">         JumpList matchDest;
</span><del>-        if (m_charSize == Char8)
-            load8(BaseIndex(input, countRegister, TimesOne, (Checked&lt;int&gt;(term-&gt;inputPosition - m_checked + Checked&lt;int64_t&gt;(term-&gt;quantityCount)) * static_cast&lt;int&gt;(sizeof(char))).unsafeGet()), character);
-        else
-            load16(BaseIndex(input, countRegister, TimesTwo, (Checked&lt;int&gt;(term-&gt;inputPosition - m_checked + Checked&lt;int64_t&gt;(term-&gt;quantityCount)) * static_cast&lt;int&gt;(sizeof(UChar))).unsafeGet()), character);
</del><ins>+        readCharacter(m_checkedOffset - term-&gt;inputPosition - term-&gt;quantityCount, character, countRegister);
</ins><span class="cx">         matchCharacterClass(character, matchDest, term-&gt;characterClass);
</span><span class="cx"> 
</span><span class="cx">         if (term-&gt;invert())
</span><span class="lines">@@ -1084,11 +1104,11 @@
</span><span class="cx">         failures.append(atEndOfInput());
</span><span class="cx"> 
</span><span class="cx">         if (term-&gt;invert()) {
</span><del>-            readCharacter(term-&gt;inputPosition - m_checked, character);
</del><ins>+            readCharacter(m_checkedOffset - term-&gt;inputPosition, character);
</ins><span class="cx">             matchCharacterClass(character, failures, term-&gt;characterClass);
</span><span class="cx">         } else {
</span><span class="cx">             JumpList matchDest;
</span><del>-            readCharacter(term-&gt;inputPosition - m_checked, character);
</del><ins>+            readCharacter(m_checkedOffset - term-&gt;inputPosition, character);
</ins><span class="cx">             matchCharacterClass(character, matchDest, term-&gt;characterClass);
</span><span class="cx">             failures.append(jump());
</span><span class="cx">             matchDest.link(this);
</span><span class="lines">@@ -1152,7 +1172,7 @@
</span><span class="cx">         nonGreedyFailures.append(branch32(Equal, countRegister, Imm32(term-&gt;quantityCount.unsafeGet())));
</span><span class="cx"> 
</span><span class="cx">         JumpList matchDest;
</span><del>-        readCharacter(term-&gt;inputPosition - m_checked, character);
</del><ins>+        readCharacter(m_checkedOffset - term-&gt;inputPosition, character);
</ins><span class="cx">         matchCharacterClass(character, matchDest, term-&gt;characterClass);
</span><span class="cx"> 
</span><span class="cx">         if (term-&gt;invert())
</span><span class="lines">@@ -1417,7 +1437,7 @@
</span><span class="cx">                 // set as appropriate to this alternative.
</span><span class="cx">                 op.m_reentry = label();
</span><span class="cx"> 
</span><del>-                m_checked += alternative-&gt;m_minimumSize;
</del><ins>+                m_checkedOffset += alternative-&gt;m_minimumSize;
</ins><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx">             case OpBodyAlternativeNext:
</span><span class="lines">@@ -1470,8 +1490,8 @@
</span><span class="cx">                 }
</span><span class="cx"> 
</span><span class="cx">                 if (op.m_op == OpBodyAlternativeNext)
</span><del>-                    m_checked += alternative-&gt;m_minimumSize;
-                m_checked -= priorAlternative-&gt;m_minimumSize;
</del><ins>+                    m_checkedOffset += alternative-&gt;m_minimumSize;
+                m_checkedOffset -= priorAlternative-&gt;m_minimumSize;
</ins><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx"> 
</span><span class="lines">@@ -1498,13 +1518,13 @@
</span><span class="cx">                 PatternDisjunction* disjunction = term-&gt;parentheses.disjunction;
</span><span class="cx"> 
</span><span class="cx">                 // Calculate how much input we need to check for, and if non-zero check.
</span><del>-                op.m_checkAdjust = alternative-&gt;m_minimumSize;
</del><ins>+                op.m_checkAdjust = Checked&lt;unsigned&gt;(alternative-&gt;m_minimumSize);
</ins><span class="cx">                 if ((term-&gt;quantityType == QuantifierFixedCount) &amp;&amp; (term-&gt;type != PatternTerm::TypeParentheticalAssertion))
</span><span class="cx">                     op.m_checkAdjust -= disjunction-&gt;m_minimumSize;
</span><span class="cx">                 if (op.m_checkAdjust)
</span><del>-                    op.m_jumps.append(jumpIfNoAvailableInput(op.m_checkAdjust));
</del><ins>+                    op.m_jumps.append(jumpIfNoAvailableInput(op.m_checkAdjust.unsafeGet()));
</ins><span class="cx"> 
</span><del>-                m_checked += op.m_checkAdjust;
</del><ins>+                m_checkedOffset += op.m_checkAdjust;
</ins><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx">             case OpSimpleNestedAlternativeNext:
</span><span class="lines">@@ -1552,11 +1572,11 @@
</span><span class="cx">                 if ((term-&gt;quantityType == QuantifierFixedCount) &amp;&amp; (term-&gt;type != PatternTerm::TypeParentheticalAssertion))
</span><span class="cx">                     op.m_checkAdjust -= disjunction-&gt;m_minimumSize;
</span><span class="cx">                 if (op.m_checkAdjust)
</span><del>-                    op.m_jumps.append(jumpIfNoAvailableInput(op.m_checkAdjust));
</del><ins>+                    op.m_jumps.append(jumpIfNoAvailableInput(op.m_checkAdjust.unsafeGet()));
</ins><span class="cx"> 
</span><span class="cx">                 YarrOp&amp; lastOp = m_ops[op.m_previousOp];
</span><del>-                m_checked -= lastOp.m_checkAdjust;
-                m_checked += op.m_checkAdjust;
</del><ins>+                m_checkedOffset -= lastOp.m_checkAdjust;
+                m_checkedOffset += op.m_checkAdjust;
</ins><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx">             case OpSimpleNestedAlternativeEnd:
</span><span class="lines">@@ -1585,7 +1605,7 @@
</span><span class="cx">                 op.m_jumps.clear();
</span><span class="cx"> 
</span><span class="cx">                 YarrOp&amp; lastOp = m_ops[op.m_previousOp];
</span><del>-                m_checked -= lastOp.m_checkAdjust;
</del><ins>+                m_checkedOffset -= lastOp.m_checkAdjust;
</ins><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx"> 
</span><span class="lines">@@ -1629,11 +1649,12 @@
</span><span class="cx">                 // offsets only afterwards, at the point the results array is
</span><span class="cx">                 // being accessed.
</span><span class="cx">                 if (term-&gt;capture() &amp;&amp; compileMode == IncludeSubpatterns) {
</span><del>-                    int inputOffset = term-&gt;inputPosition - m_checked;
</del><ins>+                    unsigned inputOffset = (m_checkedOffset - term-&gt;inputPosition).unsafeGet();
</ins><span class="cx">                     if (term-&gt;quantityType == QuantifierFixedCount)
</span><del>-                        inputOffset -= term-&gt;parentheses.disjunction-&gt;m_minimumSize;
</del><ins>+                        inputOffset += term-&gt;parentheses.disjunction-&gt;m_minimumSize;
</ins><span class="cx">                     if (inputOffset) {
</span><del>-                        add32(Imm32(inputOffset), index, indexTemporary);
</del><ins>+                        move(index, indexTemporary);
+                        sub32(Imm32(inputOffset), indexTemporary);
</ins><span class="cx">                         setSubpatternStart(indexTemporary, term-&gt;parentheses.subpatternId);
</span><span class="cx">                     } else
</span><span class="cx">                         setSubpatternStart(index, term-&gt;parentheses.subpatternId);
</span><span class="lines">@@ -1661,9 +1682,10 @@
</span><span class="cx">                 // offsets only afterwards, at the point the results array is
</span><span class="cx">                 // being accessed.
</span><span class="cx">                 if (term-&gt;capture() &amp;&amp; compileMode == IncludeSubpatterns) {
</span><del>-                    int inputOffset = term-&gt;inputPosition - m_checked;
</del><ins>+                    unsigned inputOffset = (m_checkedOffset - term-&gt;inputPosition).unsafeGet();
</ins><span class="cx">                     if (inputOffset) {
</span><del>-                        add32(Imm32(inputOffset), index, indexTemporary);
</del><ins>+                        move(index, indexTemporary);
+                        sub32(Imm32(inputOffset), indexTemporary);
</ins><span class="cx">                         setSubpatternEnd(indexTemporary, term-&gt;parentheses.subpatternId);
</span><span class="cx">                     } else
</span><span class="cx">                         setSubpatternEnd(index, term-&gt;parentheses.subpatternId);
</span><span class="lines">@@ -1729,11 +1751,11 @@
</span><span class="cx">                 storeToFrame(index, parenthesesFrameLocation);
</span><span class="cx"> 
</span><span class="cx">                 // Check 
</span><del>-                op.m_checkAdjust = m_checked - term-&gt;inputPosition;
</del><ins>+                op.m_checkAdjust = m_checkedOffset - term-&gt;inputPosition;
</ins><span class="cx">                 if (op.m_checkAdjust)
</span><del>-                    sub32(Imm32(op.m_checkAdjust), index);
</del><ins>+                    sub32(Imm32(op.m_checkAdjust.unsafeGet()), index);
</ins><span class="cx"> 
</span><del>-                m_checked -= op.m_checkAdjust;
</del><ins>+                m_checkedOffset -= op.m_checkAdjust;
</ins><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx">             case OpParentheticalAssertionEnd: {
</span><span class="lines">@@ -1751,7 +1773,7 @@
</span><span class="cx">                 }
</span><span class="cx"> 
</span><span class="cx">                 YarrOp&amp; lastOp = m_ops[op.m_previousOp];
</span><del>-                m_checked += lastOp.m_checkAdjust;
</del><ins>+                m_checkedOffset += lastOp.m_checkAdjust;
</ins><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx"> 
</span><span class="lines">@@ -1809,9 +1831,9 @@
</span><span class="cx"> 
</span><span class="cx">                 if (op.m_op == OpBodyAlternativeNext) {
</span><span class="cx">                     PatternAlternative* priorAlternative = m_ops[op.m_previousOp].m_alternative;
</span><del>-                    m_checked += priorAlternative-&gt;m_minimumSize;
</del><ins>+                    m_checkedOffset += priorAlternative-&gt;m_minimumSize;
</ins><span class="cx">                 }
</span><del>-                m_checked -= alternative-&gt;m_minimumSize;
</del><ins>+                m_checkedOffset -= alternative-&gt;m_minimumSize;
</ins><span class="cx"> 
</span><span class="cx">                 // Is this the last alternative? If not, then if we backtrack to this point we just
</span><span class="cx">                 // need to jump to try to match the next alternative.
</span><span class="lines">@@ -2014,7 +2036,7 @@
</span><span class="cx">                 ASSERT(m_backtrackingState.isEmpty());
</span><span class="cx"> 
</span><span class="cx">                 PatternAlternative* priorAlternative = m_ops[op.m_previousOp].m_alternative;
</span><del>-                m_checked += priorAlternative-&gt;m_minimumSize;
</del><ins>+                m_checkedOffset += priorAlternative-&gt;m_minimumSize;
</ins><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx"> 
</span><span class="lines">@@ -2065,7 +2087,7 @@
</span><span class="cx">                 if (op.m_checkAdjust) {
</span><span class="cx">                     // Handle the cases where we need to link the backtracks here.
</span><span class="cx">                     m_backtrackingState.link(this);
</span><del>-                    sub32(Imm32(op.m_checkAdjust), index);
</del><ins>+                    sub32(Imm32(op.m_checkAdjust.unsafeGet()), index);
</ins><span class="cx">                     if (!isLastAlternative) {
</span><span class="cx">                         // An alternative that is not the last should jump to its successor.
</span><span class="cx">                         jump(nextOp.m_reentry);
</span><span class="lines">@@ -2115,9 +2137,9 @@
</span><span class="cx"> 
</span><span class="cx">                 if (!isBegin) {
</span><span class="cx">                     YarrOp&amp; lastOp = m_ops[op.m_previousOp];
</span><del>-                    m_checked += lastOp.m_checkAdjust;
</del><ins>+                    m_checkedOffset += lastOp.m_checkAdjust;
</ins><span class="cx">                 }
</span><del>-                m_checked -= op.m_checkAdjust;
</del><ins>+                m_checkedOffset -= op.m_checkAdjust;
</ins><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx">             case OpSimpleNestedAlternativeEnd:
</span><span class="lines">@@ -2148,7 +2170,7 @@
</span><span class="cx">                 }
</span><span class="cx"> 
</span><span class="cx">                 YarrOp&amp; lastOp = m_ops[op.m_previousOp];
</span><del>-                m_checked += lastOp.m_checkAdjust;
</del><ins>+                m_checkedOffset += lastOp.m_checkAdjust;
</ins><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx"> 
</span><span class="lines">@@ -2261,7 +2283,7 @@
</span><span class="cx">                      m_backtrackingState.link(this);
</span><span class="cx"> 
</span><span class="cx">                     if (op.m_checkAdjust)
</span><del>-                        add32(Imm32(op.m_checkAdjust), index);
</del><ins>+                        add32(Imm32(op.m_checkAdjust.unsafeGet()), index);
</ins><span class="cx"> 
</span><span class="cx">                     // In an inverted assertion failure to match the subpattern
</span><span class="cx">                     // is treated as a successful match - jump to the end of the
</span><span class="lines">@@ -2278,7 +2300,7 @@
</span><span class="cx">                 // added the failure caused by a successful match to this.
</span><span class="cx">                 m_backtrackingState.append(endOp.m_jumps);
</span><span class="cx"> 
</span><del>-                m_checked += op.m_checkAdjust;
</del><ins>+                m_checkedOffset += op.m_checkAdjust;
</ins><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx">             case OpParentheticalAssertionEnd: {
</span><span class="lines">@@ -2290,7 +2312,7 @@
</span><span class="cx">                 m_backtrackingState.takeBacktracksToJumpList(op.m_jumps, this);
</span><span class="cx"> 
</span><span class="cx">                 YarrOp&amp; lastOp = m_ops[op.m_previousOp];
</span><del>-                m_checked -= lastOp.m_checkAdjust;
</del><ins>+                m_checkedOffset -= lastOp.m_checkAdjust;
</ins><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx"> 
</span><span class="lines">@@ -2634,9 +2656,7 @@
</span><span class="cx">         : m_vm(vm)
</span><span class="cx">         , m_pattern(pattern)
</span><span class="cx">         , m_charSize(charSize)
</span><del>-        , m_charScale(m_charSize == Char8 ? TimesOne: TimesTwo)
</del><span class="cx">         , m_shouldFallBack(false)
</span><del>-        , m_checked(0)
</del><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -2697,8 +2717,6 @@
</span><span class="cx"> 
</span><span class="cx">     YarrCharSize m_charSize;
</span><span class="cx"> 
</span><del>-    Scale m_charScale;
-
</del><span class="cx">     // Used to detect regular expression constructs that are not currently
</span><span class="cx">     // supported in the JIT; fall back to the interpreter when this is detected.
</span><span class="cx">     bool m_shouldFallBack;
</span><span class="lines">@@ -2716,7 +2734,7 @@
</span><span class="cx">     // FIXME: This should go away. Rather than tracking this value throughout
</span><span class="cx">     // code generation, we should gather this information up front &amp; store it
</span><span class="cx">     // on the YarrOp structure.
</span><del>-    int m_checked;
</del><ins>+    Checked&lt;unsigned&gt; m_checkedOffset;
</ins><span class="cx"> 
</span><span class="cx">     // This class records state whilst generating the backtracking path of code.
</span><span class="cx">     BacktrackingState m_backtrackingState;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreyarrYarrPatternh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/yarr/YarrPattern.h (203205 => 203206)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/yarr/YarrPattern.h        2016-07-14 00:52:00 UTC (rev 203205)
+++ trunk/Source/JavaScriptCore/yarr/YarrPattern.h        2016-07-14 01:20:11 UTC (rev 203206)
</span><span class="lines">@@ -111,7 +111,7 @@
</span><span class="cx">     };
</span><span class="cx">     QuantifierType quantityType;
</span><span class="cx">     Checked&lt;unsigned&gt; quantityCount;
</span><del>-    int inputPosition;
</del><ins>+    unsigned inputPosition;
</ins><span class="cx">     unsigned frameLocation;
</span><span class="cx"> 
</span><span class="cx">     PatternTerm(UChar32 ch)
</span></span></pre>
</div>
</div>

</body>
</html>