Title: [172744] trunk/Source
Revision
172744
Author
[email protected]
Date
2014-08-18 22:10:23 -0700 (Mon, 18 Aug 2014)

Log Message

Unreviewed, rolling out r172736.
https://bugs.webkit.org/show_bug.cgi?id=136060

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

Reverted changeset:

"Remove PurgeableBuffer since it is not very useful any more"
https://bugs.webkit.org/show_bug.cgi?id=135939
http://trac.webkit.org/changeset/172736

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WTF/ChangeLog (172743 => 172744)


--- 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)
@@ -1,3 +1,16 @@
+2014-08-18  Commit Queue  <[email protected]>
+
+        Unreviewed, rolling out r172736.
+        https://bugs.webkit.org/show_bug.cgi?id=136060
+
+        Caused 14% PLT regressions (Requested by rniwa on #webkit).
+
+        Reverted changeset:
+
+        "Remove PurgeableBuffer since it is not very useful any more"
+        https://bugs.webkit.org/show_bug.cgi?id=135939
+        http://trac.webkit.org/changeset/172736
+
 2014-08-18  Pratik Solanki  <[email protected]>
 
         Remove PurgeableBuffer since it is not very useful any more

Modified: trunk/Source/WTF/wtf/Platform.h (172743 => 172744)


--- 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)
@@ -490,6 +490,10 @@
 
 #endif /* PLATFORM(MAC) */
 
+#if OS(DARWIN) && !PLATFORM(GTK)
+#define ENABLE_PURGEABLE_MEMORY 1
+#endif
+
 #if PLATFORM(IOS)
 
 #define DONT_FINALIZE_ON_MAIN_THREAD 1

Modified: trunk/Source/WTF/wtf/VMTags.h (172743 => 172744)


--- 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)
@@ -56,12 +56,19 @@
 #define VM_TAG_FOR_COLLECTOR_MEMORY VM_MAKE_TAG(63)
 #endif // defined(VM_MEMORY_JAVASCRIPT_CORE)
 
+#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)
+
 #else // OS(DARWIN)
 
 #define VM_TAG_FOR_TCMALLOC_MEMORY -1
 #define VM_TAG_FOR_COLLECTOR_MEMORY -1
 #define VM_TAG_FOR_EXECUTABLEALLOCATOR_MEMORY -1
 #define VM_TAG_FOR_REGISTERFILE_MEMORY -1
+#define VM_TAG_FOR_WEBCORE_PURGEABLE_MEMORY -1
 
 #endif // OS(DARWIN)
 

Modified: trunk/Source/WebCore/ChangeLog (172743 => 172744)


--- 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)
@@ -1,3 +1,16 @@
+2014-08-18  Commit Queue  <[email protected]>
+
+        Unreviewed, rolling out r172736.
+        https://bugs.webkit.org/show_bug.cgi?id=136060
+
+        Caused 14% PLT regressions (Requested by rniwa on #webkit).
+
+        Reverted changeset:
+
+        "Remove PurgeableBuffer since it is not very useful any more"
+        https://bugs.webkit.org/show_bug.cgi?id=135939
+        http://trac.webkit.org/changeset/172736
+
 2014-08-18  Simon Fraser  <[email protected]>
 
         Provide default implementations of all GraphicsLayerClient methods

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (172743 => 172744)


--- 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)
@@ -2430,6 +2430,7 @@
 		7CE6CBFB187F370700D46BF5 /* FormatConverter.h in Headers */ = {isa = PBXBuildFile; fileRef = 7CE6CBFA187F370700D46BF5 /* FormatConverter.h */; };
 		7CE6CBFD187F394900D46BF5 /* FormatConverter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7CE6CBFC187F394900D46BF5 /* FormatConverter.cpp */; };
 		7D741BDA177226AA00859170 /* CSSValueKeywords.h in Copy Generated Headers */ = {isa = PBXBuildFile; fileRef = 6565814809D13043000E61D7 /* CSSValueKeywords.h */; };
+		7E33CD01127F340D00BE8F17 /* PurgePriority.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E33CD00127F340D00BE8F17 /* PurgePriority.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		7E37EF2E1339208800B29250 /* SubresourceLoaderCF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7E37EF2D1339208800B29250 /* SubresourceLoaderCF.cpp */; };
 		7E428CE513E3407F003B661C /* ResourceHandleIOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7E428CE413E3407F003B661C /* ResourceHandleIOS.mm */; };
 		7E46F6FA1627A2CA00062223 /* JSOESElementIndexUint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7E46F6F81627A2C900062223 /* JSOESElementIndexUint.cpp */; };
@@ -6187,6 +6188,8 @@
 		E4D58EB817B4ED8900CBDCA8 /* StyleFontSizeFunctions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4D58EB617B4ED8900CBDCA8 /* StyleFontSizeFunctions.cpp */; };
 		E4D58EB917B4ED8900CBDCA8 /* StyleFontSizeFunctions.h in Headers */ = {isa = PBXBuildFile; fileRef = E4D58EB717B4ED8900CBDCA8 /* StyleFontSizeFunctions.h */; };
 		E4D58EBB17B8F12800CBDCA8 /* ElementTraversal.h in Headers */ = {isa = PBXBuildFile; fileRef = E4D58EBA17B8F12800CBDCA8 /* ElementTraversal.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		E4D687770ED7AE3D006EA978 /* PurgeableBufferMac.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4D687760ED7AE3D006EA978 /* PurgeableBufferMac.cpp */; };
+		E4D687790ED7AE4F006EA978 /* PurgeableBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = E4D687780ED7AE4F006EA978 /* PurgeableBuffer.h */; };
 		E4D988B417BFD1F60084FB88 /* TextNodeTraversal.h in Headers */ = {isa = PBXBuildFile; fileRef = E4D988B317BFD1F60084FB88 /* TextNodeTraversal.h */; };
 		E4D988B617BFEB210084FB88 /* TextNodeTraversal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4D988B517BFEB210084FB88 /* TextNodeTraversal.cpp */; };
 		E4DEAA1717A93DC3000E0430 /* StyleResolveTree.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4DEAA1517A93DC3000E0430 /* StyleResolveTree.cpp */; };
