Access MemoryPressureHandler global instance via a singleton() static member function
[WebKit-https.git] / Source / WebCore / platform / MemoryPressureHandler.cpp
1 /*
2  * Copyright (C) 2011, 2014 Apple Inc. All Rights Reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "MemoryPressureHandler.h"
28
29 #include "CSSValuePool.h"
30 #include "Document.h"
31 #include "FontCache.h"
32 #include "FontCascade.h"
33 #include "GCController.h"
34 #include "JSDOMWindow.h"
35 #include "MemoryCache.h"
36 #include "Page.h"
37 #include "PageCache.h"
38 #include "ScrollingThread.h"
39 #include "WorkerThread.h"
40 #include <wtf/CurrentTime.h>
41 #include <wtf/FastMalloc.h>
42 #include <wtf/Functional.h>
43 #include <wtf/StdLibExtras.h>
44
45 namespace WebCore {
46
47 WEBCORE_EXPORT bool MemoryPressureHandler::ReliefLogger::s_loggingEnabled = false;
48
49 MemoryPressureHandler& MemoryPressureHandler::singleton()
50 {
51     static NeverDestroyed<MemoryPressureHandler> memoryPressureHandler;
52     return memoryPressureHandler;
53 }
54
55 MemoryPressureHandler::MemoryPressureHandler() 
56     : m_installed(false)
57     , m_lastRespondTime(0)
58     , m_lowMemoryHandler([this] (bool critical) { releaseMemory(critical); })
59     , m_underMemoryPressure(false)
60 #if PLATFORM(IOS)
61     // FIXME: Can we share more of this with OpenSource?
62     , m_memoryPressureReason(MemoryPressureReasonNone)
63     , m_clearPressureOnMemoryRelease(true)
64     , m_releaseMemoryBlock(0)
65     , m_observer(0)
66 #elif OS(LINUX)
67     , m_eventFD(0)
68     , m_pressureLevelFD(0)
69     , m_threadID(0)
70     , m_holdOffTimer(*this, &MemoryPressureHandler::holdOffTimerFired)
71 #endif
72 {
73 }
74
75 void MemoryPressureHandler::releaseNoncriticalMemory()
76 {
77     {
78         ReliefLogger log("Purge inactive FontData");
79         fontCache().purgeInactiveFontData();
80     }
81
82     {
83         ReliefLogger log("Clear WidthCaches");
84         clearWidthCaches();
85     }
86
87     {
88         ReliefLogger log("Discard Selector Query Cache");
89         for (auto* document : Document::allDocuments())
90             document->clearSelectorQueryCache();
91     }
92
93     {
94         ReliefLogger log("Clearing JS string cache");
95         JSDOMWindow::commonVM().stringCache.clear();
96     }
97 }
98
99 void MemoryPressureHandler::releaseCriticalMemory()
100 {
101     {
102         ReliefLogger log("Empty the PageCache");
103         // Right now, the only reason we call release critical memory while not under memory pressure is if the process is about to be suspended.
104         PruningReason pruningReason = isUnderMemoryPressure() ? PruningReason::MemoryPressure : PruningReason::ProcessSuspended;
105         PageCache::singleton().pruneToSizeNow(0, pruningReason);
106     }
107
108     {
109         ReliefLogger log("Prune MemoryCache");
110         MemoryCache::singleton().evictResources();
111     }
112
113     {
114         ReliefLogger log("Drain CSSValuePool");
115         cssValuePool().drain();
116     }
117
118     {
119         ReliefLogger log("Discard StyleResolvers");
120         for (auto* document : Document::allDocuments())
121             document->clearStyleResolver();
122     }
123
124     {
125         ReliefLogger log("Discard all JIT-compiled code");
126         gcController().discardAllCompiledCode();
127     }
128 }
129
130 void MemoryPressureHandler::releaseMemory(bool critical)
131 {
132     releaseNoncriticalMemory();
133
134     if (critical)
135         releaseCriticalMemory();
136
137     platformReleaseMemory(critical);
138
139     {
140         ReliefLogger log("Release free FastMalloc memory");
141         // FastMalloc has lock-free thread specific caches that can only be cleared from the thread itself.
142         WorkerThread::releaseFastMallocFreeMemoryInAllThreads();
143 #if ENABLE(ASYNC_SCROLLING) && !PLATFORM(IOS)
144         ScrollingThread::dispatch(WTF::releaseFastMallocFreeMemory);
145 #endif
146         WTF::releaseFastMallocFreeMemory();
147     }
148 }
149
150 #if !PLATFORM(COCOA) && !OS(LINUX)
151 void MemoryPressureHandler::install() { }
152 void MemoryPressureHandler::uninstall() { }
153 void MemoryPressureHandler::holdOff(unsigned) { }
154 void MemoryPressureHandler::respondToMemoryPressure(bool) { }
155 void MemoryPressureHandler::platformReleaseMemory(bool) { }
156 void MemoryPressureHandler::ReliefLogger::platformLog() { }
157 size_t MemoryPressureHandler::ReliefLogger::platformMemoryUsage() { return 0; }
158 #endif
159
160 } // namespace WebCore