<!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>[197040] trunk/Source/WebCore</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/197040">197040</a></dd>
<dt>Author</dt> <dd>rniwa@webkit.org</dd>
<dt>Date</dt> <dd>2016-02-24 12:26:01 -0800 (Wed, 24 Feb 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>A function named canTakeNextToken executing blocking scripts is misleading
https://bugs.webkit.org/show_bug.cgi?id=154636

Reviewed by Darin Adler.

Merged canTakeNextToken into pumpTokenizer and extracted pumpTokenizerLoop out of pumpTokenizer.

Inlined m_parserChunkSize in HTMLParserScheduler into checkForYieldBeforeToken, and removed needsYield
from PumpSession in favor of making checkForYieldBeforeToken and checkForYieldBeforeScript return a bool.

No new tests since this is a pure refactoring.

* html/parser/HTMLDocumentParser.cpp:
(WebCore::HTMLDocumentParser::canTakeNextToken): Deleted.
(WebCore::HTMLDocumentParser::pumpTokenizerLoop): Extracted from pumpTokenizer. We don't have to check
isStopped() at the beginning since pumpTokenizer asserts that. Return true when session.needsYield would
have been set to true in the old code and return false elsewhere (for stopping or incomplete token).
(WebCore::HTMLDocumentParser::pumpTokenizer):
* html/parser/HTMLDocumentParser.h:
* html/parser/HTMLParserScheduler.cpp:
(WebCore::PumpSession::PumpSession):
(WebCore::HTMLParserScheduler::HTMLParserScheduler):
(WebCore::HTMLParserScheduler::shouldYieldBeforeExecutingScript): Renamed from checkForYieldBeforeScript.
* html/parser/HTMLParserScheduler.h:
(WebCore::HTMLParserScheduler::shouldYieldBeforeToken): Renamed from checkForYieldBeforeToken.
(WebCore::HTMLParserScheduler::isScheduledForResume):
(WebCore::HTMLParserScheduler::checkForYield): Extracted from checkForYieldBeforeToken. Reset
processedTokens to 1 instead of setting it to 0 here and incrementing it later as done in the old code.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorehtmlparserHTMLDocumentParsercpp">trunk/Source/WebCore/html/parser/HTMLDocumentParser.cpp</a></li>
<li><a href="#trunkSourceWebCorehtmlparserHTMLDocumentParserh">trunk/Source/WebCore/html/parser/HTMLDocumentParser.h</a></li>
<li><a href="#trunkSourceWebCorehtmlparserHTMLParserSchedulercpp">trunk/Source/WebCore/html/parser/HTMLParserScheduler.cpp</a></li>
<li><a href="#trunkSourceWebCorehtmlparserHTMLParserSchedulerh">trunk/Source/WebCore/html/parser/HTMLParserScheduler.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (197039 => 197040)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-02-24 20:19:47 UTC (rev 197039)
+++ trunk/Source/WebCore/ChangeLog        2016-02-24 20:26:01 UTC (rev 197040)
</span><span class="lines">@@ -1,3 +1,34 @@
</span><ins>+2016-02-24  Ryosuke Niwa  &lt;rniwa@webkit.org&gt;
+
+        A function named canTakeNextToken executing blocking scripts is misleading
+        https://bugs.webkit.org/show_bug.cgi?id=154636
+
+        Reviewed by Darin Adler.
+
+        Merged canTakeNextToken into pumpTokenizer and extracted pumpTokenizerLoop out of pumpTokenizer.
+
+        Inlined m_parserChunkSize in HTMLParserScheduler into checkForYieldBeforeToken, and removed needsYield
+        from PumpSession in favor of making checkForYieldBeforeToken and checkForYieldBeforeScript return a bool.
+
+        No new tests since this is a pure refactoring.
+
+        * html/parser/HTMLDocumentParser.cpp:
+        (WebCore::HTMLDocumentParser::canTakeNextToken): Deleted.
+        (WebCore::HTMLDocumentParser::pumpTokenizerLoop): Extracted from pumpTokenizer. We don't have to check
+        isStopped() at the beginning since pumpTokenizer asserts that. Return true when session.needsYield would
+        have been set to true in the old code and return false elsewhere (for stopping or incomplete token).
+        (WebCore::HTMLDocumentParser::pumpTokenizer):
+        * html/parser/HTMLDocumentParser.h:
+        * html/parser/HTMLParserScheduler.cpp:
+        (WebCore::PumpSession::PumpSession):
+        (WebCore::HTMLParserScheduler::HTMLParserScheduler):
+        (WebCore::HTMLParserScheduler::shouldYieldBeforeExecutingScript): Renamed from checkForYieldBeforeScript.
+        * html/parser/HTMLParserScheduler.h:
+        (WebCore::HTMLParserScheduler::shouldYieldBeforeToken): Renamed from checkForYieldBeforeToken.
+        (WebCore::HTMLParserScheduler::isScheduledForResume):
+        (WebCore::HTMLParserScheduler::checkForYield): Extracted from checkForYieldBeforeToken. Reset
+        processedTokens to 1 instead of setting it to 0 here and incrementing it later as done in the old code.
+
</ins><span class="cx"> 2016-02-24  Daniel Bates  &lt;dabates@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         CSP: Enable plugin-types directive by default
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlparserHTMLDocumentParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/parser/HTMLDocumentParser.cpp (197039 => 197040)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/parser/HTMLDocumentParser.cpp        2016-02-24 20:19:47 UTC (rev 197039)
+++ trunk/Source/WebCore/html/parser/HTMLDocumentParser.cpp        2016-02-24 20:26:01 UTC (rev 197040)
</span><span class="lines">@@ -196,38 +196,6 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool HTMLDocumentParser::canTakeNextToken(SynchronousMode mode, PumpSession&amp; session)
-{
-    if (isStopped())
-        return false;
-
-    if (isWaitingForScripts()) {
-        if (mode == AllowYield)
-            m_parserScheduler-&gt;checkForYieldBeforeScript(session);
-
-        // If we don't run the script, we cannot allow the next token to be taken.
-        if (session.needsYield)
-            return false;
-
-        // If we're paused waiting for a script, we try to execute scripts before continuing.
-        runScriptsForPausedTreeBuilder();
-        if (isWaitingForScripts() || isStopped())
-            return false;
-    }
-
-    // FIXME: It's wrong for the HTMLDocumentParser to reach back to the Frame, but this approach is
-    // how the parser has always handled stopping when the page assigns window.location. What should
-    // happen instead  is that assigning window.location causes the parser to stop parsing cleanly.
-    // The problem is we're not prepared to do that at every point where we run JavaScript.
-    if (!isParsingFragment() &amp;&amp; document()-&gt;frame() &amp;&amp; document()-&gt;frame()-&gt;navigationScheduler().locationChangePending())
-        return false;
-
-    if (mode == AllowYield)
-        m_parserScheduler-&gt;checkForYieldBeforeToken(session);
-
-    return true;
-}
-
</del><span class="cx"> Document* HTMLDocumentParser::contextForParsingSession()
</span><span class="cx"> {
</span><span class="cx">     // The parsing session should interact with the document only when parsing
</span><span class="lines">@@ -237,27 +205,36 @@
</span><span class="cx">     return document();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void HTMLDocumentParser::pumpTokenizer(SynchronousMode mode)
</del><ins>+bool HTMLDocumentParser::pumpTokenizerLoop(SynchronousMode mode, bool parsingFragment, PumpSession&amp; session)
</ins><span class="cx"> {
</span><del>-    ASSERT(!isStopped());
-    ASSERT(!isScheduledForResume());
</del><ins>+    do {
+        if (UNLIKELY(isWaitingForScripts())) {
+            if (mode == AllowYield &amp;&amp; m_parserScheduler-&gt;shouldYieldBeforeExecutingScript(session))
+                return true;
+            runScriptsForPausedTreeBuilder();
+            // If we're paused waiting for a script, we try to execute scripts before continuing.
+            if (isWaitingForScripts() || isStopped())
+                return false;
+        }
</ins><span class="cx"> 
</span><del>-    // This is an attempt to check that this object is both attached to the Document and protected by something.
-    ASSERT(refCount() &gt;= 2);
</del><ins>+        // FIXME: It's wrong for the HTMLDocumentParser to reach back to the Frame, but this approach is
+        // how the parser has always handled stopping when the page assigns window.location. What should
+        // happen instead is that assigning window.location causes the parser to stop parsing cleanly.
+        // The problem is we're not prepared to do that at every point where we run JavaScript.
+        if (UNLIKELY(!parsingFragment &amp;&amp; document()-&gt;frame() &amp;&amp; document()-&gt;frame()-&gt;navigationScheduler().locationChangePending()))
+            return false;
</ins><span class="cx"> 
</span><del>-    PumpSession session(m_pumpSessionNestingLevel, contextForParsingSession());
</del><ins>+        if (UNLIKELY(mode == AllowYield &amp;&amp; m_parserScheduler-&gt;shouldYieldBeforeToken(session)))
+            return true;
</ins><span class="cx"> 
</span><del>-    m_xssAuditor.init(document(), &amp;m_xssAuditorDelegate);
-
-    while (canTakeNextToken(mode, session) &amp;&amp; !session.needsYield) {
-        if (!isParsingFragment())
</del><ins>+        if (!parsingFragment)
</ins><span class="cx">             m_sourceTracker.startToken(m_input.current(), m_tokenizer);
</span><span class="cx"> 
</span><span class="cx">         auto token = m_tokenizer.nextToken(m_input.current());
</span><span class="cx">         if (!token)
</span><del>-            break;
</del><ins>+            return false;
</ins><span class="cx"> 
</span><del>-        if (!isParsingFragment()) {
</del><ins>+        if (!parsingFragment) {
</ins><span class="cx">             m_sourceTracker.endToken(m_input.current(), m_tokenizer);
</span><span class="cx"> 
</span><span class="cx">             // We do not XSS filter innerHTML, which means we (intentionally) fail
</span><span class="lines">@@ -267,8 +244,25 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         constructTreeFromHTMLToken(token);
</span><del>-    }
</del><ins>+    } while (!isStopped());
</ins><span class="cx"> 
</span><ins>+    return false;
+}
+
+void HTMLDocumentParser::pumpTokenizer(SynchronousMode mode)
+{
+    ASSERT(!isStopped());
+    ASSERT(!isScheduledForResume());
+
+    // This is an attempt to check that this object is both attached to the Document and protected by something.
+    ASSERT(refCount() &gt;= 2);
+
+    PumpSession session(m_pumpSessionNestingLevel, contextForParsingSession());
+
+    m_xssAuditor.init(document(), &amp;m_xssAuditorDelegate);
+
+    bool shouldResume = pumpTokenizerLoop(mode, isParsingFragment(), session);
+
</ins><span class="cx">     // Ensure we haven't been totally deref'ed after pumping. Any caller of this
</span><span class="cx">     // function should be holding a RefPtr to this to ensure we weren't deleted.
</span><span class="cx">     ASSERT(refCount() &gt;= 1);
</span><span class="lines">@@ -276,7 +270,7 @@
</span><span class="cx">     if (isStopped())
</span><span class="cx">         return;
</span><span class="cx"> 
</span><del>-    if (session.needsYield)
</del><ins>+    if (shouldResume)
</ins><span class="cx">         m_parserScheduler-&gt;scheduleForResume();
</span><span class="cx"> 
</span><span class="cx">     if (isWaitingForScripts()) {
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlparserHTMLDocumentParserh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/parser/HTMLDocumentParser.h (197039 => 197040)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/parser/HTMLDocumentParser.h        2016-02-24 20:19:47 UTC (rev 197039)
+++ trunk/Source/WebCore/html/parser/HTMLDocumentParser.h        2016-02-24 20:26:01 UTC (rev 197040)
</span><span class="lines">@@ -102,8 +102,8 @@
</span><span class="cx">     Document* contextForParsingSession();
</span><span class="cx"> 
</span><span class="cx">     enum SynchronousMode { AllowYield, ForceSynchronous };
</span><del>-    bool canTakeNextToken(SynchronousMode, PumpSession&amp;);
</del><span class="cx">     void pumpTokenizer(SynchronousMode);
</span><ins>+    bool pumpTokenizerLoop(SynchronousMode, bool parsingFragment, PumpSession&amp;);
</ins><span class="cx">     void pumpTokenizerIfPossible(SynchronousMode);
</span><span class="cx">     void constructTreeFromHTMLToken(HTMLTokenizer::TokenPtr&amp;);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlparserHTMLParserSchedulercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/parser/HTMLParserScheduler.cpp (197039 => 197040)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/parser/HTMLParserScheduler.cpp        2016-02-24 20:19:47 UTC (rev 197039)
+++ trunk/Source/WebCore/html/parser/HTMLParserScheduler.cpp        2016-02-24 20:26:01 UTC (rev 197040)
</span><span class="lines">@@ -32,11 +32,6 @@
</span><span class="cx"> #include &quot;HTMLDocumentParser.h&quot;
</span><span class="cx"> #include &quot;Page.h&quot;
</span><span class="cx"> 
</span><del>-// defaultParserChunkSize is used to define how many tokens the parser will
-// process before checking against parserTimeLimit and possibly yielding.
-// This is a performance optimization to prevent checking after every token.
-static const int defaultParserChunkSize = 4096;
-
</del><span class="cx"> // defaultParserTimeLimit is the seconds the parser will run in one write() call
</span><span class="cx"> // before yielding. Inline &lt;script&gt; execution can cause it to exceed the limit.
</span><span class="cx"> // FIXME: We would like this value to be 0.2.
</span><span class="lines">@@ -75,7 +70,6 @@
</span><span class="cx">     // At that time we'll initialize startTime.
</span><span class="cx">     , processedTokens(INT_MAX)
</span><span class="cx">     , startTime(0)
</span><del>-    , needsYield(false)
</del><span class="cx">     , didSeeScript(false)
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="lines">@@ -87,7 +81,6 @@
</span><span class="cx"> HTMLParserScheduler::HTMLParserScheduler(HTMLDocumentParser&amp; parser)
</span><span class="cx">     : m_parser(parser)
</span><span class="cx">     , m_parserTimeLimit(parserTimeLimit(m_parser.document()-&gt;page()))
</span><del>-    , m_parserChunkSize(defaultParserChunkSize)
</del><span class="cx">     , m_continueNextChunkTimer(*this, &amp;HTMLParserScheduler::continueNextChunkTimerFired)
</span><span class="cx">     , m_isSuspendedWithActiveTimer(false)
</span><span class="cx"> #if !ASSERT_DISABLED
</span><span class="lines">@@ -114,15 +107,14 @@
</span><span class="cx">     m_parser.resumeParsingAfterYield();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void HTMLParserScheduler::checkForYieldBeforeScript(PumpSession&amp; session)
</del><ins>+bool HTMLParserScheduler::shouldYieldBeforeExecutingScript(PumpSession&amp; session)
</ins><span class="cx"> {
</span><span class="cx">     // If we've never painted before and a layout is pending, yield prior to running
</span><span class="cx">     // scripts to give the page a chance to paint earlier.
</span><span class="cx">     Document* document = m_parser.document();
</span><span class="cx">     bool needsFirstPaint = document-&gt;view() &amp;&amp; !document-&gt;view()-&gt;hasEverPainted();
</span><del>-    if (needsFirstPaint &amp;&amp; document-&gt;isLayoutTimerActive())
-        session.needsYield = true;
</del><span class="cx">     session.didSeeScript = true;
</span><ins>+    return needsFirstPaint &amp;&amp; document-&gt;isLayoutTimerActive();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void HTMLParserScheduler::scheduleForResume()
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlparserHTMLParserSchedulerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/parser/HTMLParserScheduler.h (197039 => 197040)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/parser/HTMLParserScheduler.h        2016-02-24 20:19:47 UTC (rev 197039)
+++ trunk/Source/WebCore/html/parser/HTMLParserScheduler.h        2016-02-24 20:26:01 UTC (rev 197040)
</span><span class="lines">@@ -54,9 +54,8 @@
</span><span class="cx">     PumpSession(unsigned&amp; nestingLevel, Document*);
</span><span class="cx">     ~PumpSession();
</span><span class="cx"> 
</span><del>-    int processedTokens;
</del><ins>+    unsigned processedTokens;
</ins><span class="cx">     double startTime;
</span><del>-    bool needsYield;
</del><span class="cx">     bool didSeeScript;
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="lines">@@ -66,29 +65,19 @@
</span><span class="cx">     explicit HTMLParserScheduler(HTMLDocumentParser&amp;);
</span><span class="cx">     ~HTMLParserScheduler();
</span><span class="cx"> 
</span><del>-    // Inline as this is called after every token in the parser.
-    void checkForYieldBeforeToken(PumpSession&amp; session)
</del><ins>+    bool shouldYieldBeforeToken(PumpSession&amp; session)
</ins><span class="cx">     {
</span><span class="cx"> #if PLATFORM(IOS)
</span><span class="cx">         if (WebThreadShouldYield())
</span><del>-            session.needsYield = true;
</del><ins>+            return true;
</ins><span class="cx"> #endif
</span><del>-        if (session.processedTokens &gt; m_parserChunkSize || session.didSeeScript) {
-            // monotonicallyIncreasingTime() can be expensive. By delaying, we avoided calling
-            // monotonicallyIncreasingTime() when constructing non-yielding PumpSessions.
-            if (!session.startTime)
-                session.startTime = monotonicallyIncreasingTime();
</del><ins>+        if (UNLIKELY(session.processedTokens &gt; numberOfTokensBeforeCheckingForYield || session.didSeeScript))
+            return checkForYield(session);
</ins><span class="cx"> 
</span><del>-            session.processedTokens = 0;
-            session.didSeeScript = false;
-
-            double elapsedTime = monotonicallyIncreasingTime() - session.startTime;
-            if (elapsedTime &gt; m_parserTimeLimit)
-                session.needsYield = true;
-        }
</del><span class="cx">         ++session.processedTokens;
</span><ins>+        return false;
</ins><span class="cx">     }
</span><del>-    void checkForYieldBeforeScript(PumpSession&amp;);
</del><ins>+    bool shouldYieldBeforeExecutingScript(PumpSession&amp;);
</ins><span class="cx"> 
</span><span class="cx">     void scheduleForResume();
</span><span class="cx">     bool isScheduledForResume() const { return m_isSuspendedWithActiveTimer || m_continueNextChunkTimer.isActive(); }
</span><span class="lines">@@ -97,12 +86,29 @@
</span><span class="cx">     void resume();
</span><span class="cx"> 
</span><span class="cx"> private:
</span><ins>+    static const unsigned numberOfTokensBeforeCheckingForYield = 4096; // Performance optimization
+
</ins><span class="cx">     void continueNextChunkTimerFired();
</span><span class="cx"> 
</span><ins>+    bool checkForYield(PumpSession&amp; session)
+    {
+        session.processedTokens = 1;
+        session.didSeeScript = false;
+
+        // monotonicallyIncreasingTime() can be expensive. By delaying, we avoided calling
+        // monotonicallyIncreasingTime() when constructing non-yielding PumpSessions.
+        if (!session.startTime) {
+            session.startTime = monotonicallyIncreasingTime();
+            return false;
+        }
+
+        double elapsedTime = monotonicallyIncreasingTime() - session.startTime;
+        return elapsedTime &gt; m_parserTimeLimit;
+    }
+
</ins><span class="cx">     HTMLDocumentParser&amp; m_parser;
</span><span class="cx"> 
</span><span class="cx">     double m_parserTimeLimit;
</span><del>-    int m_parserChunkSize;
</del><span class="cx">     Timer m_continueNextChunkTimer;
</span><span class="cx">     bool m_isSuspendedWithActiveTimer;
</span><span class="cx"> #if !ASSERT_DISABLED
</span></span></pre>
</div>
</div>

</body>
</html>