@@ -9583,6 +9586,7 @@
 		7CE683461921821500F4D928 /* UserMessageHandlerDescriptorTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UserMessageHandlerDescriptorTypes.h; sourceTree = "<group>"; };
 		7CE6CBFA187F370700D46BF5 /* FormatConverter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FormatConverter.h; sourceTree = "<group>"; };
 		7CE6CBFC187F394900D46BF5 /* FormatConverter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FormatConverter.cpp; sourceTree = "<group>"; };
+		7E33CD00127F340D00BE8F17 /* PurgePriority.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PurgePriority.h; sourceTree = "<group>"; };
 		7E37EF2D1339208800B29250 /* SubresourceLoaderCF.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SubresourceLoaderCF.cpp; path = cf/SubresourceLoaderCF.cpp; sourceTree = "<group>"; };
 		7E428CE413E3407F003B661C /* ResourceHandleIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ResourceHandleIOS.mm; sourceTree = "<group>"; };
 		7E46F6F81627A2C900062223 /* JSOESElementIndexUint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSOESElementIndexUint.cpp; sourceTree = "<group>"; };
@@ -13704,6 +13708,8 @@
 		E4D58EB617B4ED8900CBDCA8 /* StyleFontSizeFunctions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StyleFontSizeFunctions.cpp; sourceTree = "<group>"; };
 		E4D58EB717B4ED8900CBDCA8 /* StyleFontSizeFunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StyleFontSizeFunctions.h; sourceTree = "<group>"; };
 		E4D58EBA17B8F12800CBDCA8 /* ElementTraversal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ElementTraversal.h; sourceTree = "<group>"; };
+		E4D687760ED7AE3D006EA978 /* PurgeableBufferMac.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PurgeableBufferMac.cpp; sourceTree = "<group>"; };
+		E4D687780ED7AE4F006EA978 /* PurgeableBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PurgeableBuffer.h; sourceTree = "<group>"; };
 		E4D988B317BFD1F60084FB88 /* TextNodeTraversal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextNodeTraversal.h; sourceTree = "<group>"; };
 		E4D988B517BFEB210084FB88 /* TextNodeTraversal.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TextNodeTraversal.cpp; sourceTree = "<group>"; };
 		E4DEAA1517A93DC3000E0430 /* StyleResolveTree.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StyleResolveTree.cpp; sourceTree = "<group>"; };
@@ -16446,6 +16452,7 @@
 				BC94D1070C274F88006BC617 /* PlatformScreenMac.mm */,
 				29E4D8E016B0959800C84704 /* PlatformSpeechSynthesizerMac.mm */,
 				0081FEFE16B0A2B6008AAA7A /* PublicSuffixMac.mm */,
+				E4D687760ED7AE3D006EA978 /* PurgeableBufferMac.cpp */,
 				BCAE1FA512939DB7004CB026 /* ScrollAnimatorMac.h */,
 				BC51156D12B1749C00C96754 /* ScrollAnimatorMac.mm */,
 				BC8B853C0E7C7F1100AB6984 /* ScrollbarThemeMac.h */,
@@ -21392,6 +21399,8 @@
 				ABC128760B33AA6D00C693D5 /* PopupMenuClient.h */,
 				BC3BE12A0E98092F00835588 /* PopupMenuStyle.h */,
 				0081FEFD16B0A244008AAA7A /* PublicSuffix.h */,
+				E4D687780ED7AE4F006EA978 /* PurgeableBuffer.h */,
+				7E33CD00127F340D00BE8F17 /* PurgePriority.h */,
 				A72EA3BA1585CF55004FAA26 /* RefCountedSupplement.h */,
 				9831AE49154225A200FE2644 /* ReferrerPolicy.h */,
 				293EAE201356B32E0067ACF9 /* RuntimeApplicationChecks.cpp */,
@@ -25572,6 +25581,8 @@
 				FF945ECC161F7F3600971BC8 /* PseudoElement.h in Headers */,
 				0081FF0016B0A2D3008AAA7A /* PublicSuffix.h in Headers */,
 				10FB084B14E15C7E00A3DB98 /* PublicURLManager.h in Headers */,
+				E4D687790ED7AE4F006EA978 /* PurgeableBuffer.h in Headers */,
+				7E33CD01127F340D00BE8F17 /* PurgePriority.h in Headers */,
 				550A0BCA085F6039007353D6 /* QualifiedName.h in Headers */,
 				442AF7A9102CDDEA008FD4D3 /* QuickLook.h in Headers */,
 				072AE1E8183C0741000A5988 /* QuickTimePluginReplacement.h in Headers */,
@@ -29072,6 +29083,7 @@
 				FF945ECB161F7F3600971BC8 /* PseudoElement.cpp in Sources */,
 				0081FEFF16B0A2B6008AAA7A /* PublicSuffixMac.mm in Sources */,
 				CDEE393717974259001D7580 /* PublicURLManager.cpp in Sources */,
+				E4D687770ED7AE3D006EA978 /* PurgeableBufferMac.cpp in Sources */,
 				550A0BC9085F6039007353D6 /* QualifiedName.cpp in Sources */,
 				442AF7AA102CDDEA008FD4D3 /* QuickLook.mm in Sources */,
 				072AE1E6183C0741000A5988 /* QuickTimePluginReplacement.mm in Sources */,

Modified: trunk/Source/WebCore/inspector/InspectorPageAgent.cpp (172743 => 172744)


--- 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)
@@ -112,6 +112,17 @@
         return true;
     }
 
+    if (cachedResource->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->makePurgeable(false))
+            return false;
+    }
+
     return true;
 }
 

Modified: trunk/Source/WebCore/loader/DocumentLoader.cpp (172743 => 172744)


--- 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)
@@ -1093,6 +1093,11 @@
     if (resource->type() == CachedResource::MainResource)
         return 0;
 
+    // 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->makePurgeable(false))
+        return 0;
+
     ResourceBuffer* data = ""
     if (!data)
         return 0;

Modified: trunk/Source/WebCore/loader/ResourceBuffer.cpp (172743 => 172744)


--- 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)
@@ -26,6 +26,7 @@
 #include "config.h"
 #include "ResourceBuffer.h"
 
+#include "PurgeableBuffer.h"
 #include "SharedBuffer.h"
 
 namespace WebCore {
@@ -112,6 +113,30 @@
     return ResourceBuffer::adoptSharedBuffer(m_sharedBuffer->copy());
 }
 
+bool ResourceBuffer::hasPurgeableBuffer() const
+{
+    return m_sharedBuffer->hasPurgeableBuffer();
+}
+
+#if PLATFORM(IOS)
+void ResourceBuffer::setShouldUsePurgeableMemory(bool shouldUsePurgeableMemory)
+{
+    ASSERT(m_sharedBuffer);
+    sharedBuffer()->shouldUsePurgeableMemory(shouldUsePurgeableMemory);
+}
+#endif
+
+void ResourceBuffer::createPurgeableBuffer() const
+{
+    ASSERT(m_sharedBuffer);
+    sharedBuffer()->createPurgeableBuffer();
+}
+
+PassOwnPtr<PurgeableBuffer> ResourceBuffer::releasePurgeableBuffer()
+{
+    return m_sharedBuffer->releasePurgeableBuffer();
+}
+
 #if USE(CF)
 RetainPtr<CFDataRef> ResourceBuffer::createCFData()
 {

Modified: trunk/Source/WebCore/loader/ResourceBuffer.h (172743 => 172744)


--- 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)
@@ -38,6 +38,7 @@
 
 namespace WebCore {
 
+class PurgeableBuffer;
 class SharedBuffer;
 
 class ResourceBuffer : public RefCounted<ResourceBuffer> {
@@ -68,6 +69,17 @@
 #endif
     PassRefPtr<ResourceBuffer> copy() const;
 
+    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<PurgeableBuffer> releasePurgeableBuffer();
+
 #if USE(FOUNDATION)
     RetainPtr<NSData> createNSData();
 #endif

Modified: trunk/Source/WebCore/loader/SubresourceLoader.cpp (172743 => 172744)


--- 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)
@@ -299,8 +299,12 @@
     LOG(ResourceLoading, "Received '%s'.", m_resource->url().string().latin1().data());
 
     Ref<SubresourceLoader> protect(*this);
+
+#if PLATFORM(IOS)
+    if (resourceData())
+        resourceData()->setShouldUsePurgeableMemory(true);
+#endif
     CachedResourceHandle<CachedResource> protectResource(m_resource);
-
     m_state = Finishing;
     m_resource->setLoadFinishTime(finishTime);
     m_resource->finishLoading(resourceData());

Modified: trunk/Source/WebCore/loader/cache/CachedCSSStyleSheet.cpp (172743 => 172744)


--- 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)
@@ -80,6 +80,8 @@
     
 const String CachedCSSStyleSheet::sheetText(bool enforceMIMEType, bool* hasValidMIMEType) const 
 { 
+    ASSERT(!isPurgeable());
+
     if (!m_data || m_data->isEmpty() || !canUseSheet(enforceMIMEType, hasValidMIMEType))
         return String();
     
@@ -146,6 +148,9 @@
     m_parsedStyleSheetCache.clear();
 
     setDecodedSize(0);
+
+    if (!MemoryCache::shouldMakeResourcePurgeableOnEviction() && isSafeToMakePurgeable())
+        makePurgeable(true);
 }
 
 PassRefPtr<StyleSheetContents> CachedCSSStyleSheet::restoreParsedStyleSheet(const CSSParserContext& context)

