<!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>[202188] trunk/Source</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/202188">202188</a></dd>
<dt>Author</dt> <dd>cdumez@apple.com</dd>
<dt>Date</dt> <dd>2016-06-17 17:25:44 -0700 (Fri, 17 Jun 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Optimize parseCacheHeader() by using StringView
https://bugs.webkit.org/show_bug.cgi?id=158891

Reviewed by Darin Adler.

Source/WebCore:

Optimize parseCacheHeader() and avoid some temporary String allocations
by using StringView. We now strip the whitespaces in the input string
at the beginning of the function, at the same as as we strip the
control characters. We are then able to leverage StringView in the
rest of the function to get substrings without the need for extra
String allocations.

* platform/network/CacheValidation.cpp:
(WebCore::isControlCharacterOrSpace):
(WebCore::trimToNextSeparator):
(WebCore::parseCacheHeader):

Source/WTF:

Add a StringView::find() overload which takes a CharacterMatchFunction
to match the one on String.

* wtf/text/StringView.h:
(WTF::StringView::find):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWTFChangeLog">trunk/Source/WTF/ChangeLog</a></li>
<li><a href="#trunkSourceWTFwtftextStringViewh">trunk/Source/WTF/wtf/text/StringView.h</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreplatformnetworkCacheValidationcpp">trunk/Source/WebCore/platform/network/CacheValidation.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWTFChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/ChangeLog (202187 => 202188)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/ChangeLog        2016-06-18 00:09:12 UTC (rev 202187)
+++ trunk/Source/WTF/ChangeLog        2016-06-18 00:25:44 UTC (rev 202188)
</span><span class="lines">@@ -1,3 +1,16 @@
</span><ins>+2016-06-17  Chris Dumez  &lt;cdumez@apple.com&gt;
+
+        Optimize parseCacheHeader() by using StringView
+        https://bugs.webkit.org/show_bug.cgi?id=158891
+
+        Reviewed by Darin Adler.
+
+        Add a StringView::find() overload which takes a CharacterMatchFunction
+        to match the one on String.
+
+        * wtf/text/StringView.h:
+        (WTF::StringView::find):
+
</ins><span class="cx"> 2016-06-17  Mark Lam  &lt;mark.lam@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         OOM Assertion failure in JSON.stringify.
</span></span></pre></div>
<a id="trunkSourceWTFwtftextStringViewh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/text/StringView.h (202187 => 202188)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/text/StringView.h        2016-06-18 00:09:12 UTC (rev 202187)
+++ trunk/Source/WTF/wtf/text/StringView.h        2016-06-18 00:25:44 UTC (rev 202188)
</span><span class="lines">@@ -45,6 +45,8 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WTF {
</span><span class="cx"> 
</span><ins>+using CharacterMatchFunction = bool (*)(UChar);
+
</ins><span class="cx"> // StringView is a non-owning reference to a string, similar to the proposed std::string_view.
</span><span class="cx"> // Whether the string is 8-bit or 16-bit is encoded in the upper bit of the length member.
</span><span class="cx"> // This means that strings longer than 2 gigacharacters cannot be represented.
</span><span class="lines">@@ -110,6 +112,7 @@
</span><span class="cx">     StringView substring(unsigned start, unsigned length = std::numeric_limits&lt;unsigned&gt;::max()) const;
</span><span class="cx"> 
</span><span class="cx">     size_t find(UChar, unsigned start = 0) const;
</span><ins>+    size_t find(CharacterMatchFunction, unsigned start = 0) const;
</ins><span class="cx"> 
</span><span class="cx">     WTF_EXPORT_STRING_API size_t find(StringView, unsigned start) const;
</span><span class="cx"> 
</span><span class="lines">@@ -500,6 +503,13 @@
</span><span class="cx">     return WTF::find(characters16(), length(), character, start);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+inline size_t StringView::find(CharacterMatchFunction matchFunction, unsigned start) const
+{
+    if (is8Bit())
+        return WTF::find(characters8(), m_length, matchFunction, start);
+    return WTF::find(characters16(), length(), matchFunction, start);
+}
+
</ins><span class="cx"> #if !CHECK_STRINGVIEW_LIFETIME
</span><span class="cx"> inline void StringView::invalidate(const StringImpl&amp;)
</span><span class="cx"> {
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (202187 => 202188)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-06-18 00:09:12 UTC (rev 202187)
+++ trunk/Source/WebCore/ChangeLog        2016-06-18 00:25:44 UTC (rev 202188)
</span><span class="lines">@@ -1,3 +1,22 @@
</span><ins>+2016-06-17  Chris Dumez  &lt;cdumez@apple.com&gt;
+
+        Optimize parseCacheHeader() by using StringView
+        https://bugs.webkit.org/show_bug.cgi?id=158891
+
+        Reviewed by Darin Adler.
+
+        Optimize parseCacheHeader() and avoid some temporary String allocations
+        by using StringView. We now strip the whitespaces in the input string
+        at the beginning of the function, at the same as as we strip the
+        control characters. We are then able to leverage StringView in the
+        rest of the function to get substrings without the need for extra
+        String allocations.
+
+        * platform/network/CacheValidation.cpp:
+        (WebCore::isControlCharacterOrSpace):
+        (WebCore::trimToNextSeparator):
+        (WebCore::parseCacheHeader):
+
</ins><span class="cx"> 2016-06-17  Brent Fulgham  &lt;bfulgham@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Unreviewed clean-up after r202186.
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformnetworkCacheValidationcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/network/CacheValidation.cpp (202187 => 202188)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/network/CacheValidation.cpp        2016-06-18 00:09:12 UTC (rev 202187)
+++ trunk/Source/WebCore/platform/network/CacheValidation.cpp        2016-06-18 00:25:44 UTC (rev 202188)
</span><span class="lines">@@ -34,6 +34,7 @@
</span><span class="cx"> #include &quot;ResourceRequest.h&quot;
</span><span class="cx"> #include &quot;ResourceResponse.h&quot;
</span><span class="cx"> #include &lt;wtf/CurrentTime.h&gt;
</span><ins>+#include &lt;wtf/text/StringView.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><span class="lines">@@ -202,21 +203,22 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline bool isControlCharacter(UChar c)
</del><ins>+inline bool isControlCharacterOrSpace(UChar character)
</ins><span class="cx"> {
</span><del>-    return c &lt; ' ' || c == 127;
</del><ins>+    return character &lt;= ' ' || character == 127;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline String trimToNextSeparator(const String&amp; str)
</del><ins>+inline StringView trimToNextSeparator(StringView string)
</ins><span class="cx"> {
</span><del>-    return str.substring(0, str.find(isCacheHeaderSeparator));
</del><ins>+    return string.substring(0, string.find(isCacheHeaderSeparator));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static Vector&lt;std::pair&lt;String, String&gt;&gt; parseCacheHeader(const String&amp; header)
</span><span class="cx"> {
</span><span class="cx">     Vector&lt;std::pair&lt;String, String&gt;&gt; result;
</span><span class="cx"> 
</span><del>-    const String safeHeader = header.removeCharacters(isControlCharacter);
</del><ins>+    String safeHeaderString = header.removeCharacters(isControlCharacterOrSpace);
+    StringView safeHeader = safeHeaderString;
</ins><span class="cx">     unsigned max = safeHeader.length();
</span><span class="cx">     unsigned pos = 0;
</span><span class="cx">     while (pos &lt; max) {
</span><span class="lines">@@ -224,30 +226,30 @@
</span><span class="cx">         size_t nextEqualSignPosition = safeHeader.find('=', pos);
</span><span class="cx">         if (nextEqualSignPosition == notFound &amp;&amp; nextCommaPosition == notFound) {
</span><span class="cx">             // Add last directive to map with empty string as value
</span><del>-            result.append(std::make_pair(trimToNextSeparator(safeHeader.substring(pos, max - pos).stripWhiteSpace()), &quot;&quot;));
</del><ins>+            result.append({ trimToNextSeparator(safeHeader.substring(pos, max - pos)).toString(), emptyString() });
</ins><span class="cx">             return result;
</span><span class="cx">         }
</span><span class="cx">         if (nextCommaPosition != notFound &amp;&amp; (nextCommaPosition &lt; nextEqualSignPosition || nextEqualSignPosition == notFound)) {
</span><span class="cx">             // Add directive to map with empty string as value
</span><del>-            result.append(std::make_pair(trimToNextSeparator(safeHeader.substring(pos, nextCommaPosition - pos).stripWhiteSpace()), &quot;&quot;));
</del><ins>+            result.append({ trimToNextSeparator(safeHeader.substring(pos, nextCommaPosition - pos)).toString(), emptyString() });
</ins><span class="cx">             pos += nextCommaPosition - pos + 1;
</span><span class="cx">             continue;
</span><span class="cx">         }
</span><span class="cx">         // Get directive name, parse right hand side of equal sign, then add to map
</span><del>-        String directive = trimToNextSeparator(safeHeader.substring(pos, nextEqualSignPosition - pos).stripWhiteSpace());
</del><ins>+        String directive = trimToNextSeparator(safeHeader.substring(pos, nextEqualSignPosition - pos)).toString();
</ins><span class="cx">         pos += nextEqualSignPosition - pos + 1;
</span><span class="cx"> 
</span><del>-        String value = safeHeader.substring(pos, max - pos).stripWhiteSpace();
</del><ins>+        StringView value = safeHeader.substring(pos, max - pos);
</ins><span class="cx">         if (value[0] == '&quot;') {
</span><span class="cx">             // The value is a quoted string
</span><span class="cx">             size_t nextDoubleQuotePosition = value.find('&quot;', 1);
</span><span class="cx">             if (nextDoubleQuotePosition == notFound) {
</span><span class="cx">                 // Parse error; just use the rest as the value
</span><del>-                result.append(std::make_pair(directive, trimToNextSeparator(value.substring(1, value.length() - 1).stripWhiteSpace())));
</del><ins>+                result.append({ directive, trimToNextSeparator(value.substring(1, value.length() - 1)).toString() });
</ins><span class="cx">                 return result;
</span><span class="cx">             }
</span><span class="cx">             // Store the value as a quoted string without quotes
</span><del>-            result.append(std::make_pair(directive, value.substring(1, nextDoubleQuotePosition - 1).stripWhiteSpace()));
</del><ins>+            result.append({ directive, value.substring(1, nextDoubleQuotePosition - 1).toString() });
</ins><span class="cx">             pos += (safeHeader.find('&quot;', pos) - pos) + nextDoubleQuotePosition + 1;
</span><span class="cx">             // Move past next comma, if there is one
</span><span class="cx">             size_t nextCommaPosition2 = safeHeader.find(',', pos);
</span><span class="lines">@@ -260,11 +262,11 @@
</span><span class="cx">         size_t nextCommaPosition2 = value.find(',');
</span><span class="cx">         if (nextCommaPosition2 == notFound) {
</span><span class="cx">             // The rest is the value; no change to value needed
</span><del>-            result.append(std::make_pair(directive, trimToNextSeparator(value)));
</del><ins>+            result.append({ directive, trimToNextSeparator(value).toString() });
</ins><span class="cx">             return result;
</span><span class="cx">         }
</span><span class="cx">         // The value is delimited by the next comma
</span><del>-        result.append(std::make_pair(directive, trimToNextSeparator(value.substring(0, nextCommaPosition2).stripWhiteSpace())));
</del><ins>+        result.append({ directive, trimToNextSeparator(value.substring(0, nextCommaPosition2)).toString() });
</ins><span class="cx">         pos += (safeHeader.find(',', pos) - pos) + 1;
</span><span class="cx">     }
</span><span class="cx">     return result;
</span></span></pre>
</div>
</div>

</body>
</html>