<!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>[282227] branches/safari-612-branch/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/282227">282227</a></dd>
<dt>Author</dt> <dd>repstein@apple.com</dd>
<dt>Date</dt> <dd>2021-09-09 11:04:27 -0700 (Thu, 09 Sep 2021)</dd>
</dl>

<h3>Log Message</h3>
<pre>Cherry-pick <a href="http://trac.webkit.org/projects/webkit/changeset/282142">r282142</a>. rdar://problem/82931317

    Add a fast path for atomizing strings when parsing HTML
    https://bugs.webkit.org/show_bug.cgi?id=229907
    rdar://82854612

    Reviewed by Yusuke Suzuki and Darin Adler.

    On various subtests in Speedometer 2, a nontrivial amount of time is spent mapping raw UChar data vectors into
    AtomStrings while parsing HTML tag names, attribute names and attribute values. Most of this happens underneath
    the AtomHTMLToken constructor, which computes a hash for each string in the process of adding it to the atom
    string table; the time it takes to compute this string hash increases linearly with the length of the string.

    However, over the course of the benchmark, the vast majority of AtomStrings created out of tag names, attribute
    names and attribute values are both:

    (1) Strings that we've already recently atomized, and
    (2) Usually distinguishable from other atom strings based solely on their first character, last character, and
        overall string length.

    As such, it's possible to slightly improve string atomization performance in this particular case (i.e. parsing
    HTML) by maintaining a smaller cache of recently atomized AtomStrings that we index using a simple, constant-
    time hash function that considers only the first character, last character, and length of the string. In terms
    of the cache hit rate in this AtomString cache, the default string hashing algorithm only barely outperforms
    this simple hash function on Speedometer (i.e., a cache hit rate of 99.24% using the default hash algorithm vs.
    99.15% using the "first/last character and length" hash).

    Using this technique, we can get a significant performance improvement on Speedometer by introducing two small,
    fixed-size (512 capacity) AtomString tables: one to hold tag names and attribute names, and another to hold
    attribute values (which seems to contain a much larger set of unique strings); we additionally use the cheap "2-
    char & length" hash algorithm described above to index into these fixed-size tables.

    This allows us to more efficiently atomize not only known tag and attribute names, but also custom element tag
    names and attribute names and values that tend to appear frequently in markup (e.g. due to using certain
    JavaScript frameworks that get and set HTML attributes).

    * Sources.txt:
    * WebCore.xcodeproj/project.pbxproj:
    * html/parser/AtomHTMLToken.h:
    (WebCore::AtomHTMLToken::initializeAttributes):
    (WebCore::AtomHTMLToken::AtomHTMLToken):
    * html/parser/HTMLAtomStringCache.cpp: Added.
    (WebCore::HTMLAtomStringCache::cache):
    * html/parser/HTMLAtomStringCache.h: Added.

    Add a helper class that exposes three static inline helper methods: `makeTagOrAttributeName` and
    `makeAttributeValue`, which return AtomStrings for the given `Vector<UChar>` (consulting the corresponding
    cache if possible); and `clear`, which empties all cached atom strings.

    (WebCore::HTMLAtomStringCache::makeTagOrAttributeName):
    (WebCore::HTMLAtomStringCache::makeAttributeValue):
    (WebCore::HTMLAtomStringCache::clear):
    (WebCore::HTMLAtomStringCache::make):

    Additionally add an upper length limit for characters that we include in this cache; in practice, longer strings
    tend to be repeatedly atomized less frequently than shorter strings. The 36-character limit also allows for
    frequently-parsed (and atomized) UUIDs to be cached.

    (WebCore::HTMLAtomStringCache::cacheSlot):

    This hashing algorithm was inspired by `calculateWithTwoCharacters`, but with constants specifically chosen to
    minimize collisions between common HTML tag and attribute names.

    * page/MemoryRelease.cpp:
    (WebCore::releaseNoncriticalMemory):
    * page/cocoa/MemoryReleaseCocoa.mm:
    (WebCore::jettisonExpensiveObjectsOnTopLevelNavigation):

    Add logic to clear the HTML atom string cache upon receiving a low memory warning, and upon top-level
    navigation.

    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@282142 268f45cc-cd09-0410-ab3c-d52691b4dbfc</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#branchessafari612branchSourceWebCoreChangeLog">branches/safari-612-branch/Source/WebCore/ChangeLog</a></li>
