<!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>[172744] 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/172744">172744</a></dd>
<dt>Author</dt> <dd>commit-queue@webkit.org</dd>
<dt>Date</dt> <dd>2014-08-18 22:10:23 -0700 (Mon, 18 Aug 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>Unreviewed, rolling out <a href="http://trac.webkit.org/projects/webkit/changeset/172736">r172736</a>.
https://bugs.webkit.org/show_bug.cgi?id=136060

Caused 14% PLT regressions (Requested by rniwa on #webkit).

Reverted changeset:

&quot;Remove PurgeableBuffer since it is not very useful any more&quot;
https://bugs.webkit.org/show_bug.cgi?id=135939
http://trac.webkit.org/changeset/172736</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWTFChangeLog">trunk/Source/WTF/ChangeLog</a></li>
<li><a href="#trunkSourceWTFwtfPlatformh">trunk/Source/WTF/wtf/Platform.h</a></li>
<li><a href="#trunkSourceWTFwtfVMTagsh">trunk/Source/WTF/wtf/VMTags.h</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreWebCorexcodeprojprojectpbxproj">trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceWebCoreinspectorInspectorPageAgentcpp">trunk/Source/WebCore/inspector/InspectorPageAgent.cpp</a></li>
<li><a href="#trunkSourceWebCoreloaderDocumentLoadercpp">trunk/Source/WebCore/loader/DocumentLoader.cpp</a></li>
<li><a href="#trunkSourceWebCoreloaderResourceBuffercpp">trunk/Source/WebCore/loader/ResourceBuffer.cpp</a></li>
<li><a href="#trunkSourceWebCoreloaderResourceBufferh">trunk/Source/WebCore/loader/ResourceBuffer.h</a></li>
<li><a href="#trunkSourceWebCoreloaderSubresourceLoadercpp">trunk/Source/WebCore/loader/SubresourceLoader.cpp</a></li>
<li><a href="#trunkSourceWebCoreloadercacheCachedCSSStyleSheetcpp">trunk/Source/WebCore/loader/cache/CachedCSSStyleSheet.cpp</a></li>
<li><a href="#trunkSourceWebCoreloadercacheCachedCSSStyleSheeth">trunk/Source/WebCore/loader/cache/CachedCSSStyleSheet.h</a></li>
<li><a href="#trunkSourceWebCoreloadercacheCachedImagecpp">trunk/Source/WebCore/loader/cache/CachedImage.cpp</a></li>
<li><a href="#trunkSourceWebCoreloadercacheCachedImageh">trunk/Source/WebCore/loader/cache/CachedImage.h</a></li>
<li><a href="#trunkSourceWebCoreloadercacheCachedResourcecpp">trunk/Source/WebCore/loader/cache/CachedResource.cpp</a></li>
<li><a href="#trunkSourceWebCoreloadercacheCachedResourceh">trunk/Source/WebCore/loader/cache/CachedResource.h</a></li>
<li><a href="#trunkSourceWebCoreloadercacheCachedScriptcpp">trunk/Source/WebCore/loader/cache/CachedScript.cpp</a></li>
<li><a href="#trunkSourceWebCoreloadercacheCachedScripth">trunk/Source/WebCore/loader/cache/CachedScript.h</a></li>
<li><a href="#trunkSourceWebCoreloadercacheMemoryCachecpp">trunk/Source/WebCore/loader/cache/MemoryCache.cpp</a></li>
<li><a href="#trunkSourceWebCoreloadercacheMemoryCacheh">trunk/Source/WebCore/loader/cache/MemoryCache.h</a></li>
<li><a href="#trunkSourceWebCoreplatformSharedBuffercpp">trunk/Source/WebCore/platform/SharedBuffer.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformSharedBufferh">trunk/Source/WebCore/platform/SharedBuffer.h</a></li>
<li><a href="#trunkSourceWebCoreplatformcfSharedBufferCFcpp">trunk/Source/WebCore/platform/cf/SharedBufferCF.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformmacSharedBufferMacmm">trunk/Source/WebCore/platform/mac/SharedBufferMac.mm</a></li>
<li><a href="#trunkSourceWebCoreplatformsoupSharedBufferSoupcpp">trunk/Source/WebCore/platform/soup/SharedBufferSoup.cpp</a></li>
<li><a href="#trunkSourceWebKitmacChangeLog">trunk/Source/WebKit/mac/ChangeLog</a></li>
<li><a href="#trunkSourceWebKitmacMiscWebCachemm">trunk/Source/WebKit/mac/Misc/WebCache.mm</a></li>
<li><a href="#trunkSourceWebKitwinChangeLog">trunk/Source/WebKit/win/ChangeLog</a></li>
<li><a href="#trunkSourceWebKitwinWebCachecpp">trunk/Source/WebKit/win/WebCache.cpp</a></li>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2WebProcessWebProcesscpp">trunk/Source/WebKit2/WebProcess/WebProcess.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreplatformPurgePriorityh">trunk/Source/WebCore/platform/PurgePriority.h</a></li>
<li><a href="#trunkSourceWebCoreplatformPurgeableBufferh">trunk/Source/WebCore/platform/PurgeableBuffer.h</a></li>
<li><a href="#trunkSourceWebCoreplatformmacPurgeableBufferMaccpp">trunk/Source/WebCore/platform/mac/PurgeableBufferMac.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWTFChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/ChangeLog (172743 => 172744)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/ChangeLog        2014-08-19 05:04:07 UTC (rev 172743)
+++ trunk/Source/WTF/ChangeLog        2014-08-19 05:10:23 UTC (rev 172744)
</span><span class="lines">@@ -1,3 +1,16 @@
</span><ins>+2014-08-18  Commit Queue  &lt;commit-queue@webkit.org&gt;
+
+        Unreviewed, rolling out r172736.
+        https://bugs.webkit.org/show_bug.cgi?id=136060
+
+        Caused 14% PLT regressions (Requested by rniwa on #webkit).
+
+        Reverted changeset:
+
+        &quot;Remove PurgeableBuffer since it is not very useful any more&quot;
+        https://bugs.webkit.org/show_bug.cgi?id=135939
+        http://trac.webkit.org/changeset/172736
+
</ins><span class="cx"> 2014-08-18  Pratik Solanki  &lt;psolanki@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Remove PurgeableBuffer since it is not very useful any more
</span></span></pre></div>
<a id="trunkSourceWTFwtfPlatformh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/Platform.h (172743 => 172744)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/Platform.h        2014-08-19 05:04:07 UTC (rev 172743)
+++ trunk/Source/WTF/wtf/Platform.h        2014-08-19 05:10:23 UTC (rev 172744)
</span><span class="lines">@@ -490,6 +490,10 @@
</span><span class="cx"> 
</span><span class="cx"> #endif /* PLATFORM(MAC) */
</span><span class="cx"> 
</span><ins>+#if OS(DARWIN) &amp;&amp; !PLATFORM(GTK)
+#define ENABLE_PURGEABLE_MEMORY 1
+#endif
+
</ins><span class="cx"> #if PLATFORM(IOS)
</span><span class="cx"> 
</span><span class="cx"> #define DONT_FINALIZE_ON_MAIN_THREAD 1
</span></span></pre></div>
<a id="trunkSourceWTFwtfVMTagsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/VMTags.h (172743 => 172744)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/VMTags.h        2014-08-19 05:04:07 UTC (rev 172743)
+++ trunk/Source/WTF/wtf/VMTags.h        2014-08-19 05:10:23 UTC (rev 172744)
</span><span class="lines">@@ -56,12 +56,19 @@
</span><span class="cx"> #define VM_TAG_FOR_COLLECTOR_MEMORY VM_MAKE_TAG(63)
</span><span class="cx"> #endif // defined(VM_MEMORY_JAVASCRIPT_CORE)
</span><span class="cx"> 
</span><ins>+#if defined(VM_MEMORY_WEBCORE_PURGEABLE_BUFFERS)
+#define VM_TAG_FOR_WEBCORE_PURGEABLE_MEMORY VM_MAKE_TAG(VM_MEMORY_WEBCORE_PURGEABLE_BUFFERS)
+#else
+#define VM_TAG_FOR_WEBCORE_PURGEABLE_MEMORY VM_MAKE_TAG(69)
+#endif // defined(VM_MEMORY_WEBCORE_PURGEABLE_BUFFERS)
+
</ins><span class="cx"> #else // OS(DARWIN)
</span><span class="cx"> 
</span><span class="cx"> #define VM_TAG_FOR_TCMALLOC_MEMORY -1
</span><span class="cx"> #define VM_TAG_FOR_COLLECTOR_MEMORY -1
</span><span class="cx"> #define VM_TAG_FOR_EXECUTABLEALLOCATOR_MEMORY -1
</span><span class="cx"> #define VM_TAG_FOR_REGISTERFILE_MEMORY -1
</span><ins>+#define VM_TAG_FOR_WEBCORE_PURGEABLE_MEMORY -1
</ins><span class="cx"> 
</span><span class="cx"> #endif // OS(DARWIN)
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (172743 => 172744)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2014-08-19 05:04:07 UTC (rev 172743)
+++ trunk/Source/WebCore/ChangeLog        2014-08-19 05:10:23 UTC (rev 172744)
</span><span class="lines">@@ -1,3 +1,16 @@
</span><ins>+2014-08-18  Commit Queue  &lt;commit-queue@webkit.org&gt;
+
+        Unreviewed, rolling out r172736.
+        https://bugs.webkit.org/show_bug.cgi?id=136060
+
+        Caused 14% PLT regressions (Requested by rniwa on #webkit).
+
+        Reverted changeset:
+
+        &quot;Remove PurgeableBuffer since it is not very useful any more&quot;
+        https://bugs.webkit.org/show_bug.cgi?id=135939
+        http://trac.webkit.org/changeset/172736
+
</ins><span class="cx"> 2014-08-18  Simon Fraser  &lt;simon.fraser@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Provide default implementations of all GraphicsLayerClient methods
</span></span></pre></div>
<a id="trunkSourceWebCoreWebCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (172743 => 172744)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2014-08-19 05:04:07 UTC (rev 172743)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2014-08-19 05:10:23 UTC (rev 172744)
</span><span class="lines">@@ -2430,6 +2430,7 @@
</span><span class="cx">                 7CE6CBFB187F370700D46BF5 /* FormatConverter.h in Headers */ = {isa = PBXBuildFile; fileRef = 7CE6CBFA187F370700D46BF5 /* FormatConverter.h */; };
</span><span class="cx">                 7CE6CBFD187F394900D46BF5 /* FormatConverter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7CE6CBFC187F394900D46BF5 /* FormatConverter.cpp */; };
</span><span class="cx">                 7D741BDA177226AA00859170 /* CSSValueKeywords.h in Copy Generated Headers */ = {isa = PBXBuildFile; fileRef = 6565814809D13043000E61D7 /* CSSValueKeywords.h */; };
</span><ins>+                7E33CD01127F340D00BE8F17 /* PurgePriority.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E33CD00127F340D00BE8F17 /* PurgePriority.h */; settings = {ATTRIBUTES = (Private, ); }; };
</ins><span class="cx">                 7E37EF2E1339208800B29250 /* SubresourceLoaderCF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7E37EF2D1339208800B29250 /* SubresourceLoaderCF.cpp */; };
</span><span class="cx">                 7E428CE513E3407F003B661C /* ResourceHandleIOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7E428CE413E3407F003B661C /* ResourceHandleIOS.mm */; };
</span><span class="cx">                 7E46F6FA1627A2CA00062223 /* JSOESElementIndexUint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7E46F6F81627A2C900062223 /* JSOESElementIndexUint.cpp */; };
</span><span class="lines">@@ -6187,6 +6188,8 @@
</span><span class="cx">                 E4D58EB817B4ED8900CBDCA8 /* StyleFontSizeFunctions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4D58EB617B4ED8900CBDCA8 /* StyleFontSizeFunctions.cpp */; };
</span><span class="cx">                 E4D58EB917B4ED8900CBDCA8 /* StyleFontSizeFunctions.h in Headers */ = {isa = PBXBuildFile; fileRef = E4D58EB717B4ED8900CBDCA8 /* StyleFontSizeFunctions.h */; };
</span><span class="cx">                 E4D58EBB17B8F12800CBDCA8 /* ElementTraversal.h in Headers */ = {isa = PBXBuildFile; fileRef = E4D58EBA17B8F12800CBDCA8 /* ElementTraversal.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><ins>+                E4D687770ED7AE3D006EA978 /* PurgeableBufferMac.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4D687760ED7AE3D006EA978 /* PurgeableBufferMac.cpp */; };
+                E4D687790ED7AE4F006EA978 /* PurgeableBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = E4D687780ED7AE4F006EA978 /* PurgeableBuffer.h */; };
</ins><span class="cx">                 E4D988B417BFD1F60084FB88 /* TextNodeTraversal.h in Headers */ = {isa = PBXBuildFile; fileRef = E4D988B317BFD1F60084FB88 /* TextNodeTraversal.h */; };
</span><span class="cx">                 E4D988B617BFEB210084FB88 /* TextNodeTraversal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4D988B517BFEB210084FB88 /* TextNodeTraversal.cpp */; };
</span><span class="cx">                 E4DEAA1717A93DC3000E0430 /* StyleResolveTree.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4DEAA1517A93DC3000E0430 /* StyleResolveTree.cpp */; };
</span><span class="lines">@@ -9583,6 +9586,7 @@
</span><span class="cx">                 7CE683461921821500F4D928 /* UserMessageHandlerDescriptorTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UserMessageHandlerDescriptorTypes.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 7CE6CBFA187F370700D46BF5 /* FormatConverter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FormatConverter.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 7CE6CBFC187F394900D46BF5 /* FormatConverter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FormatConverter.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                7E33CD00127F340D00BE8F17 /* PurgePriority.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PurgePriority.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 7E37EF2D1339208800B29250 /* SubresourceLoaderCF.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SubresourceLoaderCF.cpp; path = cf/SubresourceLoaderCF.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 7E428CE413E3407F003B661C /* ResourceHandleIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ResourceHandleIOS.mm; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 7E46F6F81627A2C900062223 /* JSOESElementIndexUint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSOESElementIndexUint.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -13704,6 +13708,8 @@
</span><span class="cx">                 E4D58EB617B4ED8900CBDCA8 /* StyleFontSizeFunctions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StyleFontSizeFunctions.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 E4D58EB717B4ED8900CBDCA8 /* StyleFontSizeFunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StyleFontSizeFunctions.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 E4D58EBA17B8F12800CBDCA8 /* ElementTraversal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ElementTraversal.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                E4D687760ED7AE3D006EA978 /* PurgeableBufferMac.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PurgeableBufferMac.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                E4D687780ED7AE4F006EA978 /* PurgeableBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PurgeableBuffer.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 E4D988B317BFD1F60084FB88 /* TextNodeTraversal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextNodeTraversal.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 E4D988B517BFEB210084FB88 /* TextNodeTraversal.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TextNodeTraversal.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 E4DEAA1517A93DC3000E0430 /* StyleResolveTree.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StyleResolveTree.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -16446,6 +16452,7 @@
</span><span class="cx">                                 BC94D1070C274F88006BC617 /* PlatformScreenMac.mm */,
</span><span class="cx">                                 29E4D8E016B0959800C84704 /* PlatformSpeechSynthesizerMac.mm */,
</span><span class="cx">                                 0081FEFE16B0A2B6008AAA7A /* PublicSuffixMac.mm */,
</span><ins>+                                E4D687760ED7AE3D006EA978 /* PurgeableBufferMac.cpp */,
</ins><span class="cx">                                 BCAE1FA512939DB7004CB026 /* ScrollAnimatorMac.h */,
</span><span class="cx">                                 BC51156D12B1749C00C96754 /* ScrollAnimatorMac.mm */,
</span><span class="cx">                                 BC8B853C0E7C7F1100AB6984 /* ScrollbarThemeMac.h */,
</span><span class="lines">@@ -21392,6 +21399,8 @@
</span><span class="cx">                                 ABC128760B33AA6D00C693D5 /* PopupMenuClient.h */,
</span><span class="cx">                                 BC3BE12A0E98092F00835588 /* PopupMenuStyle.h */,
</span><span class="cx">                                 0081FEFD16B0A244008AAA7A /* PublicSuffix.h */,
</span><ins>+                                E4D687780ED7AE4F006EA978 /* PurgeableBuffer.h */,
+                                7E33CD00127F340D00BE8F17 /* PurgePriority.h */,
</ins><span class="cx">                                 A72EA3BA1585CF55004FAA26 /* RefCountedSupplement.h */,
</span><span class="cx">                                 9831AE49154225A200FE2644 /* ReferrerPolicy.h */,
</span><span class="cx">                                 293EAE201356B32E0067ACF9 /* RuntimeApplicationChecks.cpp */,
</span><span class="lines">@@ -25572,6 +25581,8 @@
</span><span class="cx">                                 FF945ECC161F7F3600971BC8 /* PseudoElement.h in Headers */,
</span><span class="cx">                                 0081FF0016B0A2D3008AAA7A /* PublicSuffix.h in Headers */,
</span><span class="cx">                                 10FB084B14E15C7E00A3DB98 /* PublicURLManager.h in Headers */,
</span><ins>+                                E4D687790ED7AE4F006EA978 /* PurgeableBuffer.h in Headers */,
+                                7E33CD01127F340D00BE8F17 /* PurgePriority.h in Headers */,
</ins><span class="cx">                                 550A0BCA085F6039007353D6 /* QualifiedName.h in Headers */,
</span><span class="cx">                                 442AF7A9102CDDEA008FD4D3 /* QuickLook.h in Headers */,
</span><span class="cx">                                 072AE1E8183C0741000A5988 /* QuickTimePluginReplacement.h in Headers */,
</span><span class="lines">@@ -29072,6 +29083,7 @@
</span><span class="cx">                                 FF945ECB161F7F3600971BC8 /* PseudoElement.cpp in Sources */,
</span><span class="cx">                                 0081FEFF16B0A2B6008AAA7A /* PublicSuffixMac.mm in Sources */,
</span><span class="cx">                                 CDEE393717974259001D7580 /* PublicURLManager.cpp in Sources */,
</span><ins>+                                E4D687770ED7AE3D006EA978 /* PurgeableBufferMac.cpp in Sources */,
</ins><span class="cx">                                 550A0BC9085F6039007353D6 /* QualifiedName.cpp in Sources */,
</span><span class="cx">                                 442AF7AA102CDDEA008FD4D3 /* QuickLook.mm in Sources */,
</span><span class="cx">                                 072AE1E6183C0741000A5988 /* QuickTimePluginReplacement.mm in Sources */,
</span></span></pre></div>
<a id="trunkSourceWebCoreinspectorInspectorPageAgentcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/inspector/InspectorPageAgent.cpp (172743 => 172744)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/inspector/InspectorPageAgent.cpp        2014-08-19 05:04:07 UTC (rev 172743)
+++ trunk/Source/WebCore/inspector/InspectorPageAgent.cpp        2014-08-19 05:10:23 UTC (rev 172744)
</span><span class="lines">@@ -112,6 +112,17 @@
</span><span class="cx">         return true;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    if (cachedResource-&gt;isPurgeable()) {
+        // If the resource is purgeable then make it unpurgeable to get
+        // get its data. This might fail, in which case we return an
+        // empty String.
+        // FIXME: should we do something else in the case of a purged
+        // resource that informs the user why there is no data in the
+        // inspector?
+        if (!cachedResource-&gt;makePurgeable(false))
+            return false;
+    }
+
</ins><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreloaderDocumentLoadercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/loader/DocumentLoader.cpp (172743 => 172744)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/loader/DocumentLoader.cpp        2014-08-19 05:04:07 UTC (rev 172743)
+++ trunk/Source/WebCore/loader/DocumentLoader.cpp        2014-08-19 05:10:23 UTC (rev 172744)
</span><span class="lines">@@ -1093,6 +1093,11 @@
</span><span class="cx">     if (resource-&gt;type() == CachedResource::MainResource)
</span><span class="cx">         return 0;
</span><span class="cx"> 
</span><ins>+    // FIXME: This has the side effect of making the resource non-purgeable.
+    // It would be better if it didn't have this permanent effect.
+    if (!resource-&gt;makePurgeable(false))
+        return 0;
+
</ins><span class="cx">     ResourceBuffer* data = resource-&gt;resourceBuffer();
</span><span class="cx">     if (!data)
</span><span class="cx">         return 0;
</span></span></pre></div>
<a id="trunkSourceWebCoreloaderResourceBuffercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/loader/ResourceBuffer.cpp (172743 => 172744)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/loader/ResourceBuffer.cpp        2014-08-19 05:04:07 UTC (rev 172743)
+++ trunk/Source/WebCore/loader/ResourceBuffer.cpp        2014-08-19 05:10:23 UTC (rev 172744)
</span><span class="lines">@@ -26,6 +26,7 @@
</span><span class="cx"> #include &quot;config.h&quot;
</span><span class="cx"> #include &quot;ResourceBuffer.h&quot;
</span><span class="cx"> 
</span><ins>+#include &quot;PurgeableBuffer.h&quot;
</ins><span class="cx"> #include &quot;SharedBuffer.h&quot;
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="lines">@@ -112,6 +113,30 @@
</span><span class="cx">     return ResourceBuffer::adoptSharedBuffer(m_sharedBuffer-&gt;copy());
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool ResourceBuffer::hasPurgeableBuffer() const
+{
+    return m_sharedBuffer-&gt;hasPurgeableBuffer();
+}
+
+#if PLATFORM(IOS)
+void ResourceBuffer::setShouldUsePurgeableMemory(bool shouldUsePurgeableMemory)
+{
+    ASSERT(m_sharedBuffer);
+    sharedBuffer()-&gt;shouldUsePurgeableMemory(shouldUsePurgeableMemory);
+}
+#endif
+
+void ResourceBuffer::createPurgeableBuffer() const
+{
+    ASSERT(m_sharedBuffer);
+    sharedBuffer()-&gt;createPurgeableBuffer();
+}
+
+PassOwnPtr&lt;PurgeableBuffer&gt; ResourceBuffer::releasePurgeableBuffer()
+{
+    return m_sharedBuffer-&gt;releasePurgeableBuffer();
+}
+
</ins><span class="cx"> #if USE(CF)
</span><span class="cx"> RetainPtr&lt;CFDataRef&gt; ResourceBuffer::createCFData()
</span><span class="cx"> {
</span></span></pre></div>
<a id="trunkSourceWebCoreloaderResourceBufferh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/loader/ResourceBuffer.h (172743 => 172744)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/loader/ResourceBuffer.h        2014-08-19 05:04:07 UTC (rev 172743)
+++ trunk/Source/WebCore/loader/ResourceBuffer.h        2014-08-19 05:10:23 UTC (rev 172744)
</span><span class="lines">@@ -38,6 +38,7 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><ins>+class PurgeableBuffer;
</ins><span class="cx"> class SharedBuffer;
</span><span class="cx"> 
</span><span class="cx"> class ResourceBuffer : public RefCounted&lt;ResourceBuffer&gt; {
</span><span class="lines">@@ -68,6 +69,17 @@
</span><span class="cx"> #endif
</span><span class="cx">     PassRefPtr&lt;ResourceBuffer&gt; copy() const;
</span><span class="cx"> 
</span><ins>+    bool hasPurgeableBuffer() const;
+    void createPurgeableBuffer() const;
+
+#if PLATFORM(IOS)
+    // FIXME: Remove PLATFORM(IOS)-guard once we upstream the iOS changes to SharedBuffer.{cpp, h} and SharedBufferCF.cpp.
+    void setShouldUsePurgeableMemory(bool);
+#endif
+
+    // Ensure this buffer has no other clients before calling this.
+    PassOwnPtr&lt;PurgeableBuffer&gt; releasePurgeableBuffer();
+
</ins><span class="cx"> #if USE(FOUNDATION)
</span><span class="cx">     RetainPtr&lt;NSData&gt; createNSData();
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebCoreloaderSubresourceLoadercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/loader/SubresourceLoader.cpp (172743 => 172744)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/loader/SubresourceLoader.cpp        2014-08-19 05:04:07 UTC (rev 172743)
+++ trunk/Source/WebCore/loader/SubresourceLoader.cpp        2014-08-19 05:10:23 UTC (rev 172744)
</span><span class="lines">@@ -299,8 +299,12 @@
</span><span class="cx">     LOG(ResourceLoading, &quot;Received '%s'.&quot;, m_resource-&gt;url().string().latin1().data());
</span><span class="cx"> 
</span><span class="cx">     Ref&lt;SubresourceLoader&gt; protect(*this);
</span><ins>+
+#if PLATFORM(IOS)
+    if (resourceData())
+        resourceData()-&gt;setShouldUsePurgeableMemory(true);
+#endif
</ins><span class="cx">     CachedResourceHandle&lt;CachedResource&gt; protectResource(m_resource);
</span><del>-
</del><span class="cx">     m_state = Finishing;
</span><span class="cx">     m_resource-&gt;setLoadFinishTime(finishTime);
</span><span class="cx">     m_resource-&gt;finishLoading(resourceData());
</span></span></pre></div>
<a id="trunkSourceWebCoreloadercacheCachedCSSStyleSheetcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/loader/cache/CachedCSSStyleSheet.cpp (172743 => 172744)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/loader/cache/CachedCSSStyleSheet.cpp        2014-08-19 05:04:07 UTC (rev 172743)
+++ trunk/Source/WebCore/loader/cache/CachedCSSStyleSheet.cpp        2014-08-19 05:10:23 UTC (rev 172744)
</span><span class="lines">@@ -80,6 +80,8 @@
</span><span class="cx">     
</span><span class="cx"> const String CachedCSSStyleSheet::sheetText(bool enforceMIMEType, bool* hasValidMIMEType) const 
</span><span class="cx"> { 
</span><ins>+    ASSERT(!isPurgeable());
+
</ins><span class="cx">     if (!m_data || m_data-&gt;isEmpty() || !canUseSheet(enforceMIMEType, hasValidMIMEType))
</span><span class="cx">         return String();
</span><span class="cx">     
</span><span class="lines">@@ -146,6 +148,9 @@
</span><span class="cx">     m_parsedStyleSheetCache.clear();
</span><span class="cx"> 
</span><span class="cx">     setDecodedSize(0);
</span><ins>+
+    if (!MemoryCache::shouldMakeResourcePurgeableOnEviction() &amp;&amp; isSafeToMakePurgeable())
+        makePurgeable(true);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> PassRefPtr&lt;StyleSheetContents&gt; CachedCSSStyleSheet::restoreParsedStyleSheet(const CSSParserContext&amp; context)
</span></span></pre></div>
<a id="trunkSourceWebCoreloadercacheCachedCSSStyleSheeth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/loader/cache/CachedCSSStyleSheet.h (172743 => 172744)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/loader/cache/CachedCSSStyleSheet.h        2014-08-19 05:04:07 UTC (rev 172743)
+++ trunk/Source/WebCore/loader/cache/CachedCSSStyleSheet.h        2014-08-19 05:10:23 UTC (rev 172744)
</span><span class="lines">@@ -48,6 +48,7 @@
</span><span class="cx"> 
</span><span class="cx">     private:
</span><span class="cx">         bool canUseSheet(bool enforceMIMEType, bool* hasValidMIMEType) const;
</span><ins>+        virtual PurgePriority purgePriority() const override { return PurgeLast; }
</ins><span class="cx">         virtual bool mayTryReplaceEncodedData() const override { return true; }
</span><span class="cx"> 
</span><span class="cx">         virtual void didAddClient(CachedResourceClient*) override;
</span></span></pre></div>
<a id="trunkSourceWebCoreloadercacheCachedImagecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/loader/cache/CachedImage.cpp (172743 => 172744)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/loader/cache/CachedImage.cpp        2014-08-19 05:04:07 UTC (rev 172743)
+++ trunk/Source/WebCore/loader/cache/CachedImage.cpp        2014-08-19 05:10:23 UTC (rev 172744)
</span><span class="lines">@@ -192,6 +192,8 @@
</span><span class="cx"> 
</span><span class="cx"> Image* CachedImage::image()
</span><span class="cx"> {
</span><ins>+    ASSERT(!isPurgeable());
+
</ins><span class="cx">     if (errorOccurred() &amp;&amp; m_shouldPaintBrokenImage) {
</span><span class="cx">         // Returning the 1x broken image is non-ideal, but we cannot reliably access the appropriate
</span><span class="cx">         // deviceScaleFactor from here. It is critical that callers use CachedImage::brokenImage() 
</span><span class="lines">@@ -207,6 +209,8 @@
</span><span class="cx"> 
</span><span class="cx"> Image* CachedImage::imageForRenderer(const RenderObject* renderer)
</span><span class="cx"> {
</span><ins>+    ASSERT(!isPurgeable());
+
</ins><span class="cx">     if (errorOccurred() &amp;&amp; m_shouldPaintBrokenImage) {
</span><span class="cx">         // Returning the 1x broken image is non-ideal, but we cannot reliably access the appropriate
</span><span class="cx">         // deviceScaleFactor from here. It is critical that callers use CachedImage::brokenImage() 
</span><span class="lines">@@ -270,6 +274,8 @@
</span><span class="cx"> 
</span><span class="cx"> LayoutSize CachedImage::imageSizeForRenderer(const RenderObject* renderer, float multiplier, SizeType sizeType)
</span><span class="cx"> {
</span><ins>+    ASSERT(!isPurgeable());
+
</ins><span class="cx">     if (!m_image)
</span><span class="cx">         return LayoutSize();
</span><span class="cx"> 
</span><span class="lines">@@ -456,9 +462,13 @@
</span><span class="cx"> void CachedImage::destroyDecodedData()
</span><span class="cx"> {
</span><span class="cx">     bool canDeleteImage = !m_image || (m_image-&gt;hasOneRef() &amp;&amp; m_image-&gt;isBitmapImage());
</span><del>-    if (canDeleteImage &amp;&amp; !isLoading()) {
</del><ins>+    if (isSafeToMakePurgeable() &amp;&amp; canDeleteImage &amp;&amp; !isLoading()) {
+        // Image refs the data buffer so we should not make it purgeable while the image is alive. 
+        // Invoking addClient() will reconstruct the image object.
</ins><span class="cx">         m_image = 0;
</span><span class="cx">         setDecodedSize(0);
</span><ins>+        if (!MemoryCache::shouldMakeResourcePurgeableOnEviction())
+            makePurgeable(true);
</ins><span class="cx">     } else if (m_image &amp;&amp; !errorOccurred())
</span><span class="cx">         m_image-&gt;destroyDecodedData();
</span><span class="cx"> }
</span><span class="lines">@@ -514,6 +524,9 @@
</span><span class="cx">     if (!m_data)
</span><span class="cx">         return false;
</span><span class="cx"> 
</span><ins>+    if (isPurgeable())
+        return false;
+
</ins><span class="cx">     if (m_data-&gt;size() &lt; diskImageCache().minimumImageSize())
</span><span class="cx">         return false;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreloadercacheCachedImageh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/loader/cache/CachedImage.h (172743 => 172744)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/loader/cache/CachedImage.h        2014-08-19 05:04:07 UTC (rev 172743)
+++ trunk/Source/WebCore/loader/cache/CachedImage.h        2014-08-19 05:10:23 UTC (rev 172744)
</span><span class="lines">@@ -101,6 +101,7 @@
</span><span class="cx">     void clearImage();
</span><span class="cx">     // If not null, changeRect is the changed part of the image.
</span><span class="cx">     void notifyObservers(const IntRect* changeRect = 0);
</span><ins>+    virtual PurgePriority purgePriority() const override { return PurgeFirst; }
</ins><span class="cx">     void checkShouldPaintBrokenImage();
</span><span class="cx"> 
</span><span class="cx">     virtual void switchClientsToRevalidatedResource() override;
</span></span></pre></div>
<a id="trunkSourceWebCoreloadercacheCachedResourcecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/loader/cache/CachedResource.cpp (172743 => 172744)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/loader/cache/CachedResource.cpp        2014-08-19 05:04:07 UTC (rev 172743)
+++ trunk/Source/WebCore/loader/cache/CachedResource.cpp        2014-08-19 05:10:23 UTC (rev 172744)
</span><span class="lines">@@ -40,6 +40,7 @@
</span><span class="cx"> #include &quot;Logging.h&quot;
</span><span class="cx"> #include &quot;MemoryCache.h&quot;
</span><span class="cx"> #include &quot;PlatformStrategies.h&quot;
</span><ins>+#include &quot;PurgeableBuffer.h&quot;
</ins><span class="cx"> #include &quot;ResourceBuffer.h&quot;
</span><span class="cx"> #include &quot;ResourceHandle.h&quot;
</span><span class="cx"> #include &quot;ResourceLoadScheduler.h&quot;
</span><span class="lines">@@ -465,6 +466,8 @@
</span><span class="cx"> 
</span><span class="cx"> bool CachedResource::addClientToSet(CachedResourceClient* client)
</span><span class="cx"> {
</span><ins>+    ASSERT(!isPurgeable());
+
</ins><span class="cx">     if (m_preloadResult == PreloadNotReferenced) {
</span><span class="cx">         if (isLoaded())
</span><span class="cx">             m_preloadResult = PreloadReferencedWhileComplete;
</span><span class="lines">@@ -783,6 +786,64 @@
</span><span class="cx">     return false;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool CachedResource::isSafeToMakePurgeable() const
+{ 
+#if ENABLE(DISK_IMAGE_CACHE)
+    // It does not make sense to have a resource in the disk image cache
+    // (memory mapped on disk) and purgeable (in memory). So do not allow
+    // disk image cached resources to be purgeable.
+    if (isUsingDiskImageCache())
+        return false;
+#endif
+
+    return !hasClients() &amp;&amp; !m_proxyResource &amp;&amp; !m_resourceToRevalidate;
+}
+
+bool CachedResource::makePurgeable(bool purgeable) 
+{ 
+    if (purgeable) {
+        ASSERT(isSafeToMakePurgeable());
+
+        if (m_purgeableData) {
+            ASSERT(!m_data);
+            return true;
+        }
+        if (!m_data)
+            return false;
+        
+        m_data-&gt;createPurgeableBuffer();
+        if (!m_data-&gt;hasPurgeableBuffer())
+            return false;
+
+        m_purgeableData = m_data-&gt;releasePurgeableBuffer();
+        m_purgeableData-&gt;setPurgePriority(purgePriority());
+        m_purgeableData-&gt;makePurgeable(true);
+        m_data.clear();
+        return true;
+    }
+
+    if (!m_purgeableData)
+        return true;
+    ASSERT(!m_data);
+    ASSERT(!hasClients());
+
+    if (!m_purgeableData-&gt;makePurgeable(false))
+        return false; 
+
+    m_data = ResourceBuffer::adoptSharedBuffer(SharedBuffer::adoptPurgeableBuffer(m_purgeableData.release()));
+    return true;
+}
+
+bool CachedResource::isPurgeable() const
+{
+    return m_purgeableData &amp;&amp; m_purgeableData-&gt;isPurgeable();
+}
+
+bool CachedResource::wasPurged() const
+{
+    return m_purgeableData &amp;&amp; m_purgeableData-&gt;wasPurged();
+}
+
</ins><span class="cx"> unsigned CachedResource::overheadSize() const
</span><span class="cx"> {
</span><span class="cx">     static const int kAverageClientsHashMapSize = 384;
</span></span></pre></div>
<a id="trunkSourceWebCoreloadercacheCachedResourceh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/loader/cache/CachedResource.h (172743 => 172744)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/loader/cache/CachedResource.h        2014-08-19 05:04:07 UTC (rev 172743)
+++ trunk/Source/WebCore/loader/cache/CachedResource.h        2014-08-19 05:10:23 UTC (rev 172744)
</span><span class="lines">@@ -25,6 +25,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;CachePolicy.h&quot;
</span><span class="cx"> #include &quot;FrameLoaderTypes.h&quot;
</span><ins>+#include &quot;PurgePriority.h&quot;
</ins><span class="cx"> #include &quot;ResourceError.h&quot;
</span><span class="cx"> #include &quot;ResourceLoadPriority.h&quot;
</span><span class="cx"> #include &quot;ResourceLoaderOptions.h&quot;
</span><span class="lines">@@ -46,6 +47,7 @@
</span><span class="cx"> class CachedResourceHandleBase;
</span><span class="cx"> class CachedResourceLoader;
</span><span class="cx"> class InspectorResource;
</span><ins>+class PurgeableBuffer;
</ins><span class="cx"> class ResourceBuffer;
</span><span class="cx"> class SecurityOrigin;
</span><span class="cx"> class SharedBuffer;
</span><span class="lines">@@ -186,7 +188,7 @@
</span><span class="cx">     
</span><span class="cx">     void clearLoader();
</span><span class="cx"> 
</span><del>-    ResourceBuffer* resourceBuffer() const { return m_data.get(); }
</del><ins>+    ResourceBuffer* resourceBuffer() const { ASSERT(!m_purgeableData); return m_data.get(); }
</ins><span class="cx"> 
</span><span class="cx">     virtual void willSendRequest(ResourceRequest&amp;, const ResourceResponse&amp;) { m_requestedFromNetworkingLayer = true; }
</span><span class="cx">     virtual void responseReceived(const ResourceResponse&amp;);
</span><span class="lines">@@ -229,6 +231,14 @@
</span><span class="cx">     bool isCacheValidator() const { return m_resourceToRevalidate; }
</span><span class="cx">     CachedResource* resourceToRevalidate() const { return m_resourceToRevalidate; }
</span><span class="cx">     
</span><ins>+    bool isPurgeable() const;
+    bool wasPurged() const;
+    
+    // This is used by the archive machinery to get at a purged resource without
+    // triggering a load. We should make it protected again if we can find a
+    // better way to handle the archive case.
+    bool makePurgeable(bool purgeable);
+    
</ins><span class="cx">     // HTTP revalidation support methods for CachedResourceLoader.
</span><span class="cx">     void setResourceToRevalidate(CachedResource*);
</span><span class="cx">     virtual void switchClientsToRevalidatedResource();
</span><span class="lines">@@ -263,6 +273,8 @@
</span><span class="cx">     void setDecodedSize(unsigned);
</span><span class="cx">     void didAccessDecodedData(double timeStamp);
</span><span class="cx"> 
</span><ins>+    bool isSafeToMakePurgeable() const;
+    
</ins><span class="cx">     HashCountedSet&lt;CachedResourceClient*&gt; m_clients;
</span><span class="cx"> 
</span><span class="cx">     class CachedResourceCallback {
</span><span class="lines">@@ -290,6 +302,7 @@
</span><span class="cx">     double m_responseTimestamp;
</span><span class="cx"> 
</span><span class="cx">     RefPtr&lt;ResourceBuffer&gt; m_data;
</span><ins>+    OwnPtr&lt;PurgeableBuffer&gt; m_purgeableData;
</ins><span class="cx">     DeferrableOneShotTimer m_decodedDataDeletionTimer;
</span><span class="cx"> 
</span><span class="cx"> private:
</span><span class="lines">@@ -297,6 +310,7 @@
</span><span class="cx"> 
</span><span class="cx">     void decodedDataDeletionTimerFired();
</span><span class="cx"> 
</span><ins>+    virtual PurgePriority purgePriority() const { return PurgeDefault; }
</ins><span class="cx">     virtual bool mayTryReplaceEncodedData() const { return false; }
</span><span class="cx"> 
</span><span class="cx">     double currentAge() const;
</span></span></pre></div>
<a id="trunkSourceWebCoreloadercacheCachedScriptcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/loader/cache/CachedScript.cpp (172743 => 172744)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/loader/cache/CachedScript.cpp        2014-08-19 05:04:07 UTC (rev 172743)
+++ trunk/Source/WebCore/loader/cache/CachedScript.cpp        2014-08-19 05:10:23 UTC (rev 172744)
</span><span class="lines">@@ -71,6 +71,8 @@
</span><span class="cx"> 
</span><span class="cx"> const String&amp; CachedScript::script()
</span><span class="cx"> {
</span><ins>+    ASSERT(!isPurgeable());
+
</ins><span class="cx">     if (!m_script &amp;&amp; m_data) {
</span><span class="cx">         m_script = m_decoder-&gt;decodeAndFlush(m_data-&gt;data(), encodedSize());
</span><span class="cx">         setDecodedSize(m_script.sizeInBytes());
</span><span class="lines">@@ -91,6 +93,8 @@
</span><span class="cx"> {
</span><span class="cx">     m_script = String();
</span><span class="cx">     setDecodedSize(0);
</span><ins>+    if (!MemoryCache::shouldMakeResourcePurgeableOnEviction() &amp;&amp; isSafeToMakePurgeable())
+        makePurgeable(true);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(NOSNIFF)
</span></span></pre></div>
<a id="trunkSourceWebCoreloadercacheCachedScripth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/loader/cache/CachedScript.h (172743 => 172744)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/loader/cache/CachedScript.h        2014-08-19 05:04:07 UTC (rev 172743)
+++ trunk/Source/WebCore/loader/cache/CachedScript.h        2014-08-19 05:10:23 UTC (rev 172744)
</span><span class="lines">@@ -47,6 +47,7 @@
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     private:
</span><ins>+        virtual PurgePriority purgePriority() const override { return PurgeLast; }
</ins><span class="cx">         virtual bool mayTryReplaceEncodedData() const override { return true; }
</span><span class="cx"> 
</span><span class="cx">         virtual bool shouldIgnoreHTTPStatusCodeErrors() const override;
</span></span></pre></div>
<a id="trunkSourceWebCoreloadercacheMemoryCachecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/loader/cache/MemoryCache.cpp (172743 => 172744)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/loader/cache/MemoryCache.cpp        2014-08-19 05:04:07 UTC (rev 172743)
+++ trunk/Source/WebCore/loader/cache/MemoryCache.cpp        2014-08-19 05:10:23 UTC (rev 172744)
</span><span class="lines">@@ -212,6 +212,15 @@
</span><span class="cx"> #else
</span><span class="cx">     CachedResource* resource = resources.get(url);
</span><span class="cx"> #endif
</span><ins>+    bool wasPurgeable = MemoryCache::shouldMakeResourcePurgeableOnEviction() &amp;&amp; resource &amp;&amp; resource-&gt;isPurgeable();
+    if (resource &amp;&amp; !resource-&gt;makePurgeable(false)) {
+        ASSERT(!resource-&gt;hasClients());
+        evict(resource);
+        return 0;
+    }
+    // Add the size back since we had subtracted it when we marked the memory as purgeable.
+    if (wasPurgeable)
+        adjustSize(resource-&gt;hasClients(), resource-&gt;size());
</ins><span class="cx">     return resource;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -395,6 +404,19 @@
</span><span class="cx"> 
</span><span class="cx">     int size = m_allResources.size();
</span><span class="cx">  
</span><ins>+    // See if we have any purged resources we can evict.
+    for (int i = 0; i &lt; size; i++) {
+        CachedResource* current = m_allResources[i].m_tail;
+        while (current) {
+            CachedResource* prev = current-&gt;m_prevInAllResourcesList;
+            if (current-&gt;wasPurged()) {
+                ASSERT(!current-&gt;hasClients());
+                ASSERT(!current-&gt;isPreloaded());
+                evict(current);
+            }
+            current = prev;
+        }
+    }
</ins><span class="cx">     if (targetSize &amp;&amp; m_deadSize &lt;= targetSize)
</span><span class="cx">         return;
</span><span class="cx"> 
</span><span class="lines">@@ -430,7 +452,9 @@
</span><span class="cx">             CachedResourceHandle&lt;CachedResource&gt; previous = current-&gt;m_prevInAllResourcesList;
</span><span class="cx">             ASSERT(!previous || previous-&gt;inCache());
</span><span class="cx">             if (!current-&gt;hasClients() &amp;&amp; !current-&gt;isPreloaded() &amp;&amp; !current-&gt;isCacheValidator()) {
</span><del>-                evict(current);
</del><ins>+                if (!makeResourcePurgeable(current))
+                    evict(current);
+
</ins><span class="cx">                 if (targetSize &amp;&amp; m_deadSize &lt;= targetSize)
</span><span class="cx">                     return;
</span><span class="cx">             }
</span><span class="lines">@@ -497,6 +521,28 @@
</span><span class="cx">     prune();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool MemoryCache::makeResourcePurgeable(CachedResource* resource)
+{
+    if (!MemoryCache::shouldMakeResourcePurgeableOnEviction())
+        return false;
+
+    if (!resource-&gt;inCache())
+        return false;
+
+    if (resource-&gt;isPurgeable())
+        return true;
+
+    if (!resource-&gt;isSafeToMakePurgeable())
+        return false;
+
+    if (!resource-&gt;makePurgeable(true))
+        return false;
+
+    adjustSize(resource-&gt;hasClients(), -static_cast&lt;int&gt;(resource-&gt;size()));
+
+    return true;
+}
+
</ins><span class="cx"> void MemoryCache::evict(CachedResource* resource)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(WTF::isMainThread());
</span><span class="lines">@@ -521,6 +567,12 @@
</span><span class="cx">         // Remove from the appropriate LRU list.
</span><span class="cx">         removeFromLRUList(resource);
</span><span class="cx">         removeFromLiveDecodedResourcesList(resource);
</span><ins>+
+        // If the resource was purged, it means we had already decremented the size when we made the
+        // resource purgeable in makeResourcePurgeable(). So adjust the size if we are evicting a
+        // resource that was not marked as purgeable.
+        if (!MemoryCache::shouldMakeResourcePurgeableOnEviction() || !resource-&gt;isPurgeable())
+            adjustSize(resource-&gt;hasClients(), -static_cast&lt;int&gt;(resource-&gt;size()));
</ins><span class="cx">     } else
</span><span class="cx"> #if ENABLE(CACHE_PARTITIONING)
</span><span class="cx">         ASSERT(!resources.get(resource-&gt;url()) || resources.get(resource-&gt;url())-&gt;get(resource-&gt;cachePartition()) != resource);
</span><span class="lines">@@ -840,10 +892,15 @@
</span><span class="cx"> 
</span><span class="cx"> void MemoryCache::TypeStatistic::addResource(CachedResource* o)
</span><span class="cx"> {
</span><ins>+    bool purged = o-&gt;wasPurged();
+    bool purgeable = o-&gt;isPurgeable() &amp;&amp; !purged; 
+    int pageSize = (o-&gt;encodedSize() + o-&gt;overheadSize() + 4095) &amp; ~4095;
</ins><span class="cx">     count++;
</span><del>-    size += o-&gt;size();
</del><ins>+    size += purged ? 0 : o-&gt;size(); 
</ins><span class="cx">     liveSize += o-&gt;hasClients() ? o-&gt;size() : 0;
</span><span class="cx">     decodedSize += o-&gt;decodedSize();
</span><ins>+    purgeableSize += purgeable ? pageSize : 0;
+    purgedSize += purged ? pageSize : 0;
</ins><span class="cx"> #if ENABLE(DISK_IMAGE_CACHE)
</span><span class="cx">     // Only the data inside the resource was mapped, not the entire resource.
</span><span class="cx">     mappedSize += o-&gt;isUsingDiskImageCache() ? o-&gt;resourceBuffer()-&gt;sharedBuffer()-&gt;size() : 0;
</span><span class="lines">@@ -944,29 +1001,29 @@
</span><span class="cx"> {
</span><span class="cx">     Statistics s = getStatistics();
</span><span class="cx"> #if ENABLE(DISK_IMAGE_CACHE)
</span><del>-    printf(&quot;%-13s %-13s %-13s %-13s %-13s %-13s %-13s\n&quot;, &quot;&quot;, &quot;Count&quot;, &quot;Size&quot;, &quot;LiveSize&quot;, &quot;DecodedSize&quot;, &quot;Mapped&quot;, &quot;\&quot;Real\&quot;&quot;);
</del><ins>+    printf(&quot;%-13s %-13s %-13s %-13s %-13s %-13s %-13s %-13s %-13s\n&quot;, &quot;&quot;, &quot;Count&quot;, &quot;Size&quot;, &quot;LiveSize&quot;, &quot;DecodedSize&quot;, &quot;PurgeableSize&quot;, &quot;PurgedSize&quot;, &quot;Mapped&quot;, &quot;\&quot;Real\&quot;&quot;);
+    printf(&quot;%-13s %-13s %-13s %-13s %-13s %-13s %-13s %-13s %-13s\n&quot;, &quot;-------------&quot;, &quot;-------------&quot;, &quot;-------------&quot;, &quot;-------------&quot;, &quot;-------------&quot;, &quot;-------------&quot;, &quot;-------------&quot;, &quot;-------------&quot;, &quot;-------------&quot;);
+    printf(&quot;%-13s %13d %13d %13d %13d %13d %13d %13d %13d\n&quot;, &quot;Images&quot;, s.images.count, s.images.size, s.images.liveSize, s.images.decodedSize, s.images.purgeableSize, s.images.purgedSize, s.images.mappedSize, s.images.size - s.images.mappedSize);
+#else
+    printf(&quot;%-13s %-13s %-13s %-13s %-13s %-13s %-13s\n&quot;, &quot;&quot;, &quot;Count&quot;, &quot;Size&quot;, &quot;LiveSize&quot;, &quot;DecodedSize&quot;, &quot;PurgeableSize&quot;, &quot;PurgedSize&quot;);
</ins><span class="cx">     printf(&quot;%-13s %-13s %-13s %-13s %-13s %-13s %-13s\n&quot;, &quot;-------------&quot;, &quot;-------------&quot;, &quot;-------------&quot;, &quot;-------------&quot;, &quot;-------------&quot;, &quot;-------------&quot;, &quot;-------------&quot;);
</span><del>-    printf(&quot;%-13s %13d %13d %13d %13d %13d %13d\n&quot;, &quot;Images&quot;, s.images.count, s.images.size, s.images.liveSize, s.images.decodedSize, s.images.mappedSize, s.images.size - s.images.mappedSize);
-#else
-    printf(&quot;%-13s %-13s %-13s %-13s %-13s\n&quot;, &quot;&quot;, &quot;Count&quot;, &quot;Size&quot;, &quot;LiveSize&quot;, &quot;DecodedSize&quot;);
-    printf(&quot;%-13s %-13s %-13s %-13s %-13s\n&quot;, &quot;-------------&quot;, &quot;-------------&quot;, &quot;-------------&quot;, &quot;-------------&quot;, &quot;-------------&quot;);
-    printf(&quot;%-13s %13d %13d %13d %13d\n&quot;, &quot;Images&quot;, s.images.count, s.images.size, s.images.liveSize, s.images.decodedSize);
</del><ins>+    printf(&quot;%-13s %13d %13d %13d %13d %13d %13d\n&quot;, &quot;Images&quot;, s.images.count, s.images.size, s.images.liveSize, s.images.decodedSize, s.images.purgeableSize, s.images.purgedSize);
</ins><span class="cx"> #endif
</span><del>-    printf(&quot;%-13s %13d %13d %13d %13d\n&quot;, &quot;CSS&quot;, s.cssStyleSheets.count, s.cssStyleSheets.size, s.cssStyleSheets.liveSize, s.cssStyleSheets.decodedSize);
</del><ins>+    printf(&quot;%-13s %13d %13d %13d %13d %13d %13d\n&quot;, &quot;CSS&quot;, s.cssStyleSheets.count, s.cssStyleSheets.size, s.cssStyleSheets.liveSize, s.cssStyleSheets.decodedSize, s.cssStyleSheets.purgeableSize, s.cssStyleSheets.purgedSize);
</ins><span class="cx"> #if ENABLE(XSLT)
</span><del>-    printf(&quot;%-13s %13d %13d %13d %13d\n&quot;, &quot;XSL&quot;, s.xslStyleSheets.count, s.xslStyleSheets.size, s.xslStyleSheets.liveSize, s.xslStyleSheets.decodedSize);
</del><ins>+    printf(&quot;%-13s %13d %13d %13d %13d %13d %13d\n&quot;, &quot;XSL&quot;, s.xslStyleSheets.count, s.xslStyleSheets.size, s.xslStyleSheets.liveSize, s.xslStyleSheets.decodedSize, s.xslStyleSheets.purgeableSize, s.xslStyleSheets.purgedSize);
</ins><span class="cx"> #endif
</span><del>-    printf(&quot;%-13s %13d %13d %13d %13d\n&quot;, &quot;JavaScript&quot;, s.scripts.count, s.scripts.size, s.scripts.liveSize, s.scripts.decodedSize);
-    printf(&quot;%-13s %13d %13d %13d %13d\n&quot;, &quot;Fonts&quot;, s.fonts.count, s.fonts.size, s.fonts.liveSize, s.fonts.decodedSize);
-    printf(&quot;%-13s %-13s %-13s %-13s %-13s\n\n&quot;, &quot;-------------&quot;, &quot;-------------&quot;, &quot;-------------&quot;, &quot;-------------&quot;, &quot;-------------&quot;);
</del><ins>+    printf(&quot;%-13s %13d %13d %13d %13d %13d %13d\n&quot;, &quot;JavaScript&quot;, s.scripts.count, s.scripts.size, s.scripts.liveSize, s.scripts.decodedSize, s.scripts.purgeableSize, s.scripts.purgedSize);
+    printf(&quot;%-13s %13d %13d %13d %13d %13d %13d\n&quot;, &quot;Fonts&quot;, s.fonts.count, s.fonts.size, s.fonts.liveSize, s.fonts.decodedSize, s.fonts.purgeableSize, s.fonts.purgedSize);
+    printf(&quot;%-13s %-13s %-13s %-13s %-13s %-13s %-13s\n\n&quot;, &quot;-------------&quot;, &quot;-------------&quot;, &quot;-------------&quot;, &quot;-------------&quot;, &quot;-------------&quot;, &quot;-------------&quot;, &quot;-------------&quot;);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void MemoryCache::dumpLRULists(bool includeLive) const
</span><span class="cx"> {
</span><span class="cx"> #if ENABLE(DISK_IMAGE_CACHE)
</span><del>-    printf(&quot;LRU-SP lists in eviction order (Kilobytes decoded, Kilobytes encoded, Access count, Referenced, isMemoryMapped):\n&quot;);
</del><ins>+    printf(&quot;LRU-SP lists in eviction order (Kilobytes decoded, Kilobytes encoded, Access count, Referenced, isPurgeable, wasPurged, isMemoryMapped):\n&quot;);
</ins><span class="cx"> #else
</span><del>-    printf(&quot;LRU-SP lists in eviction order (Kilobytes decoded, Kilobytes encoded, Access count, Referenced):\n&quot;);
</del><ins>+    printf(&quot;LRU-SP lists in eviction order (Kilobytes decoded, Kilobytes encoded, Access count, Referenced, isPurgeable, wasPurged):\n&quot;);
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     int size = m_allResources.size();
</span><span class="lines">@@ -977,9 +1034,9 @@
</span><span class="cx">             CachedResource* prev = current-&gt;m_prevInAllResourcesList;
</span><span class="cx">             if (includeLive || !current-&gt;hasClients())
</span><span class="cx"> #if ENABLE(DISK_IMAGE_CACHE)
</span><del>-                printf(&quot;(%.1fK, %.1fK, %uA, %dR, %d); &quot;, current-&gt;decodedSize() / 1024.0f, (current-&gt;encodedSize() + current-&gt;overheadSize()) / 1024.0f, current-&gt;accessCount(), current-&gt;hasClients(), current-&gt;isUsingDiskImageCache());
</del><ins>+                printf(&quot;(%.1fK, %.1fK, %uA, %dR, %d, %d, %d); &quot;, current-&gt;decodedSize() / 1024.0f, (current-&gt;encodedSize() + current-&gt;overheadSize()) / 1024.0f, current-&gt;accessCount(), current-&gt;hasClients(), current-&gt;isPurgeable(), current-&gt;wasPurged(), current-&gt;isUsingDiskImageCache());
</ins><span class="cx"> #else
</span><del>-                printf(&quot;(%.1fK, %.1fK, %uA, %dR); &quot;, current-&gt;decodedSize() / 1024.0f, (current-&gt;encodedSize() + current-&gt;overheadSize()) / 1024.0f, current-&gt;accessCount(), current-&gt;hasClients());
</del><ins>+                printf(&quot;(%.1fK, %.1fK, %uA, %dR, %d, %d); &quot;, current-&gt;decodedSize() / 1024.0f, (current-&gt;encodedSize() + current-&gt;overheadSize()) / 1024.0f, current-&gt;accessCount(), current-&gt;hasClients(), current-&gt;isPurgeable(), current-&gt;wasPurged());
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">             current = prev;
</span></span></pre></div>
<a id="trunkSourceWebCoreloadercacheMemoryCacheh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/loader/cache/MemoryCache.h (172743 => 172744)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/loader/cache/MemoryCache.h        2014-08-19 05:04:07 UTC (rev 172743)
+++ trunk/Source/WebCore/loader/cache/MemoryCache.h        2014-08-19 05:10:23 UTC (rev 172744)
</span><span class="lines">@@ -61,6 +61,22 @@
</span><span class="cx"> // -------|-----+++++++++++++++|
</span><span class="cx"> // -------|-----+++++++++++++++|+++++
</span><span class="cx"> 
</span><ins>+// The behavior of the cache changes in the following way if shouldMakeResourcePurgeableOnEviction
+// returns true.
+//
+// 1. Dead resources in the cache are kept in non-purgeable memory.
+// 2. When we prune dead resources, instead of freeing them, we mark their memory as purgeable and
+//    keep the resources until the kernel reclaims the purgeable memory.
+//
+// By leaving the in-cache dead resources in dirty resident memory, we decrease the likelihood of
+// the kernel claiming that memory and forcing us to refetch the resource (for example when a user
+// presses back).
+//
+// And by having an unbounded number of resource objects using purgeable memory, we can use as much
+// memory as is available on the machine. The trade-off here is that the CachedResource object (and
+// its member variables) are allocated in non-purgeable TC-malloc'd memory so we would see slightly
+// more memory use due to this.
+
</ins><span class="cx"> class MemoryCache {
</span><span class="cx">     WTF_MAKE_NONCOPYABLE(MemoryCache); WTF_MAKE_FAST_ALLOCATED;
</span><span class="cx"> public:
</span><span class="lines">@@ -85,21 +101,14 @@
</span><span class="cx">         int size;
</span><span class="cx">         int liveSize;
</span><span class="cx">         int decodedSize;
</span><ins>+        int purgeableSize;
+        int purgedSize;
</ins><span class="cx"> #if ENABLE(DISK_IMAGE_CACHE)
</span><span class="cx">         int mappedSize;
</span><ins>+        TypeStatistic() : count(0), size(0), liveSize(0), decodedSize(0), purgeableSize(0), purgedSize(0), mappedSize(0) { }
+#else
+        TypeStatistic() : count(0), size(0), liveSize(0), decodedSize(0), purgeableSize(0), purgedSize(0) { }
</ins><span class="cx"> #endif
</span><del>-
-        TypeStatistic()
-            : count(0)
-            , size(0)
-            , liveSize(0)
-            , decodedSize(0)
-#if ENABLE(DISK_IMAGE_CACHE)
-            , mappedSize(0)
-#endif
-        {
-        }
-
</del><span class="cx">         void addResource(CachedResource*);
</span><span class="cx">     };
</span><span class="cx">     
</span><span class="lines">@@ -158,6 +167,8 @@
</span><span class="cx">     void addToLiveResourcesSize(CachedResource*);
</span><span class="cx">     void removeFromLiveResourcesSize(CachedResource*);
</span><span class="cx"> 
</span><ins>+    static bool shouldMakeResourcePurgeableOnEviction();
+
</ins><span class="cx"> #if ENABLE(DISK_IMAGE_CACHE)
</span><span class="cx">     void flushCachedImagesToDisk(); // Flush encoded data from resources still referenced by web pages.
</span><span class="cx"> #endif
</span><span class="lines">@@ -211,6 +222,7 @@
</span><span class="cx">     unsigned liveCapacity() const;
</span><span class="cx">     unsigned deadCapacity() const;
</span><span class="cx"> 
</span><ins>+    bool makeResourcePurgeable(CachedResource*);
</ins><span class="cx">     void evict(CachedResource*);
</span><span class="cx"> 
</span><span class="cx">     CachedResource* resourceForRequestImpl(const ResourceRequest&amp;, CachedResourceMap&amp;);
</span><span class="lines">@@ -246,6 +258,15 @@
</span><span class="cx">     SessionCachedResourceMap m_sessionResources;
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+inline bool MemoryCache::shouldMakeResourcePurgeableOnEviction()
+{
+#if PLATFORM(IOS)
+    return true;
+#else
+    return false;
+#endif
+}
+
</ins><span class="cx"> // Function to obtain the global cache.
</span><span class="cx"> MemoryCache* memoryCache();
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformPurgePriorityh"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/platform/PurgePriority.h (0 => 172744)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/PurgePriority.h                                (rev 0)
+++ trunk/Source/WebCore/platform/PurgePriority.h        2014-08-19 05:10:23 UTC (rev 172744)
</span><span class="lines">@@ -0,0 +1,39 @@
</span><ins>+/*
+ * Copyright (C) 2010 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.
+ */
+
+#ifndef PurgePriority_h
+#define PurgePriority_h
+
+namespace WebCore {
+
+enum PurgePriority {
+    PurgeLast,
+    PurgeMiddle,
+    PurgeFirst,
+    PurgeDefault = PurgeMiddle
+};
+
+}
+
+#endif // PurgePriority_h
</ins></span></pre></div>
<a id="trunkSourceWebCoreplatformPurgeableBufferh"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/platform/PurgeableBuffer.h (0 => 172744)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/PurgeableBuffer.h                                (rev 0)
+++ trunk/Source/WebCore/platform/PurgeableBuffer.h        2014-08-19 05:10:23 UTC (rev 172744)
</span><span class="lines">@@ -0,0 +1,77 @@
</span><ins>+/*
+ * Copyright (C) 2008, 2010 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. ``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
+ * 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. 
+ */
+
+#ifndef PurgeableBuffer_h
+#define PurgeableBuffer_h
+
+#include &quot;PurgePriority.h&quot;
+#include &lt;wtf/PassOwnPtr.h&gt;
+#include &lt;wtf/Vector.h&gt;
+
+namespace WebCore {
+
+    class PurgeableBuffer {
+        WTF_MAKE_NONCOPYABLE(PurgeableBuffer);
+    public:
+        static PassOwnPtr&lt;PurgeableBuffer&gt; createUninitialized(size_t, char*&amp; data);
+        static PassOwnPtr&lt;PurgeableBuffer&gt; create(const char* data, size_t);
+        
+        ~PurgeableBuffer();
+
+        // Call makePurgeable(false) and check the return value before accessing the data.
+        const char* data() const;
+        size_t size() const { return m_size; }
+        
+        PurgePriority purgePriority() const { return m_purgePriority; }
+        void setPurgePriority(PurgePriority priority) { m_purgePriority = priority; }
+        
+        bool isPurgeable() const { return m_state != NonVolatile; }
+        bool wasPurged() const;
+
+        bool makePurgeable(bool purgeable);
+
+    private:
+        PurgeableBuffer(char* data, size_t);
+    
+        char* m_data;
+        size_t m_size;
+        PurgePriority m_purgePriority;
+
+        enum State { NonVolatile, Volatile, Purged };
+        mutable State m_state;
+    };
+
+#if !ENABLE(PURGEABLE_MEMORY)
+    inline PassOwnPtr&lt;PurgeableBuffer&gt; PurgeableBuffer::createUninitialized(size_t, char*&amp;) { return nullptr; }
+    inline PassOwnPtr&lt;PurgeableBuffer&gt; PurgeableBuffer::create(const char*, size_t) { return nullptr; }
+    inline PurgeableBuffer::~PurgeableBuffer() { }
+    inline const char* PurgeableBuffer::data() const { return 0; }
+    inline bool PurgeableBuffer::wasPurged() const { return false; }
+    inline bool PurgeableBuffer::makePurgeable(bool) { return false; }
+#endif
+    
+}
+
+#endif
</ins></span></pre></div>
<a id="trunkSourceWebCoreplatformSharedBuffercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/SharedBuffer.cpp (172743 => 172744)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/SharedBuffer.cpp        2014-08-19 05:04:07 UTC (rev 172743)
+++ trunk/Source/WebCore/platform/SharedBuffer.cpp        2014-08-19 05:10:23 UTC (rev 172744)
</span><span class="lines">@@ -27,6 +27,7 @@
</span><span class="cx"> #include &quot;config.h&quot;
</span><span class="cx"> #include &quot;SharedBuffer.h&quot;
</span><span class="cx"> 
</span><ins>+#include &quot;PurgeableBuffer.h&quot;
</ins><span class="cx"> #include &lt;wtf/PassOwnPtr.h&gt;
</span><span class="cx"> #include &lt;wtf/unicode/UTF8.h&gt;
</span><span class="cx"> 
</span><span class="lines">@@ -65,6 +66,7 @@
</span><span class="cx"> SharedBuffer::SharedBuffer()
</span><span class="cx">     : m_size(0)
</span><span class="cx">     , m_buffer(adoptRef(new DataBuffer))
</span><ins>+    , m_shouldUsePurgeableMemory(false)
</ins><span class="cx"> #if ENABLE(DISK_IMAGE_CACHE)
</span><span class="cx">     , m_isMemoryMapped(false)
</span><span class="cx">     , m_diskImageCacheId(DiskImageCache::invalidDiskCacheId)
</span><span class="lines">@@ -77,6 +79,7 @@
</span><span class="cx"> SharedBuffer::SharedBuffer(unsigned size)
</span><span class="cx">     : m_size(size)
</span><span class="cx">     , m_buffer(adoptRef(new DataBuffer))
</span><ins>+    , m_shouldUsePurgeableMemory(false)
</ins><span class="cx"> #if ENABLE(DISK_IMAGE_CACHE)
</span><span class="cx">     , m_isMemoryMapped(false)
</span><span class="cx">     , m_diskImageCacheId(DiskImageCache::invalidDiskCacheId)
</span><span class="lines">@@ -89,6 +92,7 @@
</span><span class="cx"> SharedBuffer::SharedBuffer(const char* data, unsigned size)
</span><span class="cx">     : m_size(0)
</span><span class="cx">     , m_buffer(adoptRef(new DataBuffer))
</span><ins>+    , m_shouldUsePurgeableMemory(false)
</ins><span class="cx"> #if ENABLE(DISK_IMAGE_CACHE)
</span><span class="cx">     , m_isMemoryMapped(false)
</span><span class="cx">     , m_diskImageCacheId(DiskImageCache::invalidDiskCacheId)
</span><span class="lines">@@ -102,6 +106,7 @@
</span><span class="cx"> SharedBuffer::SharedBuffer(const unsigned char* data, unsigned size)
</span><span class="cx">     : m_size(0)
</span><span class="cx">     , m_buffer(adoptRef(new DataBuffer))
</span><ins>+    , m_shouldUsePurgeableMemory(false)
</ins><span class="cx"> #if ENABLE(DISK_IMAGE_CACHE)
</span><span class="cx">     , m_isMemoryMapped(false)
</span><span class="cx">     , m_diskImageCacheId(DiskImageCache::invalidDiskCacheId)
</span><span class="lines">@@ -132,11 +137,22 @@
</span><span class="cx">     return buffer.release();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+PassRefPtr&lt;SharedBuffer&gt; SharedBuffer::adoptPurgeableBuffer(PassOwnPtr&lt;PurgeableBuffer&gt; purgeableBuffer) 
+{ 
+    ASSERT(!purgeableBuffer-&gt;isPurgeable());
+    RefPtr&lt;SharedBuffer&gt; buffer = create();
+    buffer-&gt;m_purgeableBuffer = purgeableBuffer;
+    return buffer.release();
+}
+
</ins><span class="cx"> unsigned SharedBuffer::size() const
</span><span class="cx"> {
</span><span class="cx">     if (hasPlatformData())
</span><span class="cx">         return platformDataSize();
</span><span class="cx">     
</span><ins>+    if (m_purgeableBuffer)
+        return m_purgeableBuffer-&gt;size();
+    
</ins><span class="cx">     return m_size;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -200,6 +216,44 @@
</span><span class="cx"> }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+// Try to create a PurgeableBuffer. We can fail to create one for any of the
+// following reasons:
+//   - shouldUsePurgeableMemory is set to false.
+//   - the size of the buffer is less than the minimum size required by
+//     PurgeableBuffer (currently 16k).
+//   - PurgeableBuffer::createUninitialized() call fails.
+void SharedBuffer::createPurgeableBuffer() const
+{
+    if (m_purgeableBuffer)
+        return;
+
+    if (hasPlatformData())
+        return;
+
+#if USE(NETWORK_CFDATA_ARRAY_CALLBACK)
+    if (singleDataArrayBuffer())
+        return;
+#endif
+
+    if (!m_buffer-&gt;hasOneRef())
+        return;
+
+    if (!m_shouldUsePurgeableMemory)
+        return;
+
+    char* destination = 0;
+    m_purgeableBuffer = PurgeableBuffer::createUninitialized(m_size, destination);
+    if (!m_purgeableBuffer)
+        return;
+    unsigned bufferSize = m_buffer-&gt;data.size();
+    if (bufferSize) {
+        memcpy(destination, m_buffer-&gt;data.data(), bufferSize);
+        destination += bufferSize;
+        (const_cast&lt;SharedBuffer*&gt;(this))-&gt;clearDataBuffer();
+    }
+    copyBufferAndClear(destination, m_size - bufferSize);
+}
+
</ins><span class="cx"> const char* SharedBuffer::data() const
</span><span class="cx"> {
</span><span class="cx"> #if ENABLE(DISK_IMAGE_CACHE)
</span><span class="lines">@@ -215,6 +269,11 @@
</span><span class="cx">         return buffer;
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+    createPurgeableBuffer();
+
+    if (m_purgeableBuffer)
+        return m_purgeableBuffer-&gt;data();
+    
</ins><span class="cx">     return this-&gt;buffer().data();
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -257,6 +316,7 @@
</span><span class="cx"> 
</span><span class="cx"> void SharedBuffer::append(const char* data, unsigned length)
</span><span class="cx"> {
</span><ins>+    ASSERT(!m_purgeableBuffer);
</ins><span class="cx"> #if ENABLE(DISK_IMAGE_CACHE)
</span><span class="cx">     ASSERT(!isMemoryMapped());
</span><span class="cx"> #endif
</span><span class="lines">@@ -326,12 +386,13 @@
</span><span class="cx"> 
</span><span class="cx">     m_size = 0;
</span><span class="cx">     clearDataBuffer();
</span><ins>+    m_purgeableBuffer.clear();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> PassRefPtr&lt;SharedBuffer&gt; SharedBuffer::copy() const
</span><span class="cx"> {
</span><span class="cx">     RefPtr&lt;SharedBuffer&gt; clone(adoptRef(new SharedBuffer));
</span><del>-    if (hasPlatformData()) {
</del><ins>+    if (m_purgeableBuffer || hasPlatformData()) {
</ins><span class="cx">         clone-&gt;append(data(), size());
</span><span class="cx">         return clone;
</span><span class="cx">     }
</span><span class="lines">@@ -349,6 +410,12 @@
</span><span class="cx">     return clone;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+PassOwnPtr&lt;PurgeableBuffer&gt; SharedBuffer::releasePurgeableBuffer()
+{ 
+    ASSERT(hasOneRef()); 
+    return m_purgeableBuffer.release(); 
+}
+
</ins><span class="cx"> void SharedBuffer::duplicateDataBufferIfNecessary() const
</span><span class="cx"> {
</span><span class="cx">     if (m_buffer-&gt;hasOneRef() || m_size &lt;= m_buffer-&gt;data.capacity())
</span><span class="lines">@@ -419,7 +486,7 @@
</span><span class="cx">     }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-    if (hasPlatformData()) {
</del><ins>+    if (hasPlatformData() || m_purgeableBuffer) {
</ins><span class="cx">         ASSERT_WITH_SECURITY_IMPLICATION(position &lt; size());
</span><span class="cx">         someData = data() + position;
</span><span class="cx">         return totalSize - position;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformSharedBufferh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/SharedBuffer.h (172743 => 172744)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/SharedBuffer.h        2014-08-19 05:04:07 UTC (rev 172743)
+++ trunk/Source/WebCore/platform/SharedBuffer.h        2014-08-19 05:10:23 UTC (rev 172744)
</span><span class="lines">@@ -49,6 +49,8 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx">     
</span><ins>+class PurgeableBuffer;
+
</ins><span class="cx"> class SharedBuffer : public RefCounted&lt;SharedBuffer&gt; {
</span><span class="cx"> public:
</span><span class="cx">     static PassRefPtr&lt;SharedBuffer&gt; create() { return adoptRef(new SharedBuffer); }
</span><span class="lines">@@ -60,6 +62,10 @@
</span><span class="cx"> 
</span><span class="cx">     static PassRefPtr&lt;SharedBuffer&gt; adoptVector(Vector&lt;char&gt;&amp; vector);
</span><span class="cx">     
</span><ins>+    // The buffer must be in non-purgeable state before adopted to a SharedBuffer. 
+    // It will stay that way until released.
+    static PassRefPtr&lt;SharedBuffer&gt; adoptPurgeableBuffer(PassOwnPtr&lt;PurgeableBuffer&gt;);
+    
</ins><span class="cx">     ~SharedBuffer();
</span><span class="cx">     
</span><span class="cx"> #if USE(FOUNDATION)
</span><span class="lines">@@ -104,6 +110,11 @@
</span><span class="cx"> 
</span><span class="cx">     PassRefPtr&lt;SharedBuffer&gt; copy() const;
</span><span class="cx">     
</span><ins>+    bool hasPurgeableBuffer() const { return m_purgeableBuffer.get(); }
+
+    // Ensure this buffer has no other clients before calling this.
+    PassOwnPtr&lt;PurgeableBuffer&gt; releasePurgeableBuffer();
+
</ins><span class="cx">     // Return the number of consecutive bytes after &quot;position&quot;. &quot;data&quot;
</span><span class="cx">     // points to the first byte.
</span><span class="cx">     // Return 0 when no more data left.
</span><span class="lines">@@ -118,6 +129,8 @@
</span><span class="cx">     //      }
</span><span class="cx">     unsigned getSomeData(const char*&amp; data, unsigned position = 0) const;
</span><span class="cx"> 
</span><ins>+    void shouldUsePurgeableMemory(bool use) { m_shouldUsePurgeableMemory = use; }
+
</ins><span class="cx"> #if ENABLE(DISK_IMAGE_CACHE)
</span><span class="cx">     enum MemoryMappingState { QueuedForMapping, PreviouslyQueuedForMapping, SuccessAlreadyMapped, FailureCacheFull };
</span><span class="cx"> 
</span><span class="lines">@@ -142,6 +155,8 @@
</span><span class="cx">     void setMemoryMappedNotificationCallback(MemoryMappedNotifyCallback, MemoryMappedNotifyCallbackData);
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+    void createPurgeableBuffer() const;
+
</ins><span class="cx">     void tryReplaceContentsWithPlatformBuffer(SharedBuffer*);
</span><span class="cx">     bool hasPlatformData() const;
</span><span class="cx"> 
</span><span class="lines">@@ -158,6 +173,8 @@
</span><span class="cx">     // Calling this function will force internal segmented buffers
</span><span class="cx">     // to be merged into a flat buffer. Use getSomeData() whenever possible
</span><span class="cx">     // for better performance.
</span><ins>+    // As well, be aware that this method does *not* return any purgeable
+    // memory, which can be a source of bugs.
</ins><span class="cx">     const Vector&lt;char&gt;&amp; buffer() const;
</span><span class="cx"> 
</span><span class="cx">     void clearPlatformData();
</span><span class="lines">@@ -173,6 +190,8 @@
</span><span class="cx">     unsigned m_size;
</span><span class="cx">     mutable RefPtr&lt;DataBuffer&gt; m_buffer;
</span><span class="cx"> 
</span><ins>+    bool m_shouldUsePurgeableMemory;
+    mutable OwnPtr&lt;PurgeableBuffer&gt; m_purgeableBuffer;
</ins><span class="cx"> #if USE(NETWORK_CFDATA_ARRAY_CALLBACK)
</span><span class="cx">     explicit SharedBuffer(CFArrayRef);
</span><span class="cx">     mutable Vector&lt;RetainPtr&lt;CFDataRef&gt;&gt; m_dataArray;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformcfSharedBufferCFcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/cf/SharedBufferCF.cpp (172743 => 172744)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/cf/SharedBufferCF.cpp        2014-08-19 05:04:07 UTC (rev 172743)
+++ trunk/Source/WebCore/platform/cf/SharedBufferCF.cpp        2014-08-19 05:10:23 UTC (rev 172744)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> #include &quot;config.h&quot;
</span><span class="cx"> #include &quot;SharedBuffer.h&quot;
</span><span class="cx"> 
</span><ins>+#include &quot;PurgeableBuffer.h&quot;
</ins><span class="cx"> #include &lt;wtf/cf/TypeCasts.h&gt;
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(DISK_IMAGE_CACHE)
</span><span class="lines">@@ -39,6 +40,7 @@
</span><span class="cx"> SharedBuffer::SharedBuffer(CFDataRef cfData)
</span><span class="cx">     : m_size(0)
</span><span class="cx">     , m_buffer(adoptRef(new DataBuffer))
</span><ins>+    , m_shouldUsePurgeableMemory(false)
</ins><span class="cx"> #if ENABLE(DISK_IMAGE_CACHE)
</span><span class="cx">     , m_isMemoryMapped(false)
</span><span class="cx">     , m_diskImageCacheId(DiskImageCache::invalidDiskCacheId)
</span><span class="lines">@@ -128,6 +130,7 @@
</span><span class="cx"> SharedBuffer::SharedBuffer(CFArrayRef cfDataArray)
</span><span class="cx">     : m_size(0)
</span><span class="cx">     , m_buffer(adoptRef(new DataBuffer))
</span><ins>+    , m_shouldUsePurgeableMemory(false)
</ins><span class="cx"> #if ENABLE(DISK_IMAGE_CACHE)
</span><span class="cx">     , m_isMemoryMapped(false)
</span><span class="cx">     , m_diskImageCacheId(DiskImageCache::invalidDiskCacheId)
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmacPurgeableBufferMaccpp"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/platform/mac/PurgeableBufferMac.cpp (0 => 172744)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mac/PurgeableBufferMac.cpp                                (rev 0)
+++ trunk/Source/WebCore/platform/mac/PurgeableBufferMac.cpp        2014-08-19 05:10:23 UTC (rev 172744)
</span><span class="lines">@@ -0,0 +1,159 @@
</span><ins>+/*
+ * Copyright (C) 2008 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. ``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
+ * 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 &quot;config.h&quot;
+
+#if ENABLE(PURGEABLE_MEMORY)
+
+#include &quot;PurgeableBuffer.h&quot;
+
+#include &lt;mach/mach.h&gt;
+#include &lt;wtf/Assertions.h&gt;
+#include &lt;wtf/VMTags.h&gt;
+
+namespace WebCore {
+
+// Purgeable buffers are allocated in multiples of the page size (4KB in common CPUs) so
+// it does not make sense for very small buffers. Set our minimum size to 16KB.
+static const size_t minPurgeableBufferSize = 4 * 4096;
+
+PurgeableBuffer::PurgeableBuffer(char* data, size_t size)
+    : m_data(data)
+    , m_size(size)
+    , m_purgePriority(PurgeDefault)
+    , m_state(NonVolatile)
+{
+}
+
+PurgeableBuffer::~PurgeableBuffer()
+{
+    vm_deallocate(mach_task_self(), reinterpret_cast&lt;vm_address_t&gt;(m_data), m_size);
+}
+
+PassOwnPtr&lt;PurgeableBuffer&gt; PurgeableBuffer::createUninitialized(size_t size, char*&amp; data)
+{
+    if (size &lt; minPurgeableBufferSize)
+        return nullptr;
+
+    vm_address_t buffer = 0;
+    kern_return_t ret = vm_allocate(mach_task_self(), &amp;buffer, size, VM_FLAGS_PURGABLE | VM_FLAGS_ANYWHERE | VM_TAG_FOR_WEBCORE_PURGEABLE_MEMORY);
+
+    ASSERT(ret == KERN_SUCCESS);
+    if (ret != KERN_SUCCESS)
+        return nullptr;
+
+    data = reinterpret_cast&lt;char*&gt;(buffer);
+    return adoptPtr(new PurgeableBuffer(data, size));
+}
+
+PassOwnPtr&lt;PurgeableBuffer&gt; PurgeableBuffer::create(const char* data, size_t size)
+{
+    char* destination;
+    OwnPtr&lt;PurgeableBuffer&gt; purgeableBuffer = PurgeableBuffer::createUninitialized(size, destination);
+    if (!purgeableBuffer)
+        return nullptr;
+    memcpy(destination, data, size);
+    return purgeableBuffer.release();
+}
+
+bool PurgeableBuffer::makePurgeable(bool purgeable)
+{
+    if (purgeable) {
+        if (m_state != NonVolatile)
+            return true;
+
+        int volatileGroup;
+        if (m_purgePriority == PurgeFirst)
+            volatileGroup = VM_VOLATILE_GROUP_0;
+        else if (m_purgePriority == PurgeMiddle)
+            volatileGroup = VM_VOLATILE_GROUP_4;
+        else
+            volatileGroup = VM_VOLATILE_GROUP_7;
+        
+        int state = VM_PURGABLE_VOLATILE | volatileGroup;
+        // So apparently &quot;purgeable&quot; is the correct spelling and the API here is misspelled.
+        kern_return_t ret = vm_purgable_control(mach_task_self(), reinterpret_cast&lt;vm_address_t&gt;(m_data), VM_PURGABLE_SET_STATE, &amp;state);
+        
+        if (ret != KERN_SUCCESS) {
+            // If that failed we have no clue what state we are in so assume purged.
+            m_state = Purged;
+            return true;
+        }
+        
+        m_state = Volatile;
+        return true;
+    }
+
+    if (m_state == NonVolatile)
+        return true;
+    if (m_state == Purged)
+        return false;
+    
+    int state = VM_PURGABLE_NONVOLATILE;
+    kern_return_t ret = vm_purgable_control(mach_task_self(), reinterpret_cast&lt;vm_address_t&gt;(m_data), VM_PURGABLE_SET_STATE, &amp;state);
+
+    if (ret != KERN_SUCCESS) {
+        // If that failed we have no clue what state we are in so assume purged.
+        m_state = Purged;
+        return false;
+    }
+
+    m_state = state &amp; VM_PURGABLE_EMPTY ? Purged : NonVolatile;
+    return m_state == NonVolatile;
+}
+    
+bool PurgeableBuffer::wasPurged() const
+{
+    if (m_state == NonVolatile)
+        return false;
+    if (m_state == Purged)
+        return true;
+
+    int state;
+    kern_return_t ret = vm_purgable_control(mach_task_self(), reinterpret_cast&lt;vm_address_t&gt;(m_data), VM_PURGABLE_GET_STATE, &amp;state);
+
+    if (ret != KERN_SUCCESS) {
+        // If that failed we have no clue what state we are in so assume purged.
+        m_state = Purged;
+        return true;        
+    }
+
+    if (state &amp; VM_PURGABLE_EMPTY) {
+        m_state = Purged;
+        return true;
+    }
+        
+    return false;
+}
+
+const char* PurgeableBuffer::data() const
+{
+    ASSERT(m_state == NonVolatile);
+    return m_data;
+}
+    
+}
+
+#endif
</ins></span></pre></div>
<a id="trunkSourceWebCoreplatformmacSharedBufferMacmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mac/SharedBufferMac.mm (172743 => 172744)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mac/SharedBufferMac.mm        2014-08-19 05:04:07 UTC (rev 172743)
+++ trunk/Source/WebCore/platform/mac/SharedBufferMac.mm        2014-08-19 05:10:23 UTC (rev 172744)
</span><span class="lines">@@ -152,6 +152,12 @@
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     data(); // Force data into m_buffer from segments or data array.
</span><ins>+    if (hasPurgeableBuffer()) {
+        RefPtr&lt;SharedBuffer::DataBuffer&gt; copiedBuffer = adoptRef(new DataBuffer);
+        copiedBuffer-&gt;data.append(data(), size());
+        return adoptCF((CFDataRef)adoptNS([[WebCoreSharedBufferData alloc] initWithSharedBufferDataBuffer:copiedBuffer.get()]).leakRef());
+    }
+
</ins><span class="cx">     return adoptCF((CFDataRef)adoptNS([[WebCoreSharedBufferData alloc] initWithSharedBufferDataBuffer:m_buffer.get()]).leakRef());
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformsoupSharedBufferSoupcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/soup/SharedBufferSoup.cpp (172743 => 172744)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/soup/SharedBufferSoup.cpp        2014-08-19 05:04:07 UTC (rev 172743)
+++ trunk/Source/WebCore/platform/soup/SharedBufferSoup.cpp        2014-08-19 05:10:23 UTC (rev 172744)
</span><span class="lines">@@ -22,6 +22,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;SharedBuffer.h&quot;
</span><span class="cx"> 
</span><ins>+#include &quot;PurgeableBuffer.h&quot;
</ins><span class="cx"> #include &lt;libsoup/soup.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span></span></pre></div>
<a id="trunkSourceWebKitmacChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/mac/ChangeLog (172743 => 172744)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/mac/ChangeLog        2014-08-19 05:04:07 UTC (rev 172743)
+++ trunk/Source/WebKit/mac/ChangeLog        2014-08-19 05:10:23 UTC (rev 172744)
</span><span class="lines">@@ -1,3 +1,16 @@
</span><ins>+2014-08-18  Commit Queue  &lt;commit-queue@webkit.org&gt;
+
+        Unreviewed, rolling out r172736.
+        https://bugs.webkit.org/show_bug.cgi?id=136060
+
+        Caused 14% PLT regressions (Requested by rniwa on #webkit).
+
+        Reverted changeset:
+
+        &quot;Remove PurgeableBuffer since it is not very useful any more&quot;
+        https://bugs.webkit.org/show_bug.cgi?id=135939
+        http://trac.webkit.org/changeset/172736
+
</ins><span class="cx"> 2014-08-18  Pratik Solanki  &lt;psolanki@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Remove PurgeableBuffer since it is not very useful any more
</span></span></pre></div>
<a id="trunkSourceWebKitmacMiscWebCachemm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/mac/Misc/WebCache.mm (172743 => 172744)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/mac/Misc/WebCache.mm        2014-08-19 05:04:07 UTC (rev 172743)
+++ trunk/Source/WebKit/mac/Misc/WebCache.mm        2014-08-19 05:10:23 UTC (rev 172744)
</span><span class="lines">@@ -108,6 +108,26 @@
</span><span class="cx"> #endif
</span><span class="cx">             [NSNumber numberWithInt:s.scripts.decodedSize], @&quot;JavaScript&quot;,
</span><span class="cx">             nil],
</span><ins>+        [NSDictionary dictionaryWithObjectsAndKeys:
+            [NSNumber numberWithInt:s.images.purgeableSize], @&quot;Images&quot;,
+            [NSNumber numberWithInt:s.cssStyleSheets.purgeableSize] ,@&quot;CSS&quot;,
+#if ENABLE(XSLT)
+            [NSNumber numberWithInt:s.xslStyleSheets.purgeableSize], @&quot;XSL&quot;,
+#else
+            [NSNumber numberWithInt:0], @&quot;XSL&quot;,
+#endif
+            [NSNumber numberWithInt:s.scripts.purgeableSize], @&quot;JavaScript&quot;,
+            nil],
+        [NSDictionary dictionaryWithObjectsAndKeys:
+            [NSNumber numberWithInt:s.images.purgedSize], @&quot;Images&quot;,
+            [NSNumber numberWithInt:s.cssStyleSheets.purgedSize] ,@&quot;CSS&quot;,
+#if ENABLE(XSLT)
+            [NSNumber numberWithInt:s.xslStyleSheets.purgedSize], @&quot;XSL&quot;,
+#else
+            [NSNumber numberWithInt:0], @&quot;XSL&quot;,
+#endif
+            [NSNumber numberWithInt:s.scripts.purgedSize], @&quot;JavaScript&quot;,
+            nil],
</ins><span class="cx"> #if ENABLE(DISK_IMAGE_CACHE) &amp;&amp; PLATFORM(IOS)
</span><span class="cx">         [NSDictionary dictionaryWithObjectsAndKeys:
</span><span class="cx">             [NSNumber numberWithInt:s.images.mappedSize], @&quot;Images&quot;,
</span></span></pre></div>
<a id="trunkSourceWebKitwinChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/win/ChangeLog (172743 => 172744)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/win/ChangeLog        2014-08-19 05:04:07 UTC (rev 172743)
+++ trunk/Source/WebKit/win/ChangeLog        2014-08-19 05:10:23 UTC (rev 172744)
</span><span class="lines">@@ -1,3 +1,16 @@
</span><ins>+2014-08-18  Commit Queue  &lt;commit-queue@webkit.org&gt;
+
+        Unreviewed, rolling out r172736.
+        https://bugs.webkit.org/show_bug.cgi?id=136060
+
+        Caused 14% PLT regressions (Requested by rniwa on #webkit).
+
+        Reverted changeset:
+
+        &quot;Remove PurgeableBuffer since it is not very useful any more&quot;
+        https://bugs.webkit.org/show_bug.cgi?id=135939
+        http://trac.webkit.org/changeset/172736
+
</ins><span class="cx"> 2014-08-18  Pratik Solanki  &lt;psolanki@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Remove PurgeableBuffer since it is not very useful any more
</span></span></pre></div>
<a id="trunkSourceWebKitwinWebCachecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/win/WebCache.cpp (172743 => 172744)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/win/WebCache.cpp        2014-08-19 05:04:07 UTC (rev 172743)
+++ trunk/Source/WebKit/win/WebCache.cpp        2014-08-19 05:10:23 UTC (rev 172744)
</span><span class="lines">@@ -202,6 +202,52 @@
</span><span class="cx">     propBag-&gt;setDictionary(dictionary.get());
</span><span class="cx">     s[3] = propBag.leakRef();
</span><span class="cx"> 
</span><ins>+    // Purgable Sizes.
+    dictionary = adoptCF(CFDictionaryCreateMutable(0, 0, &amp;kCFTypeDictionaryKeyCallBacks, &amp;kCFTypeDictionaryValueCallBacks));
+
+    value = adoptCF(CFNumberCreate(0, kCFNumberIntType, &amp;stat.images.purgeableSize));
+    CFDictionaryAddValue(dictionary.get(), imagesKey, value.get());
+
+    value = adoptCF(CFNumberCreate(0, kCFNumberIntType, &amp;stat.cssStyleSheets.purgeableSize));
+    CFDictionaryAddValue(dictionary.get(), stylesheetsKey, value.get());
+
+#if ENABLE(XSLT)
+    value = adoptCF(CFNumberCreate(0, kCFNumberIntType, &amp;stat.xslStyleSheets.purgeableSize));
+#else
+    value = adoptCF(CFNumberCreate(0, kCFNumberIntType, &amp;zero));
+#endif
+    CFDictionaryAddValue(dictionary.get(), xslKey, value.get());
+
+    value = adoptCF(CFNumberCreate(0, kCFNumberIntType, &amp;stat.scripts.purgeableSize));
+    CFDictionaryAddValue(dictionary.get(), scriptsKey, value.get());
+
+    propBag = CFDictionaryPropertyBag::createInstance();
+    propBag-&gt;setDictionary(dictionary.get());
+    s[4] = propBag.leakRef();
+
+    // Purged Sizes.
+    dictionary = adoptCF(CFDictionaryCreateMutable(0, 0, &amp;kCFTypeDictionaryKeyCallBacks, &amp;kCFTypeDictionaryValueCallBacks));
+
+    value = adoptCF(CFNumberCreate(0, kCFNumberIntType, &amp;stat.images.purgedSize));
+    CFDictionaryAddValue(dictionary.get(), imagesKey, value.get());
+
+    value = adoptCF(CFNumberCreate(0, kCFNumberIntType, &amp;stat.cssStyleSheets.purgedSize));
+    CFDictionaryAddValue(dictionary.get(), stylesheetsKey, value.get());
+
+#if ENABLE(XSLT)
+    value = adoptCF(CFNumberCreate(0, kCFNumberIntType, &amp;stat.xslStyleSheets.purgedSize));
+#else
+    value = adoptCF(CFNumberCreate(0, kCFNumberIntType, &amp;zero));
+#endif
+    CFDictionaryAddValue(dictionary.get(), xslKey, value.get());
+
+    value = adoptCF(CFNumberCreate(0, kCFNumberIntType, &amp;stat.scripts.purgedSize));
+    CFDictionaryAddValue(dictionary.get(), scriptsKey, value.get());
+
+    propBag = CFDictionaryPropertyBag::createInstance();
+    propBag-&gt;setDictionary(dictionary.get());
+    s[5] = propBag.leakRef();
+
</ins><span class="cx">     return S_OK;
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (172743 => 172744)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2014-08-19 05:04:07 UTC (rev 172743)
+++ trunk/Source/WebKit2/ChangeLog        2014-08-19 05:10:23 UTC (rev 172744)
</span><span class="lines">@@ -1,3 +1,16 @@
</span><ins>+2014-08-18  Commit Queue  &lt;commit-queue@webkit.org&gt;
+
+        Unreviewed, rolling out r172736.
+        https://bugs.webkit.org/show_bug.cgi?id=136060
+
+        Caused 14% PLT regressions (Requested by rniwa on #webkit).
+
+        Reverted changeset:
+
+        &quot;Remove PurgeableBuffer since it is not very useful any more&quot;
+        https://bugs.webkit.org/show_bug.cgi?id=135939
+        http://trac.webkit.org/changeset/172736
+
</ins><span class="cx"> 2014-08-18  Simon Fraser  &lt;simon.fraser@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Provide default implementations of all GraphicsLayerClient methods
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessWebProcesscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/WebProcess.cpp (172743 => 172744)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/WebProcess.cpp        2014-08-19 05:04:07 UTC (rev 172743)
+++ trunk/Source/WebKit2/WebProcess/WebProcess.cpp        2014-08-19 05:10:23 UTC (rev 172744)
</span><span class="lines">@@ -885,6 +885,20 @@
</span><span class="cx">     decodedSizes.set(xslString, memoryCacheStatistics.xslStyleSheets.decodedSize);
</span><span class="cx">     decodedSizes.set(javaScriptString, memoryCacheStatistics.scripts.decodedSize);
</span><span class="cx">     result.append(decodedSizes);
</span><ins>+    
+    HashMap&lt;String, uint64_t&gt; purgeableSizes;
+    purgeableSizes.set(imagesString, memoryCacheStatistics.images.purgeableSize);
+    purgeableSizes.set(cssString, memoryCacheStatistics.cssStyleSheets.purgeableSize);
+    purgeableSizes.set(xslString, memoryCacheStatistics.xslStyleSheets.purgeableSize);
+    purgeableSizes.set(javaScriptString, memoryCacheStatistics.scripts.purgeableSize);
+    result.append(purgeableSizes);
+    
+    HashMap&lt;String, uint64_t&gt; purgedSizes;
+    purgedSizes.set(imagesString, memoryCacheStatistics.images.purgedSize);
+    purgedSizes.set(cssString, memoryCacheStatistics.cssStyleSheets.purgedSize);
+    purgedSizes.set(xslString, memoryCacheStatistics.xslStyleSheets.purgedSize);
+    purgedSizes.set(javaScriptString, memoryCacheStatistics.scripts.purgedSize);
+    result.append(purgedSizes);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void WebProcess::getWebCoreStatistics(uint64_t callbackID)
</span></span></pre>
</div>
</div>

</body>
</html>