<!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>[209179] trunk</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/209179">209179</a></dd>
<dt>Author</dt> <dd>utatane.tea@gmail.com</dd>
<dt>Date</dt> <dd>2016-12-01 01:24:21 -0800 (Thu, 01 Dec 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Introduce StringImpl::StaticStringImpl with constexpr constructor
https://bugs.webkit.org/show_bug.cgi?id=165093

Reviewed by Darin Adler.

Source/WTF:

This patch adds new class, StringImpl::StaticStringImpl.
By using this class, we can easily create static StringImpls.
This class has constexpr constructor. You can initialize instances
of this class as global static variables without invoking global
constructors.

We already have similar system, StaticASCIILiteral. But using it
requires some special perl script since we need to calculate
hash value. On the other hand, we can use StaticStringImpl without
any script supports since we implement constexpr hash function.
In the future, we will replace all the use of StaticASCIILiteral
with this StaticStringImpl.

We define empty / null strings as StaticStringImpl. And we make
StringImpl::empty() &amp; StringImpl::null() inline functions.

* wtf/Hasher.h:
(WTF::StringHasher::hashWithTop8BitsMasked):
(WTF::StringHasher::hash):
(WTF::StringHasher::finalize):
(WTF::StringHasher::finalizeAndMaskTop8Bits):
(WTF::StringHasher::computeLiteralHash):
(WTF::StringHasher::computeLiteralHashAndMaskTop8Bits):
(WTF::StringHasher::avalancheBits3):
(WTF::StringHasher::avalancheBits2):
(WTF::StringHasher::avalancheBits1):
(WTF::StringHasher::avalancheBits0):
(WTF::StringHasher::avalancheBits):
(WTF::StringHasher::avoidZero):
(WTF::StringHasher::processPendingCharacter):
(WTF::StringHasher::calculateWithRemainingLastCharacter1):
(WTF::StringHasher::calculateWithRemainingLastCharacter0):
(WTF::StringHasher::calculateWithRemainingLastCharacter):
(WTF::StringHasher::calculate1):
(WTF::StringHasher::calculate0):
(WTF::StringHasher::calculate):
(WTF::StringHasher::computeLiteralHashImpl):
* wtf/text/StringImpl.cpp:
* wtf/text/StringImpl.h:
(WTF::StringImpl::StaticStringImpl::StaticStringImpl):
(WTF::StringImpl::null):
(WTF::StringImpl::empty):
* wtf/text/StringStatics.cpp:
(WTF::StringImpl::null): Deleted.
(WTF::StringImpl::empty): Deleted.

Tools:

* TestWebKitAPI/Tests/WTF/StringImpl.cpp:
(TestWebKitAPI::TEST):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWTFChangeLog">trunk/Source/WTF/ChangeLog</a></li>
<li><a href="#trunkSourceWTFwtfHasherh">trunk/Source/WTF/wtf/Hasher.h</a></li>
<li><a href="#trunkSourceWTFwtftextStringImplcpp">trunk/Source/WTF/wtf/text/StringImpl.cpp</a></li>
<li><a href="#trunkSourceWTFwtftextStringImplh">trunk/Source/WTF/wtf/text/StringImpl.h</a></li>
<li><a href="#trunkSourceWTFwtftextStringStaticscpp">trunk/Source/WTF/wtf/text/StringStatics.cpp</a></li>
<li><a href="#trunkToolsChangeLog">trunk/Tools/ChangeLog</a></li>
<li><a href="#trunkToolsTestWebKitAPITestsWTFStringImplcpp">trunk/Tools/TestWebKitAPI/Tests/WTF/StringImpl.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWTFChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/ChangeLog (209178 => 209179)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/ChangeLog        2016-12-01 09:22:51 UTC (rev 209178)
+++ trunk/Source/WTF/ChangeLog        2016-12-01 09:24:21 UTC (rev 209179)
</span><span class="lines">@@ -1,3 +1,56 @@
</span><ins>+2016-12-01  Yusuke Suzuki  &lt;utatane.tea@gmail.com&gt;
+
+        Introduce StringImpl::StaticStringImpl with constexpr constructor
+        https://bugs.webkit.org/show_bug.cgi?id=165093
+
+        Reviewed by Darin Adler.
+
+        This patch adds new class, StringImpl::StaticStringImpl.
+        By using this class, we can easily create static StringImpls.
+        This class has constexpr constructor. You can initialize instances
+        of this class as global static variables without invoking global
+        constructors.
+
+        We already have similar system, StaticASCIILiteral. But using it
+        requires some special perl script since we need to calculate
+        hash value. On the other hand, we can use StaticStringImpl without
+        any script supports since we implement constexpr hash function.
+        In the future, we will replace all the use of StaticASCIILiteral
+        with this StaticStringImpl.
+
+        We define empty / null strings as StaticStringImpl. And we make
+        StringImpl::empty() &amp; StringImpl::null() inline functions.
+
+        * wtf/Hasher.h:
+        (WTF::StringHasher::hashWithTop8BitsMasked):
+        (WTF::StringHasher::hash):
+        (WTF::StringHasher::finalize):
+        (WTF::StringHasher::finalizeAndMaskTop8Bits):
+        (WTF::StringHasher::computeLiteralHash):
+        (WTF::StringHasher::computeLiteralHashAndMaskTop8Bits):
+        (WTF::StringHasher::avalancheBits3):
+        (WTF::StringHasher::avalancheBits2):
+        (WTF::StringHasher::avalancheBits1):
+        (WTF::StringHasher::avalancheBits0):
+        (WTF::StringHasher::avalancheBits):
+        (WTF::StringHasher::avoidZero):
+        (WTF::StringHasher::processPendingCharacter):
+        (WTF::StringHasher::calculateWithRemainingLastCharacter1):
+        (WTF::StringHasher::calculateWithRemainingLastCharacter0):
+        (WTF::StringHasher::calculateWithRemainingLastCharacter):
+        (WTF::StringHasher::calculate1):
+        (WTF::StringHasher::calculate0):
+        (WTF::StringHasher::calculate):
+        (WTF::StringHasher::computeLiteralHashImpl):
+        * wtf/text/StringImpl.cpp:
+        * wtf/text/StringImpl.h:
+        (WTF::StringImpl::StaticStringImpl::StaticStringImpl):
+        (WTF::StringImpl::null):
+        (WTF::StringImpl::empty):
+        * wtf/text/StringStatics.cpp:
+        (WTF::StringImpl::null): Deleted.
+        (WTF::StringImpl::empty): Deleted.
+
</ins><span class="cx"> 2016-11-30  Darin Adler  &lt;darin@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Roll out StringBuilder changes from the previous patch.
</span></span></pre></div>
<a id="trunkSourceWTFwtfHasherh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/Hasher.h (209178 => 209179)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/Hasher.h        2016-12-01 09:22:51 UTC (rev 209178)
+++ trunk/Source/WTF/wtf/Hasher.h        2016-12-01 09:24:21 UTC (rev 209179)
</span><span class="lines">@@ -36,11 +36,12 @@
</span><span class="cx"> // JavaScriptCore and the CodeGeneratorJS.pm script in WebCore.
</span><span class="cx"> 
</span><span class="cx"> // Golden ratio. Arbitrary start value to avoid mapping all zeros to a hash value of zero.
</span><del>-static const unsigned stringHashingStartValue = 0x9E3779B9U;
</del><ins>+static constexpr const unsigned stringHashingStartValue = 0x9E3779B9U;
</ins><span class="cx"> 
</span><span class="cx"> class StringHasher {
</span><span class="cx"> public:
</span><del>-    static const unsigned flagCount = 8; // Save 8 bits for StringImpl to use as flags.
</del><ins>+    static constexpr const unsigned flagCount = 8; // Save 8 bits for StringImpl to use as flags.
+    static constexpr const unsigned maskHash = (1U &lt;&lt; (sizeof(unsigned) * 8 - flagCount)) - 1;
</ins><span class="cx"> 
</span><span class="cx">     StringHasher()
</span><span class="cx">         : m_hash(stringHashingStartValue)
</span><span class="lines">@@ -162,34 +163,12 @@
</span><span class="cx"> 
</span><span class="cx">     unsigned hashWithTop8BitsMasked() const
</span><span class="cx">     {
</span><del>-        unsigned result = avalancheBits();
-
-        // Reserving space from the high bits for flags preserves most of the hash's
-        // value, since hash lookup typically masks out the high bits anyway.
-        result &amp;= (1U &lt;&lt; (sizeof(result) * 8 - flagCount)) - 1;
-
-        // This avoids ever returning a hash code of 0, since that is used to
-        // signal &quot;hash not computed yet&quot;. Setting the high bit maintains
-        // reasonable fidelity to a hash code of 0 because it is likely to yield
-        // exactly 0 when hash lookup masks out the high bits.
-        if (!result)
-            result = 0x80000000 &gt;&gt; flagCount;
-
-        return result;
</del><ins>+        return finalizeAndMaskTop8Bits(processPendingCharacter());
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     unsigned hash() const
</span><span class="cx">     {
</span><del>-        unsigned result = avalancheBits();
-
-        // This avoids ever returning a hash code of 0, since that is used to
-        // signal &quot;hash not computed yet&quot;. Setting the high bit maintains
-        // reasonable fidelity to a hash code of 0 because it is likely to yield
-        // exactly 0 when hash lookup masks out the high bits.
-        if (!result)
-            result = 0x80000000;
-
-        return result;
</del><ins>+        return finalize(processPendingCharacter());
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     template&lt;typename T, UChar Converter(T)&gt; static unsigned computeHashAndMaskTop8Bits(const T* data, unsigned length)
</span><span class="lines">@@ -257,6 +236,30 @@
</span><span class="cx">         return hashMemory(data, length);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    static constexpr unsigned finalize(unsigned hash)
+    {
+        return avoidZero(avalancheBits(hash));
+    }
+
+    static constexpr unsigned finalizeAndMaskTop8Bits(unsigned hash)
+    {
+        // Reserving space from the high bits for flags preserves most of the hash's
+        // value, since hash lookup typically masks out the high bits anyway.
+        return avoidZero(avalancheBits(hash) &amp; StringHasher::maskHash);
+    }
+
+    template&lt;typename T, unsigned charactersCount&gt;
+    static constexpr unsigned computeLiteralHash(const T (&amp;characters)[charactersCount])
+    {
+        return StringHasher::finalize(computeLiteralHashImpl(stringHashingStartValue, 0, characters, charactersCount - 1));
+    }
+
+    template&lt;typename T, unsigned charactersCount&gt;
+    static constexpr unsigned computeLiteralHashAndMaskTop8Bits(const T (&amp;characters)[charactersCount])
+    {
+        return StringHasher::finalizeAndMaskTop8Bits(computeLiteralHashImpl(stringHashingStartValue, 0, characters, charactersCount - 1));
+    }
+
</ins><span class="cx"> private:
</span><span class="cx">     static UChar defaultConverter(UChar character)
</span><span class="cx">     {
</span><span class="lines">@@ -268,8 +271,42 @@
</span><span class="cx">         return character;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    unsigned avalancheBits() const
</del><ins>+    ALWAYS_INLINE static constexpr unsigned avalancheBits3(unsigned hash)
</ins><span class="cx">     {
</span><ins>+        return hash ^ (hash &lt;&lt; 10);
+    }
+
+    ALWAYS_INLINE static constexpr unsigned avalancheBits2(unsigned hash)
+    {
+        return avalancheBits3(hash + (hash &gt;&gt; 15));
+    }
+
+    ALWAYS_INLINE static constexpr unsigned avalancheBits1(unsigned hash)
+    {
+        return avalancheBits2(hash ^ (hash &lt;&lt; 2));
+    }
+
+    ALWAYS_INLINE static constexpr unsigned avalancheBits0(unsigned hash)
+    {
+        return avalancheBits1(hash + (hash &gt;&gt; 5));
+    }
+
+    ALWAYS_INLINE static constexpr unsigned avalancheBits(unsigned hash)
+    {
+        return avalancheBits0(hash ^ (hash &lt;&lt; 3));
+    }
+
+    // This avoids ever returning a hash code of 0, since that is used to
+    // signal &quot;hash not computed yet&quot;. Setting the high bit maintains
+    // reasonable fidelity to a hash code of 0 because it is likely to yield
+    // exactly 0 when hash lookup masks out the high bits.
+    ALWAYS_INLINE static constexpr unsigned avoidZero(unsigned hash)
+    {
+        return hash ? hash : (0x80000000 &gt;&gt; StringHasher::flagCount);
+    }
+
+    unsigned processPendingCharacter() const
+    {
</ins><span class="cx">         unsigned result = m_hash;
</span><span class="cx"> 
</span><span class="cx">         // Handle end case.
</span><span class="lines">@@ -278,17 +315,51 @@
</span><span class="cx">             result ^= result &lt;&lt; 11;
</span><span class="cx">             result += result &gt;&gt; 17;
</span><span class="cx">         }
</span><ins>+        return result;
+    }
</ins><span class="cx"> 
</span><del>-        // Force &quot;avalanching&quot; of final 31 bits.
-        result ^= result &lt;&lt; 3;
-        result += result &gt;&gt; 5;
-        result ^= result &lt;&lt; 2;
-        result += result &gt;&gt; 15;
-        result ^= result &lt;&lt; 10;
</del><span class="cx"> 
</span><del>-        return result;
</del><ins>+    // FIXME: This code limits itself to the older, more limited C++11 constexpr capabilities, using
+    // recursion instead of looping, for example. Would be nice to rewrite this in a simpler way
+    // once we no longer need to support compilers like GCC 4.9 that do not yet support it.
+    static constexpr unsigned calculateWithRemainingLastCharacter1(unsigned hash)
+    {
+        return hash + (hash &gt;&gt; 17);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    static constexpr unsigned calculateWithRemainingLastCharacter0(unsigned hash)
+    {
+        return calculateWithRemainingLastCharacter1((hash &lt;&lt; 11) ^ hash);
+    }
+
+    static constexpr unsigned calculateWithRemainingLastCharacter(unsigned hash, unsigned character)
+    {
+        return calculateWithRemainingLastCharacter0(hash + character);
+    }
+
+    static constexpr unsigned calculate1(unsigned hash)
+    {
+        return hash + (hash &gt;&gt; 11);
+    }
+
+    static constexpr unsigned calculate0(unsigned hash, unsigned secondCharacter)
+    {
+        return calculate1((hash &lt;&lt; 16) ^ ((secondCharacter &lt;&lt; 11) ^ hash));
+    }
+
+    static constexpr unsigned calculate(unsigned hash, unsigned firstCharacter, unsigned secondCharacter)
+    {
+        return calculate0(hash + firstCharacter, secondCharacter);
+    }
+
+    static constexpr unsigned computeLiteralHashImpl(unsigned hash, unsigned index, const char* characters, unsigned length)
+    {
+        return (index == length)
+            ? hash : ((index + 1) == length)
+            ? calculateWithRemainingLastCharacter(hash, characters[index])
+            : computeLiteralHashImpl(calculate(hash, characters[index], characters[index + 1]), index + 2, characters, length);
+    }
+
</ins><span class="cx">     unsigned m_hash;
</span><span class="cx">     bool m_hasPendingCharacter;
</span><span class="cx">     UChar m_pendingCharacter;
</span></span></pre></div>
<a id="trunkSourceWTFwtftextStringImplcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/text/StringImpl.cpp (209178 => 209179)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/text/StringImpl.cpp        2016-12-01 09:22:51 UTC (rev 209178)
+++ trunk/Source/WTF/wtf/text/StringImpl.cpp        2016-12-01 09:24:21 UTC (rev 209179)
</span><span class="lines">@@ -101,6 +101,8 @@
</span><span class="cx"> }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+StringImpl::StaticStringImpl StringImpl::s_atomicNullString(&quot;&quot;, StringImpl::StringAtomic);
+StringImpl::StaticStringImpl StringImpl::s_atomicEmptyString(&quot;&quot;, StringImpl::StringAtomic);
</ins><span class="cx"> 
</span><span class="cx"> StringImpl::~StringImpl()
</span><span class="cx"> {
</span></span></pre></div>
<a id="trunkSourceWTFwtftextStringImplh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/text/StringImpl.h (209178 => 209179)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/text/StringImpl.h        2016-12-01 09:22:51 UTC (rev 209178)
+++ trunk/Source/WTF/wtf/text/StringImpl.h        2016-12-01 09:24:21 UTC (rev 209179)
</span><span class="lines">@@ -149,18 +149,18 @@
</span><span class="cx"> 
</span><span class="cx">     // The bottom 6 bits in the hash are flags.
</span><span class="cx"> public:
</span><del>-    static const unsigned s_flagCount = 6;
</del><ins>+    static constexpr const unsigned s_flagCount = 6;
</ins><span class="cx"> private:
</span><del>-    static const unsigned s_flagMask = (1u &lt;&lt; s_flagCount) - 1;
-    COMPILE_ASSERT(s_flagCount &lt;= StringHasher::flagCount, StringHasher_reserves_enough_bits_for_StringImpl_flags);
-    static const unsigned s_flagStringKindCount = 4;
</del><ins>+    static constexpr const unsigned s_flagMask = (1u &lt;&lt; s_flagCount) - 1;
+    static_assert(s_flagCount &lt;= StringHasher::flagCount, &quot;StringHasher reserves enough bits for StringImpl flags&quot;);
+    static constexpr const unsigned s_flagStringKindCount = 4;
</ins><span class="cx"> 
</span><del>-    static const unsigned s_hashFlagStringKindIsAtomic = 1u &lt;&lt; (s_flagStringKindCount);
-    static const unsigned s_hashFlagStringKindIsSymbol = 1u &lt;&lt; (s_flagStringKindCount + 1);
-    static const unsigned s_hashMaskStringKind = s_hashFlagStringKindIsAtomic | s_hashFlagStringKindIsSymbol;
-    static const unsigned s_hashFlag8BitBuffer = 1u &lt;&lt; 3;
-    static const unsigned s_hashFlagDidReportCost = 1u &lt;&lt; 2;
-    static const unsigned s_hashMaskBufferOwnership = (1u &lt;&lt; 0) | (1u &lt;&lt; 1);
</del><ins>+    static constexpr const unsigned s_hashFlagStringKindIsAtomic = 1u &lt;&lt; (s_flagStringKindCount);
+    static constexpr const unsigned s_hashFlagStringKindIsSymbol = 1u &lt;&lt; (s_flagStringKindCount + 1);
+    static constexpr const unsigned s_hashMaskStringKind = s_hashFlagStringKindIsAtomic | s_hashFlagStringKindIsSymbol;
+    static constexpr const unsigned s_hashFlag8BitBuffer = 1u &lt;&lt; 3;
+    static constexpr const unsigned s_hashFlagDidReportCost = 1u &lt;&lt; 2;
+    static constexpr const unsigned s_hashMaskBufferOwnership = (1u &lt;&lt; 0) | (1u &lt;&lt; 1);
</ins><span class="cx"> 
</span><span class="cx">     enum StringKind {
</span><span class="cx">         StringNormal = 0u, // non-symbol, non-atomic
</span><span class="lines">@@ -168,25 +168,6 @@
</span><span class="cx">         StringSymbol = s_hashFlagStringKindIsSymbol, // symbol, non-atomic
</span><span class="cx">     };
</span><span class="cx"> 
</span><del>-    // Used to construct static strings, which have an special refCount that can never hit zero.
-    // This means that the static string will never be destroyed, which is important because
-    // static strings will be shared across threads &amp; ref-counted in a non-threadsafe manner.
-    friend class NeverDestroyed&lt;StringImpl&gt;;
-    enum ConstructEmptyStringTag { ConstructEmptyString };
-    StringImpl(ConstructEmptyStringTag)
-        : m_refCount(s_refCountFlagIsStaticString)
-        , m_length(0)
-        , m_data8(reinterpret_cast&lt;const LChar*&gt;(&amp;m_length))
-        , m_hashAndFlags(s_hashFlag8BitBuffer | StringAtomic | BufferOwned)
-    {
-        // Ensure that the hash is computed so that AtomicStringHash can call existingHash()
-        // with impunity. The empty string is special because it is never entered into
-        // AtomicString's HashKey, but still needs to compare correctly.
-        STRING_STATS_ADD_8BIT_STRING(m_length);
-
-        hash();
-    }
-
</del><span class="cx">     // FIXME: there has to be a less hacky way to do this.
</span><span class="cx">     enum Force8Bit { Force8BitConstructor };
</span><span class="cx">     // Create a normal 8-bit string with internal storage (BufferInternal)
</span><span class="lines">@@ -606,8 +587,44 @@
</span><span class="cx">         m_refCount = tempRefCount;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    WTF_EXPORT_PRIVATE static StringImpl* empty();
</del><ins>+    class StaticStringImpl {
+    public:
+        // Used to construct static strings, which have an special refCount that can never hit zero.
+        // This means that the static string will never be destroyed, which is important because
+        // static strings will be shared across threads &amp; ref-counted in a non-threadsafe manner.
+        template&lt;unsigned charactersCount&gt;
+        constexpr StaticStringImpl(const char (&amp;characters)[charactersCount], StringKind stringKind = StringNormal)
+            : m_refCount(s_refCountFlagIsStaticString)
+            , m_length(charactersCount - 1)
+            , m_data8(characters)
+            , m_hashAndFlags(s_hashFlag8BitBuffer | stringKind | BufferInternal | (StringHasher::computeLiteralHashAndMaskTop8Bits(characters) &lt;&lt; s_flagCount))
+        {
+        }
</ins><span class="cx"> 
</span><ins>+        template&lt;unsigned charactersCount&gt;
+        constexpr StaticStringImpl(const char16_t (&amp;characters)[charactersCount], StringKind stringKind = StringNormal)
+            : m_refCount(s_refCountFlagIsStaticString)
+            , m_length(charactersCount - 1)
+            , m_data16(characters)
+            , m_hashAndFlags(stringKind | BufferInternal | (StringHasher::computeLiteralHashAndMaskTop8Bits(characters) &lt;&lt; s_flagCount))
+        {
+        }
+
+        // These member variables must match the layout of StringImpl.
+        unsigned m_refCount;
+        unsigned m_length;
+        union {
+            const char* m_data8;
+            const char16_t* m_data16;
+        };
+        unsigned m_hashAndFlags;
+    };
+
+    WTF_EXPORTDATA static StaticStringImpl s_atomicNullString;
+    WTF_EXPORTDATA static StaticStringImpl s_atomicEmptyString;
+    ALWAYS_INLINE static StringImpl* null() { return reinterpret_cast&lt;StringImpl*&gt;(&amp;s_atomicNullString); }
+    ALWAYS_INLINE static StringImpl* empty() { return reinterpret_cast&lt;StringImpl*&gt;(&amp;s_atomicEmptyString); }
+
</ins><span class="cx">     // FIXME: Does this really belong in StringImpl?
</span><span class="cx">     template &lt;typename T&gt; static void copyChars(T* destination, const T* source, unsigned numCharacters)
</span><span class="cx">     {
</span><span class="lines">@@ -866,7 +883,6 @@
</span><span class="cx">     template &lt;typename CharType&gt; static Ref&lt;StringImpl&gt; createInternal(const CharType*, unsigned);
</span><span class="cx">     WTF_EXPORT_PRIVATE NEVER_INLINE unsigned hashSlowCase() const;
</span><span class="cx">     WTF_EXPORT_PRIVATE static unsigned nextHashForSymbol();
</span><del>-    WTF_EXPORT_PRIVATE static StringImpl* null();
</del><span class="cx"> 
</span><span class="cx">     // The bottom bit in the ref count indicates a static (immortal) string.
</span><span class="cx">     static const unsigned s_refCountFlagIsStaticString = 0x1;
</span><span class="lines">@@ -877,6 +893,8 @@
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> public:
</span><ins>+    // FIXME: It should be replaced with StaticStringImpl.
+    // https://bugs.webkit.org/show_bug.cgi?id=165134
</ins><span class="cx">     struct StaticASCIILiteral {
</span><span class="cx">         // These member variables must match the layout of StringImpl.
</span><span class="cx">         unsigned m_refCount;
</span><span class="lines">@@ -899,7 +917,7 @@
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> private:
</span><del>-    // These member variables must match the layout of StaticASCIILiteral.
</del><ins>+    // These member variables must match the layout of StaticASCIILiteral and StaticStringImpl.
</ins><span class="cx">     unsigned m_refCount;
</span><span class="cx">     unsigned m_length;
</span><span class="cx">     union {
</span><span class="lines">@@ -910,6 +928,7 @@
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> static_assert(sizeof(StringImpl) == sizeof(StringImpl::StaticASCIILiteral), &quot;&quot;);
</span><ins>+static_assert(sizeof(StringImpl) == sizeof(StringImpl::StaticStringImpl), &quot;&quot;);
</ins><span class="cx"> 
</span><span class="cx"> #if !ASSERT_DISABLED
</span><span class="cx"> // StringImpls created from StaticASCIILiteral will ASSERT
</span></span></pre></div>
<a id="trunkSourceWTFwtftextStringStaticscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/text/StringStatics.cpp (209178 => 209179)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/text/StringStatics.cpp        2016-12-01 09:22:51 UTC (rev 209178)
+++ trunk/Source/WTF/wtf/text/StringStatics.cpp        2016-12-01 09:24:21 UTC (rev 209179)
</span><span class="lines">@@ -41,18 +41,6 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WTF {
</span><span class="cx"> 
</span><del>-StringImpl* StringImpl::null()
-{
-    static NeverDestroyed&lt;StringImpl&gt; nullString(ConstructEmptyString);
-    return &amp;nullString.get();
-}
-
-StringImpl* StringImpl::empty()
-{
-    static NeverDestroyed&lt;StringImpl&gt; emptyString(ConstructEmptyString);
-    return &amp;emptyString.get();
-}
-
</del><span class="cx"> // In addition to the normal hash value, store specialized hash value for
</span><span class="cx"> // symbolized StringImpl*. And don't use the normal hash value for symbolized
</span><span class="cx"> // StringImpl* when they are treated as Identifiers. Unique nature of these
</span></span></pre></div>
<a id="trunkToolsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Tools/ChangeLog (209178 => 209179)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/ChangeLog        2016-12-01 09:22:51 UTC (rev 209178)
+++ trunk/Tools/ChangeLog        2016-12-01 09:24:21 UTC (rev 209179)
</span><span class="lines">@@ -1,3 +1,13 @@
</span><ins>+2016-12-01  Yusuke Suzuki  &lt;utatane.tea@gmail.com&gt;
+
+        Introduce StringImpl::StaticStringImpl with constexpr constructor
+        https://bugs.webkit.org/show_bug.cgi?id=165093
+
+        Reviewed by Darin Adler.
+
+        * TestWebKitAPI/Tests/WTF/StringImpl.cpp:
+        (TestWebKitAPI::TEST):
+
</ins><span class="cx"> 2016-11-30  Antoine Quint  &lt;graouts@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [Modern Media Controls] Add an HTML comment flag to turn the feature on
</span></span></pre></div>
<a id="trunkToolsTestWebKitAPITestsWTFStringImplcpp"></a>
<div class="modfile"><h4>Modified: trunk/Tools/TestWebKitAPI/Tests/WTF/StringImpl.cpp (209178 => 209179)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/Tests/WTF/StringImpl.cpp        2016-12-01 09:22:51 UTC (rev 209178)
+++ trunk/Tools/TestWebKitAPI/Tests/WTF/StringImpl.cpp        2016-12-01 09:24:21 UTC (rev 209179)
</span><span class="lines">@@ -25,6 +25,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;config.h&quot;
</span><span class="cx"> 
</span><ins>+#include &lt;wtf/Hasher.h&gt;
</ins><span class="cx"> #include &lt;wtf/text/SymbolImpl.h&gt;
</span><span class="cx"> #include &lt;wtf/text/WTFString.h&gt;
</span><span class="cx"> 
</span><span class="lines">@@ -574,4 +575,20 @@
</span><span class="cx">     ASSERT_FALSE(reference-&gt;isAtomic());
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+TEST(WTF, StringImplConstexprHasher)
+{
+    ASSERT_EQ(stringFromUTF8(&quot;&quot;)-&gt;hash(), StringHasher::computeLiteralHashAndMaskTop8Bits(&quot;&quot;));
+    ASSERT_EQ(stringFromUTF8(&quot;A&quot;)-&gt;hash(), StringHasher::computeLiteralHashAndMaskTop8Bits(&quot;A&quot;));
+    ASSERT_EQ(stringFromUTF8(&quot;AA&quot;)-&gt;hash(), StringHasher::computeLiteralHashAndMaskTop8Bits(&quot;AA&quot;));
+    ASSERT_EQ(stringFromUTF8(&quot;Cocoa&quot;)-&gt;hash(), StringHasher::computeLiteralHashAndMaskTop8Bits(&quot;Cocoa&quot;));
+    ASSERT_EQ(stringFromUTF8(&quot;Cappuccino&quot;)-&gt;hash(), StringHasher::computeLiteralHashAndMaskTop8Bits(&quot;Cappuccino&quot;));
+}
+
+TEST(WTF, StringImplEmpty)
+{
+    ASSERT_FALSE(StringImpl::empty()-&gt;length());
+    ASSERT_FALSE(StringImpl::null()-&gt;length());
+    ASSERT_NE(StringImpl::null(), StringImpl::empty());
+}
+
</ins><span class="cx"> } // namespace TestWebKitAPI
</span></span></pre>
</div>
</div>

</body>
</html>