<li><a href="#branchessafari612branchSourceWebCoreSourcestxt">branches/safari-612-branch/Source/WebCore/Sources.txt</a></li>
<li><a href="#branchessafari612branchSourceWebCoreWebCorexcodeprojprojectpbxproj">branches/safari-612-branch/Source/WebCore/WebCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#branchessafari612branchSourceWebCorehtmlparserAtomHTMLTokenh">branches/safari-612-branch/Source/WebCore/html/parser/AtomHTMLToken.h</a></li>
<li><a href="#branchessafari612branchSourceWebCorepageMemoryReleasecpp">branches/safari-612-branch/Source/WebCore/page/MemoryRelease.cpp</a></li>
<li><a href="#branchessafari612branchSourceWebCorepagecocoaMemoryReleaseCocoamm">branches/safari-612-branch/Source/WebCore/page/cocoa/MemoryReleaseCocoa.mm</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#branchessafari612branchSourceWebCorehtmlparserHTMLAtomStringCachecpp">branches/safari-612-branch/Source/WebCore/html/parser/HTMLAtomStringCache.cpp</a></li>
<li><a href="#branchessafari612branchSourceWebCorehtmlparserHTMLAtomStringCacheh">branches/safari-612-branch/Source/WebCore/html/parser/HTMLAtomStringCache.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="branchessafari612branchSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: branches/safari-612-branch/Source/WebCore/ChangeLog (282226 => 282227)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612-branch/Source/WebCore/ChangeLog      2021-09-09 18:01:36 UTC (rev 282226)
+++ branches/safari-612-branch/Source/WebCore/ChangeLog 2021-09-09 18:04:27 UTC (rev 282227)
</span><span class="lines">@@ -1,3 +1,150 @@
</span><ins>+2021-09-09  Russell Epstein  <repstein@apple.com>
+
+        Cherry-pick r282142. rdar://problem/82931317
+
+    Add a fast path for atomizing strings when parsing HTML
+    https://bugs.webkit.org/show_bug.cgi?id=229907
+    rdar://82854612
+    
+    Reviewed by Yusuke Suzuki and Darin Adler.
+    
+    On various subtests in Speedometer 2, a nontrivial amount of time is spent mapping raw UChar data vectors into
+    AtomStrings while parsing HTML tag names, attribute names and attribute values. Most of this happens underneath
+    the AtomHTMLToken constructor, which computes a hash for each string in the process of adding it to the atom
+    string table; the time it takes to compute this string hash increases linearly with the length of the string.
+    
+    However, over the course of the benchmark, the vast majority of AtomStrings created out of tag names, attribute
+    names and attribute values are both:
+    
+    (1) Strings that we've already recently atomized, and
+    (2) Usually distinguishable from other atom strings based solely on their first character, last character, and
+        overall string length.
+    
+    As such, it's possible to slightly improve string atomization performance in this particular case (i.e. parsing
+    HTML) by maintaining a smaller cache of recently atomized AtomStrings that we index using a simple, constant-
+    time hash function that considers only the first character, last character, and length of the string. In terms
+    of the cache hit rate in this AtomString cache, the default string hashing algorithm only barely outperforms
+    this simple hash function on Speedometer (i.e., a cache hit rate of 99.24% using the default hash algorithm vs.
+    99.15% using the "first/last character and length" hash).
+    
+    Using this technique, we can get a significant performance improvement on Speedometer by introducing two small,
+    fixed-size (512 capacity) AtomString tables: one to hold tag names and attribute names, and another to hold
+    attribute values (which seems to contain a much larger set of unique strings); we additionally use the cheap "2-
+    char & length" hash algorithm described above to index into these fixed-size tables.
+    
+    This allows us to more efficiently atomize not only known tag and attribute names, but also custom element tag
+    names and attribute names and values that tend to appear frequently in markup (e.g. due to using certain
+    JavaScript frameworks that get and set HTML attributes).
+    
+    * Sources.txt:
+    * WebCore.xcodeproj/project.pbxproj:
+    * html/parser/AtomHTMLToken.h:
+    (WebCore::AtomHTMLToken::initializeAttributes):
+    (WebCore::AtomHTMLToken::AtomHTMLToken):
+    * html/parser/HTMLAtomStringCache.cpp: Added.
+    (WebCore::HTMLAtomStringCache::cache):
+    * html/parser/HTMLAtomStringCache.h: Added.
+    
+    Add a helper class that exposes three static inline helper methods: `makeTagOrAttributeName` and
+    `makeAttributeValue`, which return AtomStrings for the given `Vector<UChar>` (consulting the corresponding
+    cache if possible); and `clear`, which empties all cached atom strings.
+    
+    (WebCore::HTMLAtomStringCache::makeTagOrAttributeName):
+    (WebCore::HTMLAtomStringCache::makeAttributeValue):
+    (WebCore::HTMLAtomStringCache::clear):
+    (WebCore::HTMLAtomStringCache::make):
+    
+    Additionally add an upper length limit for characters that we include in this cache; in practice, longer strings
+    tend to be repeatedly atomized less frequently than shorter strings. The 36-character limit also allows for
+    frequently-parsed (and atomized) UUIDs to be cached.
+    
+    (WebCore::HTMLAtomStringCache::cacheSlot):
+    
+    This hashing algorithm was inspired by `calculateWithTwoCharacters`, but with constants specifically chosen to
+    minimize collisions between common HTML tag and attribute names.
+    
+    * page/MemoryRelease.cpp:
+    (WebCore::releaseNoncriticalMemory):
+    * page/cocoa/MemoryReleaseCocoa.mm:
+    (WebCore::jettisonExpensiveObjectsOnTopLevelNavigation):
+    
+    Add logic to clear the HTML atom string cache upon receiving a low memory warning, and upon top-level
+    navigation.
+    
+    
+    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@282142 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+    2021-09-08  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+            Add a fast path for atomizing strings when parsing HTML
+            https://bugs.webkit.org/show_bug.cgi?id=229907
+            rdar://82854612
+
+            Reviewed by Yusuke Suzuki and Darin Adler.
+
+            On various subtests in Speedometer 2, a nontrivial amount of time is spent mapping raw UChar data vectors into
+            AtomStrings while parsing HTML tag names, attribute names and attribute values. Most of this happens underneath
+            the AtomHTMLToken constructor, which computes a hash for each string in the process of adding it to the atom
+            string table; the time it takes to compute this string hash increases linearly with the length of the string.
+
+            However, over the course of the benchmark, the vast majority of AtomStrings created out of tag names, attribute
+            names and attribute values are both:
+
+            (1) Strings that we've already recently atomized, and
+            (2) Usually distinguishable from other atom strings based solely on their first character, last character, and
+                overall string length.
+
+            As such, it's possible to slightly improve string atomization performance in this particular case (i.e. parsing
+            HTML) by maintaining a smaller cache of recently atomized AtomStrings that we index using a simple, constant-
+            time hash function that considers only the first character, last character, and length of the string. In terms
+            of the cache hit rate in this AtomString cache, the default string hashing algorithm only barely outperforms
+            this simple hash function on Speedometer (i.e., a cache hit rate of 99.24% using the default hash algorithm vs.
+            99.15% using the "first/last character and length" hash).
+
+            Using this technique, we can get a significant performance improvement on Speedometer by introducing two small,
+            fixed-size (512 capacity) AtomString tables: one to hold tag names and attribute names, and another to hold
+            attribute values (which seems to contain a much larger set of unique strings); we additionally use the cheap "2-
+            char & length" hash algorithm described above to index into these fixed-size tables.
+
+            This allows us to more efficiently atomize not only known tag and attribute names, but also custom element tag
+            names and attribute names and values that tend to appear frequently in markup (e.g. due to using certain
+            JavaScript frameworks that get and set HTML attributes).
+
+            * Sources.txt:
+            * WebCore.xcodeproj/project.pbxproj:
+            * html/parser/AtomHTMLToken.h:
+            (WebCore::AtomHTMLToken::initializeAttributes):
+            (WebCore::AtomHTMLToken::AtomHTMLToken):
+            * html/parser/HTMLAtomStringCache.cpp: Added.
+            (WebCore::HTMLAtomStringCache::cache):
+            * html/parser/HTMLAtomStringCache.h: Added.
+
+            Add a helper class that exposes three static inline helper methods: `makeTagOrAttributeName` and
+            `makeAttributeValue`, which return AtomStrings for the given `Vector<UChar>` (consulting the corresponding
+            cache if possible); and `clear`, which empties all cached atom strings.
+
+            (WebCore::HTMLAtomStringCache::makeTagOrAttributeName):
+            (WebCore::HTMLAtomStringCache::makeAttributeValue):
+            (WebCore::HTMLAtomStringCache::clear):
+            (WebCore::HTMLAtomStringCache::make):
+
+            Additionally add an upper length limit for characters that we include in this cache; in practice, longer strings
+            tend to be repeatedly atomized less frequently than shorter strings. The 36-character limit also allows for
+            frequently-parsed (and atomized) UUIDs to be cached.
+
+            (WebCore::HTMLAtomStringCache::cacheSlot):
+
+            This hashing algorithm was inspired by `calculateWithTwoCharacters`, but with constants specifically chosen to
+            minimize collisions between common HTML tag and attribute names.
+
+            * page/MemoryRelease.cpp:
+            (WebCore::releaseNoncriticalMemory):
+            * page/cocoa/MemoryReleaseCocoa.mm:
+            (WebCore::jettisonExpensiveObjectsOnTopLevelNavigation):
+
+            Add logic to clear the HTML atom string cache upon receiving a low memory warning, and upon top-level
+            navigation.
+
</ins><span class="cx"> 2021-09-01  Russell Epstein  <repstein@apple.com>
</span><span class="cx"> 
</span><span class="cx">         Cherry-pick r281817. rdar://problem/82652467
</span></span></pre></div>
<a id="branchessafari612branchSourceWebCoreSourcestxt"></a>
<div class="modfile"><h4>Modified: branches/safari-612-branch/Source/WebCore/Sources.txt (282226 => 282227)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612-branch/Source/WebCore/Sources.txt    2021-09-09 18:01:36 UTC (rev 282226)
+++ branches/safari-612-branch/Source/WebCore/Sources.txt       2021-09-09 18:04:27 UTC (rev 282227)
</span><span class="lines">@@ -1302,6 +1302,7 @@
</span><span class="cx"> html/canvas/WebGLVertexArrayObjectOES.cpp
</span><span class="cx"> html/forms/FileIconLoader.cpp
</span><span class="cx"> html/parser/CSSPreloadScanner.cpp
</span><ins>+html/parser/HTMLAtomStringCache.cpp
</ins><span class="cx"> html/parser/HTMLConstructionSite.cpp
</span><span class="cx"> html/parser/HTMLDocumentParser.cpp
</span><span class="cx"> html/parser/HTMLElementStack.cpp
</span></span></pre></div>
<a id="branchessafari612branchSourceWebCoreWebCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: branches/safari-612-branch/Source/WebCore/WebCore.xcodeproj/project.pbxproj (282226 => 282227)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612-branch/Source/WebCore/WebCore.xcodeproj/project.pbxproj      2021-09-09 18:01:36 UTC (rev 282226)
+++ branches/safari-612-branch/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2021-09-09 18:04:27 UTC (rev 282227)
</span><span class="lines">@@ -5384,6 +5384,7 @@
</span><span class="cx">          F48D2A7E2157182600C6752B /* FontAttributes.h in Headers */ = {isa = PBXBuildFile; fileRef = F48D2A712156DC0A00C6752B /* FontAttributes.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">          F48D2AA52159740D00C6752B /* ColorCocoa.h in Headers */ = {isa = PBXBuildFile; fileRef = F48D2AA32159740D00C6752B /* ColorCocoa.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">          F49786881FF45FA500E060AB /* PasteboardItemInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = F49786871FF45FA500E060AB /* PasteboardItemInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><ins>+               F4B0018926E7F21F006EAABE /* HTMLAtomStringCache.h in Headers */ = {isa = PBXBuildFile; fileRef = F4B0018726E7F21F006EAABE /* HTMLAtomStringCache.h */; };
</ins><span class="cx">           F4B2A909265030BA009E7286 /* DataDetectorHighlight.h in Headers */ = {isa = PBXBuildFile; fileRef = F4B2A90626502BA0009E7286 /* DataDetectorHighlight.h */; };
</span><span class="cx">          F4B422C4220C0568009E1E7D /* DOMPasteAccess.h in Headers */ = {isa = PBXBuildFile; fileRef = F4B422C2220C0000009E1E7D /* DOMPasteAccess.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">          F4BFB9851E1DDF9B00862C24 /* DumpEditingHistory.js in Copy Scripts */ = {isa = PBXBuildFile; fileRef = F48389831E1DDF2B0076B7EA /* DumpEditingHistory.js */; };
</span><span class="lines">@@ -16555,6 +16556,8 @@
</span><span class="cx">          F48D2AA42159740D00C6752B /* ColorCocoa.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ColorCocoa.mm; sourceTree = "<group>"; };
</span><span class="cx">          F49786871FF45FA500E060AB /* PasteboardItemInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PasteboardItemInfo.h; sourceTree = "<group>"; };
</span><span class="cx">          F49E98E421DEE6C1009AE55E /* EditAction.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = EditAction.cpp; sourceTree = "<group>"; };
</span><ins>+               F4B0018726E7F21F006EAABE /* HTMLAtomStringCache.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HTMLAtomStringCache.h; sourceTree = "<group>"; };
+               F4B0018826E7F21F006EAABE /* HTMLAtomStringCache.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = HTMLAtomStringCache.cpp; sourceTree = "<group>"; };
</ins><span class="cx">           F4B2A90626502BA0009E7286 /* DataDetectorHighlight.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DataDetectorHighlight.h; sourceTree = "<group>"; };
</span><span class="cx">          F4B2A90826502BC0009E7286 /* DataDetectorHighlight.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = DataDetectorHighlight.mm; sourceTree = "<group>"; };
</span><span class="cx">          F4B2A90C265087E4009E7286 /* ImageOverlayControllerMac.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ImageOverlayControllerMac.mm; sourceTree = "<group>"; };
</span><span class="lines">@@ -24035,6 +24038,8 @@
</span><span class="cx">                          97C1F552122855CB00EDE617 /* AtomHTMLToken.h */,
</span><span class="cx">                          977B3849122883E900B81FF8 /* CSSPreloadScanner.cpp */,
</span><span class="cx">                          977B384A122883E900B81FF8 /* CSSPreloadScanner.h */,
</span><ins>+                               F4B0018826E7F21F006EAABE /* HTMLAtomStringCache.cpp */,
+                               F4B0018726E7F21F006EAABE /* HTMLAtomStringCache.h */,
</ins><span class="cx">                           977B384B122883E900B81FF8 /* HTMLConstructionSite.cpp */,
</span><span class="cx">                          977B384C122883E900B81FF8 /* HTMLConstructionSite.h */,
</span><span class="cx">                          977B384D122883E900B81FF8 /* HTMLDocumentParser.cpp */,
</span><span class="lines">@@ -32140,6 +32145,7 @@
</span><span class="cx">                          BC97E23A109144950010D361 /* HTMLAllCollection.h in Headers */,
</span><span class="cx">                          A8CFF7AB0A156978000A4234 /* HTMLAnchorElement.h in Headers */,
</span><span class="cx">                          A8EA7D2E0A19385500A8EF5F /* HTMLAreaElement.h in Headers */,
</span><ins>+                               F4B0018926E7F21F006EAABE /* HTMLAtomStringCache.h in Headers */,
</ins><span class="cx">                           7C5F28FC1A827D8400C0F31F /* HTMLAttachmentElement.h in Headers */,
</span><span class="cx">                          E44613A20CD6331000FADA75 /* HTMLAudioElement.h in Headers */,
</span><span class="cx">                          A871DC1F0A15205700B12A68 /* HTMLBaseElement.h in Headers */,
</span></span></pre></div>
<a id="branchessafari612branchSourceWebCorehtmlparserAtomHTMLTokenh"></a>
<div class="modfile"><h4>Modified: branches/safari-612-branch/Source/WebCore/html/parser/AtomHTMLToken.h (282226 => 282227)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612-branch/Source/WebCore/html/parser/AtomHTMLToken.h    2021-09-09 18:01:36 UTC (rev 282226)
+++ branches/safari-612-branch/Source/WebCore/html/parser/AtomHTMLToken.h       2021-09-09 18:04:27 UTC (rev 282227)
</span><span class="lines">@@ -26,6 +26,7 @@
</span><span class="cx"> 
</span><span class="cx"> #pragma once
</span><span class="cx"> 
</span><ins>+#include "HTMLAtomStringCache.h"
</ins><span class="cx"> #include "HTMLToken.h"
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="lines">@@ -202,11 +203,11 @@
</span><span class="cx">         if (attribute.name.isEmpty())
</span><span class="cx">             continue;
</span><span class="cx"> 
</span><del>-        AtomString localName(attribute.name);
</del><ins>+        auto localName = HTMLAtomStringCache::makeTagOrAttributeName(attribute.name);
</ins><span class="cx"> 
</span><span class="cx">         // FIXME: This is N^2 for the number of attributes.
</span><span class="cx">         if (!hasAttribute(m_attributes, localName))
</span><del>-            m_attributes.uncheckedAppend(Attribute(QualifiedName(nullAtom(), localName, nullAtom()), AtomString(attribute.value)));
</del><ins>+            m_attributes.uncheckedAppend(Attribute(QualifiedName(nullAtom(), localName, nullAtom()), HTMLAtomStringCache::makeAttributeValue(attribute.value)));
</ins><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -218,7 +219,7 @@
</span><span class="cx">         ASSERT_NOT_REACHED();
</span><span class="cx">         return;
</span><span class="cx">     case HTMLToken::DOCTYPE:
</span><del>-        m_name = AtomString(token.name());
</del><ins>+        m_name = HTMLAtomStringCache::makeTagOrAttributeName(token.name());
</ins><span class="cx">         m_doctypeData = token.releaseDoctypeData();
</span><span class="cx">         return;
</span><span class="cx">     case HTMLToken::EndOfFile:
</span><span class="lines">@@ -226,7 +227,7 @@
</span><span class="cx">     case HTMLToken::StartTag:
</span><span class="cx">     case HTMLToken::EndTag:
</span><span class="cx">         m_selfClosing = token.selfClosing();
</span><del>-        m_name = AtomString(token.name());
</del><ins>+        m_name = HTMLAtomStringCache::makeTagOrAttributeName(token.name());
</ins><span class="cx">         initializeAttributes(token.attributes());
</span><span class="cx">         return;
</span><span class="cx">     case HTMLToken::Comment:
</span></span></pre></div>
<a id="branchessafari612branchSourceWebCorehtmlparserHTMLAtomStringCachecpp"></a>
<div class="addfile"><h4>Added: branches/safari-612-branch/Source/WebCore/html/parser/HTMLAtomStringCache.cpp (0 => 282227)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612-branch/Source/WebCore/html/parser/HTMLAtomStringCache.cpp                            (rev 0)
+++ branches/safari-612-branch/Source/WebCore/html/parser/HTMLAtomStringCache.cpp       2021-09-09 18:04:27 UTC (rev 282227)
</span><span class="lines">@@ -0,0 +1,37 @@
</span><ins>+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "HTMLAtomStringCache.h"
+
+namespace WebCore {
+
+HTMLAtomStringCache::Cache& HTMLAtomStringCache::cache(Type type)
+{
+    static MainThreadNeverDestroyed<Cache> caches[2];
+    return caches[static_cast<size_t>(type)].get();
+}
+
+} // namespace WebCore
</ins></span></pre></div>
<a id="branchessafari612branchSourceWebCorehtmlparserHTMLAtomStringCacheh"></a>
<div class="addfile"><h4>Added: branches/safari-612-branch/Source/WebCore/html/parser/HTMLAtomStringCache.h (0 => 282227)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612-branch/Source/WebCore/html/parser/HTMLAtomStringCache.h                              (rev 0)
+++ branches/safari-612-branch/Source/WebCore/html/parser/HTMLAtomStringCache.h 2021-09-09 18:04:27 UTC (rev 282227)
</span><span class="lines">@@ -0,0 +1,94 @@
</span><ins>+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <wtf/NeverDestroyed.h>
+#include <wtf/Vector.h>
+#include <wtf/text/AtomString.h>
+
+namespace WebCore {
+
+class HTMLAtomStringCache {
+public:
+    template<size_t inlineCapacity>
+    ALWAYS_INLINE static AtomString makeTagOrAttributeName(const Vector<UChar, inlineCapacity>& string)
+    {
+        return make<Type::TagOrAttributeName>(string);
+    }
+
+    template<size_t inlineCapacity>
+    ALWAYS_INLINE static AtomString makeAttributeValue(const Vector<UChar, inlineCapacity>& string)
+    {
+        return make<Type::AttributeValue>(string);
+    }
+
+    ALWAYS_INLINE static void clear()
+    {
+        // FIXME (webkit.org/b/230019): We should try to find more opportunities to clear this cache without hindering this performance optimization.
+        cache(Type::TagOrAttributeName).fill({ });
+        cache(Type::AttributeValue).fill({ });
+    }
+
+private:
+    enum class Type : bool { TagOrAttributeName, AttributeValue };
+
+    template<HTMLAtomStringCache::Type type, size_t inlineCapacity>
+    ALWAYS_INLINE static AtomString make(const Vector<UChar, inlineCapacity>& string)
+    {
+        if (string.isEmpty())
+            return emptyAtom();
+
+        auto length = string.size();
+        if (length > maxStringLengthForCache)
+            return AtomString(string);
+
+        auto firstCharacter = string[0];
+        auto lastCharacter = string[length - 1];
+        auto& slot = cacheSlot(type, firstCharacter, lastCharacter, length);
+        if (!equal(slot.impl(), string.data(), length)) {
+            AtomString result(string);
+            slot = result;
+            return result;
+        }
+
+        return slot;
+    }
+
+    ALWAYS_INLINE static AtomString& cacheSlot(Type type, UChar firstCharacter, UChar lastCharacter, UChar length)
+    {
+        unsigned hash = (firstCharacter << 6) ^ ((lastCharacter << 14) ^ firstCharacter);
+        hash += (hash >> 14) + (length << 14);
+        hash ^= hash << 14;
+        return cache(type)[(hash + (hash >> 6)) % capacity];
+    }
+
+    static constexpr auto maxStringLengthForCache = 36;
+    static constexpr auto capacity = 512;
+    using Cache = std::array<AtomString, capacity>;
+    static Cache& cache(Type);
+};
+
+} // namespace WebCore
</ins></span></pre></div>
<a id="branchessafari612branchSourceWebCorepageMemoryReleasecpp"></a>
<div class="modfile"><h4>Modified: branches/safari-612-branch/Source/WebCore/page/MemoryRelease.cpp (282226 => 282227)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612-branch/Source/WebCore/page/MemoryRelease.cpp 2021-09-09 18:01:36 UTC (rev 282226)
+++ branches/safari-612-branch/Source/WebCore/page/MemoryRelease.cpp    2021-09-09 18:04:27 UTC (rev 282227)
</span><span class="lines">@@ -38,6 +38,7 @@
</span><span class="cx"> #include "FontCache.h"
</span><span class="cx"> #include "Frame.h"
</span><span class="cx"> #include "GCController.h"
</span><ins>+#include "HTMLAtomStringCache.h"
</ins><span class="cx"> #include "HTMLMediaElement.h"
</span><span class="cx"> #include "InlineStyleSheetOwner.h"
</span><span class="cx"> #include "InspectorInstrumentation.h"
</span><span class="lines">@@ -85,6 +86,7 @@
</span><span class="cx">         MemoryCache::singleton().pruneDeadResourcesToSize(0);
</span><span class="cx"> 
</span><span class="cx">     InlineStyleSheetOwner::clearCache();
</span><ins>+    HTMLAtomStringCache::clear();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static void releaseCriticalMemory(Synchronous synchronous, MaintainBackForwardCache maintainBackForwardCache, MaintainMemoryCache maintainMemoryCache)
</span></span></pre></div>
<a id="branchessafari612branchSourceWebCorepagecocoaMemoryReleaseCocoamm"></a>
<div class="modfile"><h4>Modified: branches/safari-612-branch/Source/WebCore/page/cocoa/MemoryReleaseCocoa.mm (282226 => 282227)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612-branch/Source/WebCore/page/cocoa/MemoryReleaseCocoa.mm       2021-09-09 18:01:36 UTC (rev 282226)
+++ branches/safari-612-branch/Source/WebCore/page/cocoa/MemoryReleaseCocoa.mm  2021-09-09 18:04:27 UTC (rev 282227)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> 
</span><span class="cx"> #import "FontFamilySpecificationCoreText.h"
</span><span class="cx"> #import "GCController.h"
</span><ins>+#import "HTMLAtomStringCache.h"
</ins><span class="cx"> #import "IOSurfacePool.h"
</span><span class="cx"> #import "LayerPool.h"
</span><span class="cx"> #import "LocaleCocoa.h"
</span><span class="lines">@@ -83,7 +84,6 @@
</span><span class="cx"> 
</span><span class="cx"> void jettisonExpensiveObjectsOnTopLevelNavigation()
</span><span class="cx"> {
</span><del>-#if PLATFORM(IOS_FAMILY)
</del><span class="cx">     // Protect against doing excessive jettisoning during repeated navigations.
</span><span class="cx">     const auto minimumTimeSinceNavigation = 2_s;
</span><span class="cx"> 
</span><span class="lines">@@ -95,10 +95,13 @@
</span><span class="cx">     if (!shouldJettison)
</span><span class="cx">         return;
</span><span class="cx"> 
</span><ins>+#if PLATFORM(IOS_FAMILY)
</ins><span class="cx">     // Throw away linked JS code. Linked code is tied to a global object and is not reusable.
</span><span class="cx">     // The immediate memory savings outweigh the cost of recompilation in case we go back again.
</span><span class="cx">     GCController::singleton().deleteAllLinkedCode(JSC::DeleteAllCodeIfNotCollecting);
</span><span class="cx"> #endif
</span><ins>+
+    HTMLAtomStringCache::clear();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void registerMemoryReleaseNotifyCallbacks()
</span></span></pre>
</div>
</div>

</body>
</html>