Modified: trunk/Source/WebCore/loader/cache/CachedCSSStyleSheet.h (172743 => 172744)


--- 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)
@@ -48,6 +48,7 @@
 
     private:
         bool canUseSheet(bool enforceMIMEType, bool* hasValidMIMEType) const;
+        virtual PurgePriority purgePriority() const override { return PurgeLast; }
         virtual bool mayTryReplaceEncodedData() const override { return true; }
 
         virtual void didAddClient(CachedResourceClient*) override;

Modified: trunk/Source/WebCore/loader/cache/CachedImage.cpp (172743 => 172744)


--- 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)
@@ -192,6 +192,8 @@
 
 Image* CachedImage::image()
 {
+    ASSERT(!isPurgeable());
+
     if (errorOccurred() && m_shouldPaintBrokenImage) {
         // Returning the 1x broken image is non-ideal, but we cannot reliably access the appropriate
         // deviceScaleFactor from here. It is critical that callers use CachedImage::brokenImage() 
@@ -207,6 +209,8 @@
 
 Image* CachedImage::imageForRenderer(const RenderObject* renderer)
 {
+    ASSERT(!isPurgeable());
+
     if (errorOccurred() && m_shouldPaintBrokenImage) {
         // Returning the 1x broken image is non-ideal, but we cannot reliably access the appropriate
         // deviceScaleFactor from here. It is critical that callers use CachedImage::brokenImage() 
@@ -270,6 +274,8 @@
 
 LayoutSize CachedImage::imageSizeForRenderer(const RenderObject* renderer, float multiplier, SizeType sizeType)
 {
+    ASSERT(!isPurgeable());
+
     if (!m_image)
         return LayoutSize();
 
@@ -456,9 +462,13 @@
 void CachedImage::destroyDecodedData()
 {
     bool canDeleteImage = !m_image || (m_image->hasOneRef() && m_image->isBitmapImage());
-    if (canDeleteImage && !isLoading()) {
+    if (isSafeToMakePurgeable() && canDeleteImage && !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.
         m_image = 0;
         setDecodedSize(0);
+        if (!MemoryCache::shouldMakeResourcePurgeableOnEviction())
+            makePurgeable(true);
     } else if (m_image && !errorOccurred())
         m_image->destroyDecodedData();
 }
@@ -514,6 +524,9 @@
     if (!m_data)
         return false;
 
+    if (isPurgeable())
+        return false;
+
     if (m_data->size() < diskImageCache().minimumImageSize())
         return false;
 

Modified: trunk/Source/WebCore/loader/cache/CachedImage.h (172743 => 172744)


--- 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)
@@ -101,6 +101,7 @@
     void clearImage();
     // If not null, changeRect is the changed part of the image.
     void notifyObservers(const IntRect* changeRect = 0);
+    virtual PurgePriority purgePriority() const override { return PurgeFirst; }
     void checkShouldPaintBrokenImage();
 
     virtual void switchClientsToRevalidatedResource() override;

Modified: trunk/Source/WebCore/loader/cache/CachedResource.cpp (172743 => 172744)


--- 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)
@@ -40,6 +40,7 @@
 #include "Logging.h"
 #include "MemoryCache.h"
 #include "PlatformStrategies.h"
+#include "PurgeableBuffer.h"
 #include "ResourceBuffer.h"
 #include "ResourceHandle.h"
 #include "ResourceLoadScheduler.h"
@@ -465,6 +466,8 @@
 
 bool CachedResource::addClientToSet(CachedResourceClient* client)
 {
+    ASSERT(!isPurgeable());
+
     if (m_preloadResult == PreloadNotReferenced) {
         if (isLoaded())
             m_preloadResult = PreloadReferencedWhileComplete;
@@ -783,6 +786,64 @@
     return false;
 }
 
+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() && !m_proxyResource && !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->createPurgeableBuffer();
+        if (!m_data->hasPurgeableBuffer())
+            return false;
+
+        m_purgeableData = m_data->releasePurgeableBuffer();
+        m_purgeableData->setPurgePriority(purgePriority());
+        m_purgeableData->makePurgeable(true);
+        m_data.clear();
+        return true;
+    }
+
+    if (!m_purgeableData)
+        return true;
+    ASSERT(!m_data);
+    ASSERT(!hasClients());
+
+    if (!m_purgeableData->makePurgeable(false))
+        return false; 
+
+    m_data = ResourceBuffer::adoptSharedBuffer(SharedBuffer::adoptPurgeableBuffer(m_purgeableData.release()));
+    return true;
+}
+
+bool CachedResource::isPurgeable() const
+{
+    return m_purgeableData && m_purgeableData->isPurgeable();
+}
+
+bool CachedResource::wasPurged() const
+{
+    return m_purgeableData && m_purgeableData->wasPurged();
+}
+
 unsigned CachedResource::overheadSize() const
 {
     static const int kAverageClientsHashMapSize = 384;

Modified: trunk/Source/WebCore/loader/cache/CachedResource.h (172743 => 172744)


--- 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)
@@ -25,6 +25,7 @@
 
 #include "CachePolicy.h"
 #include "FrameLoaderTypes.h"
+#include "PurgePriority.h"
 #include "ResourceError.h"
 #include "ResourceLoadPriority.h"
 #include "ResourceLoaderOptions.h"
@@ -46,6 +47,7 @@
 class CachedResourceHandleBase;
 class CachedResourceLoader;
 class InspectorResource;
+class PurgeableBuffer;
 class ResourceBuffer;
 class SecurityOrigin;
 class SharedBuffer;
@@ -186,7 +188,7 @@
     
     void clearLoader();
 
-    ResourceBuffer* resourceBuffer() const { return m_data.get(); }
+    ResourceBuffer* resourceBuffer() const { ASSERT(!m_purgeableData); return m_data.get(); }
 
     virtual void willSendRequest(ResourceRequest&, const ResourceResponse&) { m_requestedFromNetworkingLayer = true; }
     virtual void responseReceived(const ResourceResponse&);
@@ -229,6 +231,14 @@
     bool isCacheValidator() const { return m_resourceToRevalidate; }
     CachedResource* resourceToRevalidate() const { return m_resourceToRevalidate; }
     
+    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);
+    
     // HTTP revalidation support methods for CachedResourceLoader.
     void setResourceToRevalidate(CachedResource*);
     virtual void switchClientsToRevalidatedResource();
@@ -263,6 +273,8 @@
     void setDecodedSize(unsigned);
     void didAccessDecodedData(double timeStamp);
 
+    bool isSafeToMakePurgeable() const;
+    
     HashCountedSet<CachedResourceClient*> m_clients;
 
     class CachedResourceCallback {
@@ -290,6 +302,7 @@
     double m_responseTimestamp;
 
     RefPtr<ResourceBuffer> m_data;
+    OwnPtr<PurgeableBuffer> m_purgeableData;
     DeferrableOneShotTimer m_decodedDataDeletionTimer;
 
 private:
@@ -297,6 +310,7 @@
 
     void decodedDataDeletionTimerFired();
 
+    virtual PurgePriority purgePriority() const { return PurgeDefault; }
     virtual bool mayTryReplaceEncodedData() const { return false; }
 
     double currentAge() const;

Modified: trunk/Source/WebCore/loader/cache/CachedScript.cpp (172743 => 172744)


--- 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)
@@ -71,6 +71,8 @@
 
 const String& CachedScript::script()
 {
+    ASSERT(!isPurgeable());
+
     if (!m_script && m_data) {
         m_script = m_decoder->decodeAndFlush(m_data->data(), encodedSize());
         setDecodedSize(m_script.sizeInBytes());
@@ -91,6 +93,8 @@
 {
     m_script = String();
     setDecodedSize(0);
+    if (!MemoryCache::shouldMakeResourcePurgeableOnEviction() && isSafeToMakePurgeable())
+        makePurgeable(true);
 }
 
 #if ENABLE(NOSNIFF)

Modified: trunk/Source/WebCore/loader/cache/CachedScript.h (172743 => 172744)


--- 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)
@@ -47,6 +47,7 @@
 #endif
 
     private:
+        virtual PurgePriority purgePriority() const override { return PurgeLast; }
         virtual bool mayTryReplaceEncodedData() const override { return true; }
 
         virtual bool shouldIgnoreHTTPStatusCodeErrors() const override;

Modified: trunk/Source/WebCore/loader/cache/MemoryCache.cpp (172743 => 172744)


--- 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)
@@ -212,6 +212,15 @@
 #else
     CachedResource* resource = resources.get(url);
 #endif
+    bool wasPurgeable = MemoryCache::shouldMakeResourcePurgeableOnEviction() && resource && resource->isPurgeable();
+    if (resource && !resource->makePurgeable(false)) {
+        ASSERT(!resource->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->hasClients(), resource->size());
     return resource;
 }
 
@@ -395,6 +404,19 @@
 
     int size = m_allResources.size();
  
+    // See if we have any purged resources we can evict.
+    for (int i = 0; i < size; i++) {
+        CachedResource* current = m_allResources[i].m_tail;
+        while (current) {
+            CachedResource* prev = current->m_prevInAllResourcesList;
+            if (current->wasPurged()) {
+                ASSERT(!current->hasClients());
+                ASSERT(!current->isPreloaded());
+                evict(current);
+            }
+            current = prev;
+        }
+    }
     if (targetSize && m_deadSize <= targetSize)
         return;
 
@@ -430,7 +452,9 @@
             CachedResourceHandle<CachedResource> previous = current->m_prevInAllResourcesList;
             ASSERT(!previous || previous->inCache());
             if (!current->hasClients() && !current->isPreloaded() && !current->isCacheValidator()) {
-                evict(current);
+                if (!makeResourcePurgeable(current))
+                    evict(current);
+
                 if (targetSize && m_deadSize <= targetSize)
                     return;
             }
@@ -497,6 +521,28 @@
     prune();
 }
 
+bool MemoryCache::makeResourcePurgeable(CachedResource* resource)
+{
+    if (!MemoryCache::shouldMakeResourcePurgeableOnEviction())
+        return false;
+
+    if (!resource->inCache())
+        return false;
+
+    if (resource->isPurgeable())
+        return true;
+
+    if (!resource->isSafeToMakePurgeable())
+        return false;
+
+    if (!resource->makePurgeable(true))
+        return false;
+
+    adjustSize(resource->hasClients(), -static_cast<int>(resource->size()));
+
+    return true;
+}
+
 void MemoryCache::evict(CachedResource* resource)
 {
     ASSERT(WTF::isMainThread());
@@ -521,6 +567,12 @@
         // Remove from the appropriate LRU list.
         removeFromLRUList(resource);
         removeFromLiveDecodedResourcesList(resource);
+
+        // 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->isPurgeable())
+            adjustSize(resource->hasClients(), -static_cast<int>(resource->size()));
     } else
 #if ENABLE(CACHE_PARTITIONING)
         ASSERT(!resources.get(resource->url()) || resources.get(resource->url())->get(resource->cachePartition()) != resource);
@@ -840,10 +892,15 @@
 
 void MemoryCache::TypeStatistic::addResource(CachedResource* o)
 {
+    bool purged = o->wasPurged();
+    bool purgeable = o->isPurgeable() && !purged; 
+    int pageSize = (o->encodedSize() + o->overheadSize() + 4095) & ~4095;
     count++;
-    size += o->size();
+    size += purged ? 0 : o->size(); 
     liveSize += o->hasClients() ? o->size() : 0;
     decodedSize += o->decodedSize();
+    purgeableSize += purgeable ? pageSize : 0;
+    purgedSize += purged ? pageSize : 0;
 #if ENABLE(DISK_IMAGE_CACHE)
     // Only the data inside the resource was mapped, not the entire resource.
     mappedSize += o->isUsingDiskImageCache() ? o->resourceBuffer()->sharedBuffer()->size() : 0;
@@ -944,29 +1001,29 @@
 {
     Statistics s = getStatistics();
 #if ENABLE(DISK_IMAGE_CACHE)
-    printf("%-13s %-13s %-13s %-13s %-13s %-13s %-13s\n", "", "Count", "Size", "LiveSize", "DecodedSize", "Mapped", "\"Real\"");
+    printf("%-13s %-13s %-13s %-13s %-13s %-13s %-13s %-13s %-13s\n", "", "Count", "Size", "LiveSize", "DecodedSize", "PurgeableSize", "PurgedSize", "Mapped", "\"Real\"");
+    printf("%-13s %-13s %-13s %-13s %-13s %-13s %-13s %-13s %-13s\n", "-------------", "-------------", "-------------", "-------------", "-------------", "-------------", "-------------", "-------------", "-------------");
+    printf("%-13s %13d %13d %13d %13d %13d %13d %13d %13d\n", "Images", 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("%-13s %-13s %-13s %-13s %-13s %-13s %-13s\n", "", "Count", "Size", "LiveSize", "DecodedSize", "PurgeableSize", "PurgedSize");
     printf("%-13s %-13s %-13s %-13s %-13s %-13s %-13s\n", "-------------", "-------------", "-------------", "-------------", "-------------", "-------------", "-------------");
-    printf("%-13s %13d %13d %13d %13d %13d %13d\n", "Images", s.images.count, s.images.size, s.images.liveSize, s.images.decodedSize, s.images.mappedSize, s.images.size - s.images.mappedSize);
-#else
-    printf("%-13s %-13s %-13s %-13s %-13s\n", "", "Count", "Size", "LiveSize", "DecodedSize");
-    printf("%-13s %-13s %-13s %-13s %-13s\n", "-------------", "-------------", "-------------", "-------------", "-------------");
-    printf("%-13s %13d %13d %13d %13d\n", "Images", s.images.count, s.images.size, s.images.liveSize, s.images.decodedSize);
+    printf("%-13s %13d %13d %13d %13d %13d %13d\n", "Images", s.images.count, s.images.size, s.images.liveSize, s.images.decodedSize, s.images.purgeableSize, s.images.purgedSize);
 #endif
-    printf("%-13s %13d %13d %13d %13d\n", "CSS", s.cssStyleSheets.count, s.cssStyleSheets.size, s.cssStyleSheets.liveSize, s.cssStyleSheets.decodedSize);
+    printf("%-13s %13d %13d %13d %13d %13d %13d\n", "CSS", s.cssStyleSheets.count, s.cssStyleSheets.size, s.cssStyleSheets.liveSize, s.cssStyleSheets.decodedSize, s.cssStyleSheets.purgeableSize, s.cssStyleSheets.purgedSize);
 #if ENABLE(XSLT)
-    printf("%-13s %13d %13d %13d %13d\n", "XSL", s.xslStyleSheets.count, s.xslStyleSheets.size, s.xslStyleSheets.liveSize, s.xslStyleSheets.decodedSize);
+    printf("%-13s %13d %13d %13d %13d %13d %13d\n", "XSL", s.xslStyleSheets.count, s.xslStyleSheets.size, s.xslStyleSheets.liveSize, s.xslStyleSheets.decodedSize, s.xslStyleSheets.purgeableSize, s.xslStyleSheets.purgedSize);
 #endif
-    printf("%-13s %13d %13d %13d %13d\n", "_javascript_", s.scripts.count, s.scripts.size, s.scripts.liveSize, s.scripts.decodedSize);
-    printf("%-13s %13d %13d %13d %13d\n", "Fonts", s.fonts.count, s.fonts.size, s.fonts.liveSize, s.fonts.decodedSize);
-    printf("%-13s %-13s %-13s %-13s %-13s\n\n", "-------------", "-------------", "-------------", "-------------", "-------------");
+    printf("%-13s %13d %13d %13d %13d %13d %13d\n", "_javascript_", s.scripts.count, s.scripts.size, s.scripts.liveSize, s.scripts.decodedSize, s.scripts.purgeableSize, s.scripts.purgedSize);
+    printf("%-13s %13d %13d %13d %13d %13d %13d\n", "Fonts", s.fonts.count, s.fonts.size, s.fonts.liveSize, s.fonts.decodedSize, s.fonts.purgeableSize, s.fonts.purgedSize);
+    printf("%-13s %-13s %-13s %-13s %-13s %-13s %-13s\n\n", "-------------", "-------------", "-------------", "-------------", "-------------", "-------------", "-------------");
 }
 
 void MemoryCache::dumpLRULists(bool includeLive) const
 {
 #if ENABLE(DISK_IMAGE_CACHE)
-    printf("LRU-SP lists in eviction order (Kilobytes decoded, Kilobytes encoded, Access count, Referenced, isMemoryMapped):\n");
+    printf("LRU-SP lists in eviction order (Kilobytes decoded, Kilobytes encoded, Access count, Referenced, isPurgeable, wasPurged, isMemoryMapped):\n");
 #else
-    printf("LRU-SP lists in eviction order (Kilobytes decoded, Kilobytes encoded, Access count, Referenced):\n");
+    printf("LRU-SP lists in eviction order (Kilobytes decoded, Kilobytes encoded, Access count, Referenced, isPurgeable, wasPurged):\n");
 #endif
 
     int size = m_allResources.size();
@@ -977,9 +1034,9 @@
             CachedResource* prev = current->m_prevInAllResourcesList;
             if (includeLive || !current->hasClients())
 #if ENABLE(DISK_IMAGE_CACHE)
-                printf("(%.1fK, %.1fK, %uA, %dR, %d); ", current->decodedSize() / 1024.0f, (current->encodedSize() + current->overheadSize()) / 1024.0f, current->accessCount(), current->hasClients(), current->isUsingDiskImageCache());
+                printf("(%.1fK, %.1fK, %uA, %dR, %d, %d, %d); ", current->decodedSize() / 1024.0f, (current->encodedSize() + current->overheadSize()) / 1024.0f, current->accessCount(), current->hasClients(), current->isPurgeable(), current->wasPurged(), current->isUsingDiskImageCache());
 #else
-                printf("(%.1fK, %.1fK, %uA, %dR); ", current->decodedSize() / 1024.0f, (current->encodedSize() + current->overheadSize()) / 1024.0f, current->accessCount(), current->hasClients());
+                printf("(%.1fK, %.1fK, %uA, %dR, %d, %d); ", current->decodedSize() / 1024.0f, (current->encodedSize() + current->overheadSize()) / 1024.0f, current->accessCount(), current->hasClients(), current->isPurgeable(), current->wasPurged());
 #endif
 
             current = prev;

Modified: trunk/Source/WebCore/loader/cache/MemoryCache.h (172743 => 172744)


--- 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)
@@ -61,6 +61,22 @@
 // -------|-----+++++++++++++++|
 // -------|-----+++++++++++++++|+++++
 
+// 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.
+
 class MemoryCache {
     WTF_MAKE_NONCOPYABLE(MemoryCache); WTF_MAKE_FAST_ALLOCATED;
 public:
@@ -85,21 +101,14 @@
         int size;
         int liveSize;
         int decodedSize;
+        int purgeableSize;
+        int purgedSize;
 #if ENABLE(DISK_IMAGE_CACHE)
         int mappedSize;
+        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) { }
 #endif
-
-        TypeStatistic()
-            : count(0)
-            , size(0)
-            , liveSize(0)
-            , decodedSize(0)
-#if ENABLE(DISK_IMAGE_CACHE)
-            , mappedSize(0)
-#endif
-        {
-        }
-
         void addResource(CachedResource*);
     };
     
@@ -158,6 +167,8 @@
     void addToLiveResourcesSize(CachedResource*);
     void removeFromLiveResourcesSize(CachedResource*);
 
+    static bool shouldMakeResourcePurgeableOnEviction();
+
 #if ENABLE(DISK_IMAGE_CACHE)
     void flushCachedImagesToDisk(); // Flush encoded data from resources still referenced by web pages.
 #endif
@@ -211,6 +222,7 @@
     unsigned liveCapacity() const;
     unsigned deadCapacity() const;
 
+    bool makeResourcePurgeable(CachedResource*);
     void evict(CachedResource*);
 
     CachedResource* resourceForRequestImpl(const ResourceRequest&, CachedResourceMap&);
@@ -246,6 +258,15 @@
     SessionCachedResourceMap m_sessionResources;
 };
 
+inline bool MemoryCache::shouldMakeResourcePurgeableOnEviction()
+{
+#if PLATFORM(IOS)
+    return true;
+#else
+    return false;
+#endif
+}
+
 // Function to obtain the global cache.
 MemoryCache* memoryCache();
 

Added: trunk/Source/WebCore/platform/PurgePriority.h (0 => 172744)


--- trunk/Source/WebCore/platform/PurgePriority.h	                        (rev 0)
+++ trunk/Source/WebCore/platform/PurgePriority.h	2014-08-19 05:10:23 UTC (rev 172744)
@@ -0,0 +1,39 @@
+/*
+ * 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

Added: trunk/Source/WebCore/platform/PurgeableBuffer.h (0 => 172744)


--- trunk/Source/WebCore/platform/PurgeableBuffer.h	                        (rev 0)
+++ trunk/Source/WebCore/platform/PurgeableBuffer.h	2014-08-19 05:10:23 UTC (rev 172744)
@@ -0,0 +1,77 @@
+/*
+ * 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 "PurgePriority.h"
+#include <wtf/PassOwnPtr.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+    class PurgeableBuffer {
+        WTF_MAKE_NONCOPYABLE(PurgeableBuffer);
+    public:
+        static PassOwnPtr<PurgeableBuffer> createUninitialized(size_t, char*& data);
+        static PassOwnPtr<PurgeableBuffer> 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<PurgeableBuffer> PurgeableBuffer::createUninitialized(size_t, char*&) { return nullptr; }
+    inline PassOwnPtr<PurgeableBuffer> 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

Modified: trunk/Source/WebCore/platform/SharedBuffer.cpp (172743 => 172744)


--- 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)
@@ -27,6 +27,7 @@
 #include "config.h"
 #include "SharedBuffer.h"
 
+#include "PurgeableBuffer.h"
 #include <wtf/PassOwnPtr.h>
 #include <wtf/unicode/UTF8.h>
 
@@ -65,6 +66,7 @@
 SharedBuffer::SharedBuffer()
     : m_size(0)
     , m_buffer(adoptRef(new DataBuffer))
+    , m_shouldUsePurgeableMemory(false)
 #if ENABLE(DISK_IMAGE_CACHE)
     , m_isMemoryMapped(false)
     , m_diskImageCacheId(DiskImageCache::invalidDiskCacheId)
@@ -77,6 +79,7 @@
 SharedBuffer::SharedBuffer(unsigned size)
     : m_size(size)
     , m_buffer(adoptRef(new DataBuffer))
+    , m_shouldUsePurgeableMemory(false)
 #if ENABLE(DISK_IMAGE_CACHE)
     , m_isMemoryMapped(false)
     , m_diskImageCacheId(DiskImageCache::invalidDiskCacheId)
@@ -89,6 +92,7 @@
 SharedBuffer::SharedBuffer(const char* data, unsigned size)
     : m_size(0)
     , m_buffer(adoptRef(new DataBuffer))
+    , m_shouldUsePurgeableMemory(false)
 #if ENABLE(DISK_IMAGE_CACHE)
     , m_isMemoryMapped(false)
     , m_diskImageCacheId(DiskImageCache::invalidDiskCacheId)
@@ -102,6 +106,7 @@
 SharedBuffer::SharedBuffer(const unsigned char* data, unsigned size)
     : m_size(0)
     , m_buffer(adoptRef(new DataBuffer))
+    , m_shouldUsePurgeableMemory(false)
 #if ENABLE(DISK_IMAGE_CACHE)
     , m_isMemoryMapped(false)
     , m_diskImageCacheId(DiskImageCache::invalidDiskCacheId)
@@ -132,11 +137,22 @@
     return buffer.release();
 }
 
+PassRefPtr<SharedBuffer> SharedBuffer::adoptPurgeableBuffer(PassOwnPtr<PurgeableBuffer> purgeableBuffer) 
+{ 
+    ASSERT(!purgeableBuffer->isPurgeable());
+    RefPtr<SharedBuffer> buffer = create();
+    buffer->m_purgeableBuffer = purgeableBuffer;
+    return buffer.release();
+}
+
 unsigned SharedBuffer::size() const
 {
     if (hasPlatformData())
         return platformDataSize();
     
+    if (m_purgeableBuffer)
+        return m_purgeableBuffer->size();
+    
     return m_size;
 }
 
@@ -200,6 +216,44 @@
 }
 #endif
 
+// 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->hasOneRef())
+        return;
+
+    if (!m_shouldUsePurgeableMemory)
+        return;
+
+    char* destination = 0;
+    m_purgeableBuffer = PurgeableBuffer::createUninitialized(m_size, destination);
+    if (!m_purgeableBuffer)
+        return;
+    unsigned bufferSize = m_buffer->data.size();
+    if (bufferSize) {
+        memcpy(destination, m_buffer->data.data(), bufferSize);
+        destination += bufferSize;
+        (const_cast<SharedBuffer*>(this))->clearDataBuffer();
+    }
+    copyBufferAndClear(destination, m_size - bufferSize);
+}
+
 const char* SharedBuffer::data() const
 {
 #if ENABLE(DISK_IMAGE_CACHE)
@@ -215,6 +269,11 @@
         return buffer;
 #endif
 
+    createPurgeableBuffer();
+
+    if (m_purgeableBuffer)
+        return m_purgeableBuffer->data();
+    
     return this->buffer().data();
 }
 
@@ -257,6 +316,7 @@
 
 void SharedBuffer::append(const char* data, unsigned length)
 {
+    ASSERT(!m_purgeableBuffer);
 #if ENABLE(DISK_IMAGE_CACHE)
     ASSERT(!isMemoryMapped());
 #endif
@@ -326,12 +386,13 @@
 
     m_size = 0;
     clearDataBuffer();
+    m_purgeableBuffer.clear();
 }
 
 PassRefPtr<SharedBuffer> SharedBuffer::copy() const
 {
     RefPtr<SharedBuffer> clone(adoptRef(new SharedBuffer));
-    if (hasPlatformData()) {
+    if (m_purgeableBuffer || hasPlatformData()) {
         clone->append(data(), size());
         return clone;
     }
@@ -349,6 +410,12 @@
     return clone;
 }
 
+PassOwnPtr<PurgeableBuffer> SharedBuffer::releasePurgeableBuffer()
+{ 
+    ASSERT(hasOneRef()); 
+    return m_purgeableBuffer.release(); 
+}
+
 void SharedBuffer::duplicateDataBufferIfNecessary() const
 {
     if (m_buffer->hasOneRef() || m_size <= m_buffer->data.capacity())
@@ -419,7 +486,7 @@
     }
 #endif
 
-    if (hasPlatformData()) {
+    if (hasPlatformData() || m_purgeableBuffer) {
         ASSERT_WITH_SECURITY_IMPLICATION(position < size());
         someData = data() + position;
         return totalSize - position;

Modified: trunk/Source/WebCore/platform/SharedBuffer.h (172743 => 172744)


--- 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)
@@ -49,6 +49,8 @@
 
 namespace WebCore {
     
+class PurgeableBuffer;
+
 class SharedBuffer : public RefCounted<SharedBuffer> {
 public:
     static PassRefPtr<SharedBuffer> create() { return adoptRef(new SharedBuffer); }
@@ -60,6 +62,10 @@
 
     static PassRefPtr<SharedBuffer> adoptVector(Vector<char>& vector);
     
+    // The buffer must be in non-purgeable state before adopted to a SharedBuffer. 
+    // It will stay that way until released.
+    static PassRefPtr<SharedBuffer> adoptPurgeableBuffer(PassOwnPtr<PurgeableBuffer>);
+    
     ~SharedBuffer();
     
 #if USE(FOUNDATION)
@@ -104,6 +110,11 @@
 
     PassRefPtr<SharedBuffer> copy() const;
     
+    bool hasPurgeableBuffer() const { return m_purgeableBuffer.get(); }
+
+    // Ensure this buffer has no other clients before calling this.
+    PassOwnPtr<PurgeableBuffer> releasePurgeableBuffer();
+
     // Return the number of consecutive bytes after "position". "data"
     // points to the first byte.
     // Return 0 when no more data left.
@@ -118,6 +129,8 @@
     //      }
     unsigned getSomeData(const char*& data, unsigned position = 0) const;
 
+    void shouldUsePurgeableMemory(bool use) { m_shouldUsePurgeableMemory = use; }
+
 #if ENABLE(DISK_IMAGE_CACHE)
     enum MemoryMappingState { QueuedForMapping, PreviouslyQueuedForMapping, SuccessAlreadyMapped, FailureCacheFull };
 
@@ -142,6 +155,8 @@
     void setMemoryMappedNotificationCallback(MemoryMappedNotifyCallback, MemoryMappedNotifyCallbackData);
 #endif
 
+    void createPurgeableBuffer() const;
+
     void tryReplaceContentsWithPlatformBuffer(SharedBuffer*);
     bool hasPlatformData() const;
 
@@ -158,6 +173,8 @@
     // Calling this function will force internal segmented buffers
     // to be merged into a flat buffer. Use getSomeData() whenever possible
     // for better performance.
+    // As well, be aware that this method does *not* return any purgeable
+    // memory, which can be a source of bugs.
     const Vector<char>& buffer() const;
 
     void clearPlatformData();
@@ -173,6 +190,8 @@
     unsigned m_size;
     mutable RefPtr<DataBuffer> m_buffer;
 
+    bool m_shouldUsePurgeableMemory;
+    mutable OwnPtr<PurgeableBuffer> m_purgeableBuffer;
 #if USE(NETWORK_CFDATA_ARRAY_CALLBACK)
     explicit SharedBuffer(CFArrayRef);
     mutable Vector<RetainPtr<CFDataRef>> m_dataArray;

Modified: trunk/Source/WebCore/platform/cf/SharedBufferCF.cpp (172743 => 172744)


--- 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)
@@ -28,6 +28,7 @@
 #include "config.h"
 #include "SharedBuffer.h"
 
+#include "PurgeableBuffer.h"
 #include <wtf/cf/TypeCasts.h>
 
 #if ENABLE(DISK_IMAGE_CACHE)
@@ -39,6 +40,7 @@
 SharedBuffer::SharedBuffer(CFDataRef cfData)
     : m_size(0)
     , m_buffer(adoptRef(new DataBuffer))
+    , m_shouldUsePurgeableMemory(false)
 #if ENABLE(DISK_IMAGE_CACHE)
     , m_isMemoryMapped(false)
     , m_diskImageCacheId(DiskImageCache::invalidDiskCacheId)
@@ -128,6 +130,7 @@
 SharedBuffer::SharedBuffer(CFArrayRef cfDataArray)
     : m_size(0)
     , m_buffer(adoptRef(new DataBuffer))
+    , m_shouldUsePurgeableMemory(false)
 #if ENABLE(DISK_IMAGE_CACHE)
     , m_isMemoryMapped(false)
     , m_diskImageCacheId(DiskImageCache::invalidDiskCacheId)

Added: trunk/Source/WebCore/platform/mac/PurgeableBufferMac.cpp (0 => 172744)


--- 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)
@@ -0,0 +1,159 @@
+/*
+ * 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 "config.h"
+
+#if ENABLE(PURGEABLE_MEMORY)
+
+#include "PurgeableBuffer.h"
+
+#include <mach/mach.h>
+#include <wtf/Assertions.h>
+#include <wtf/VMTags.h>
+
+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<vm_address_t>(m_data), m_size);
+}
+
+PassOwnPtr<PurgeableBuffer> PurgeableBuffer::createUninitialized(size_t size, char*& data)
+{
+    if (size < minPurgeableBufferSize)
+        return nullptr;
+
+    vm_address_t buffer = 0;
+    kern_return_t ret = vm_allocate(mach_task_self(), &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 = ""
+    return adoptPtr(new PurgeableBuffer(data, size));
+}
+
+PassOwnPtr<PurgeableBuffer> PurgeableBuffer::create(const char* data, size_t size)
+{
+    char* destination;
+    OwnPtr<PurgeableBuffer> 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 "purgeable" is the correct spelling and the API here is misspelled.
+        kern_return_t ret = vm_purgable_control(mach_task_self(), reinterpret_cast<vm_address_t>(m_data), VM_PURGABLE_SET_STATE, &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<vm_address_t>(m_data), VM_PURGABLE_SET_STATE, &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 & 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<vm_address_t>(m_data), VM_PURGABLE_GET_STATE, &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 & VM_PURGABLE_EMPTY) {
+        m_state = Purged;
+        return true;
+    }
+        
+    return false;
+}
+
+const char* PurgeableBuffer::data() const
+{
+    ASSERT(m_state == NonVolatile);
+    return m_data;
+}
+    
+}
+
+#endif

Modified: trunk/Source/WebCore/platform/mac/SharedBufferMac.mm (172743 => 172744)


--- 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)
@@ -152,6 +152,12 @@
 #endif
 
     data(); // Force data into m_buffer from segments or data array.
+    if (hasPurgeableBuffer()) {
+        RefPtr<SharedBuffer::DataBuffer> copiedBuffer = adoptRef(new DataBuffer);
+        copiedBuffer->data.append(data(), size());
+        return adoptCF((CFDataRef)adoptNS([[WebCoreSharedBufferData alloc] initWithSharedBufferDataBuffer:copiedBuffer.get()]).leakRef());
+    }
+
     return adoptCF((CFDataRef)adoptNS([[WebCoreSharedBufferData alloc] initWithSharedBufferDataBuffer:m_buffer.get()]).leakRef());
 }
 

Modified: trunk/Source/WebCore/platform/soup/SharedBufferSoup.cpp (172743 => 172744)


--- 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)
@@ -22,6 +22,7 @@
 
 #include "SharedBuffer.h"
 
+#include "PurgeableBuffer.h"
 #include <libsoup/soup.h>
 
 namespace WebCore {

Modified: trunk/Source/WebKit/mac/ChangeLog (172743 => 172744)


--- 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)
@@ -1,3 +1,16 @@
+2014-08-18  Commit Queue  <[email protected]>
+
+        Unreviewed, rolling out r172736.
+        https://bugs.webkit.org/show_bug.cgi?id=136060
+
+        Caused 14% PLT regressions (Requested by rniwa on #webkit).
+
+        Reverted changeset:
+
+        "Remove PurgeableBuffer since it is not very useful any more"
+        https://bugs.webkit.org/show_bug.cgi?id=135939
+        http://trac.webkit.org/changeset/172736
+
 2014-08-18  Pratik Solanki  <[email protected]>
 
         Remove PurgeableBuffer since it is not very useful any more

Modified: trunk/Source/WebKit/mac/Misc/WebCache.mm (172743 => 172744)


--- 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)
@@ -108,6 +108,26 @@
 #endif
             [NSNumber numberWithInt:s.scripts.decodedSize], @"_javascript_",
             nil],
+        [NSDictionary dictionaryWithObjectsAndKeys:
+            [NSNumber numberWithInt:s.images.purgeableSize], @"Images",
+            [NSNumber numberWithInt:s.cssStyleSheets.purgeableSize] ,@"CSS",
+#if ENABLE(XSLT)
+            [NSNumber numberWithInt:s.xslStyleSheets.purgeableSize], @"XSL",
+#else
+            [NSNumber numberWithInt:0], @"XSL",
+#endif
+            [NSNumber numberWithInt:s.scripts.purgeableSize], @"_javascript_",
+            nil],
+        [NSDictionary dictionaryWithObjectsAndKeys:
+            [NSNumber numberWithInt:s.images.purgedSize], @"Images",
+            [NSNumber numberWithInt:s.cssStyleSheets.purgedSize] ,@"CSS",
+#if ENABLE(XSLT)
+            [NSNumber numberWithInt:s.xslStyleSheets.purgedSize], @"XSL",
+#else
+            [NSNumber numberWithInt:0], @"XSL",
+#endif
+            [NSNumber numberWithInt:s.scripts.purgedSize], @"_javascript_",
+            nil],
 #if ENABLE(DISK_IMAGE_CACHE) && PLATFORM(IOS)
         [NSDictionary dictionaryWithObjectsAndKeys:
             [NSNumber numberWithInt:s.images.mappedSize], @"Images",

Modified: trunk/Source/WebKit/win/ChangeLog (172743 => 172744)


--- 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)
@@ -1,3 +1,16 @@
+2014-08-18  Commit Queue  <[email protected]>
+
+        Unreviewed, rolling out r172736.
+        https://bugs.webkit.org/show_bug.cgi?id=136060
+
+        Caused 14% PLT regressions (Requested by rniwa on #webkit).
+
+        Reverted changeset:
+
+        "Remove PurgeableBuffer since it is not very useful any more"
+        https://bugs.webkit.org/show_bug.cgi?id=135939
+        http://trac.webkit.org/changeset/172736
+
 2014-08-18  Pratik Solanki  <[email protected]>
 
         Remove PurgeableBuffer since it is not very useful any more

Modified: trunk/Source/WebKit/win/WebCache.cpp (172743 => 172744)


--- 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)
@@ -202,6 +202,52 @@
     propBag->setDictionary(dictionary.get());
     s[3] = propBag.leakRef();
 
+    // Purgable Sizes.
+    dictionary = adoptCF(CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
+
+    value = adoptCF(CFNumberCreate(0, kCFNumberIntType, &stat.images.purgeableSize));
+    CFDictionaryAddValue(dictionary.get(), imagesKey, value.get());
+
+    value = adoptCF(CFNumberCreate(0, kCFNumberIntType, &stat.cssStyleSheets.purgeableSize));
+    CFDictionaryAddValue(dictionary.get(), stylesheetsKey, value.get());
+
+#if ENABLE(XSLT)
+    value = adoptCF(CFNumberCreate(0, kCFNumberIntType, &stat.xslStyleSheets.purgeableSize));
+#else
+    value = adoptCF(CFNumberCreate(0, kCFNumberIntType, &zero));
+#endif
+    CFDictionaryAddValue(dictionary.get(), xslKey, value.get());
+
+    value = adoptCF(CFNumberCreate(0, kCFNumberIntType, &stat.scripts.purgeableSize));
+    CFDictionaryAddValue(dictionary.get(), scriptsKey, value.get());
+
+    propBag = CFDictionaryPropertyBag::createInstance();
+    propBag->setDictionary(dictionary.get());
+    s[4] = propBag.leakRef();
+
+    // Purged Sizes.
+    dictionary = adoptCF(CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
+
+    value = adoptCF(CFNumberCreate(0, kCFNumberIntType, &stat.images.purgedSize));
+    CFDictionaryAddValue(dictionary.get(), imagesKey, value.get());
+
+    value = adoptCF(CFNumberCreate(0, kCFNumberIntType, &stat.cssStyleSheets.purgedSize));
+    CFDictionaryAddValue(dictionary.get(), stylesheetsKey, value.get());
+
+#if ENABLE(XSLT)
+    value = adoptCF(CFNumberCreate(0, kCFNumberIntType, &stat.xslStyleSheets.purgedSize));
+#else
+    value = adoptCF(CFNumberCreate(0, kCFNumberIntType, &zero));
+#endif
+    CFDictionaryAddValue(dictionary.get(), xslKey, value.get());
+
+    value = adoptCF(CFNumberCreate(0, kCFNumberIntType, &stat.scripts.purgedSize));
+    CFDictionaryAddValue(dictionary.get(), scriptsKey, value.get());
+
+    propBag = CFDictionaryPropertyBag::createInstance();
+    propBag->setDictionary(dictionary.get());
+    s[5] = propBag.leakRef();
+
     return S_OK;
 }
 

Modified: trunk/Source/WebKit2/ChangeLog (172743 => 172744)


--- 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)
@@ -1,3 +1,16 @@
+2014-08-18  Commit Queue  <[email protected]>
+
+        Unreviewed, rolling out r172736.
+        https://bugs.webkit.org/show_bug.cgi?id=136060
+
+        Caused 14% PLT regressions (Requested by rniwa on #webkit).
+
+        Reverted changeset:
+
+        "Remove PurgeableBuffer since it is not very useful any more"
+        https://bugs.webkit.org/show_bug.cgi?id=135939
+        http://trac.webkit.org/changeset/172736
+
 2014-08-18  Simon Fraser  <[email protected]>
 
         Provide default implementations of all GraphicsLayerClient methods

Modified: trunk/Source/WebKit2/WebProcess/WebProcess.cpp (172743 => 172744)


--- 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)
@@ -885,6 +885,20 @@
     decodedSizes.set(xslString, memoryCacheStatistics.xslStyleSheets.decodedSize);
     decodedSizes.set(_javascript_String, memoryCacheStatistics.scripts.decodedSize);
     result.append(decodedSizes);
+    
+    HashMap<String, uint64_t> purgeableSizes;
+    purgeableSizes.set(imagesString, memoryCacheStatistics.images.purgeableSize);
+    purgeableSizes.set(cssString, memoryCacheStatistics.cssStyleSheets.purgeableSize);
+    purgeableSizes.set(xslString, memoryCacheStatistics.xslStyleSheets.purgeableSize);
+    purgeableSizes.set(_javascript_String, memoryCacheStatistics.scripts.purgeableSize);
+    result.append(purgeableSizes);
+    
+    HashMap<String, uint64_t> purgedSizes;
+    purgedSizes.set(imagesString, memoryCacheStatistics.images.purgedSize);
+    purgedSizes.set(cssString, memoryCacheStatistics.cssStyleSheets.purgedSize);
+    purgedSizes.set(xslString, memoryCacheStatistics.xslStyleSheets.purgedSize);
+    purgedSizes.set(_javascript_String, memoryCacheStatistics.scripts.purgedSize);
+    result.append(purgedSizes);
 }
 
 void WebProcess::getWebCoreStatistics(uint64_t callbackID)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to