7f3a21d6c32907be834c9d967bbe89b5c13801f7
[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/StdLibExtras.h>
43
44 namespace WebCore {
45
46 WEBCORE_EXPORT bool MemoryPressureHandler::ReliefLogger::s_loggingEnabled = false;
47
48 MemoryPressureHandler& MemoryPressureHandler::singleton()
49 {
50     static NeverDestroyed<MemoryPressureHandler> memoryPressureHandler;
51     return memoryPressureHandler;
52 }
53
54 MemoryPressureHandler::MemoryPressureHandler() 
55     : m_installed(false)
56     , m_lastRespondTime(0)
57     , m_lowMemoryHandler([this] (bool critical) { releaseMemory(critical); })
58     , m_underMemoryPressure(false)
59 #if PLATFORM(IOS)
60     // FIXME: Can we share more of this with OpenSource?
61     , m_memoryPressureReason(MemoryPressureReasonNone)
62     , m_clearPressureOnMemoryRelease(true)
63     , m_releaseMemoryBlock(0)
64     , m_observer(0)
65 #elif OS(LINUX)
66     , m_eventFD(0)
67     , m_pressureLevelFD(0)
68     , m_threadID(0)
69     , m_holdOffTimer(*this, &MemoryPressureHandler::holdOffTimerFired)
70 #endif
71 {
72 }
73
74 void MemoryPressureHandler::releaseNoncriticalMemory()
75 {
76     {
77         ReliefLogger log("Purge inactive FontData");
78         FontCache::singleton().purgeInactiveFontData();
79     }
80
81     {
82         ReliefLogger log("Clear WidthCaches");
83         clearWidthCaches();
84     }
85
86     {
87         ReliefLogger log("Discard Selector Query Cache");
88         for (auto* document : Document::allDocuments())
89             document->clearSelectorQueryCache();
90     }
91
92     {
93         ReliefLogger log("Clearing JS string cache");
94         JSDOMWindow::commonVM().stringCache.clear();
95     }
96
97     {
98         ReliefLogger log("Prune MemoryCache dead resources");
99         MemoryCache::singleton().pruneDeadResourcesToSize(0);
100     }
101 }
102
103 void MemoryPressureHandler::releaseCriticalMemory()
104 {
105     {
106         ReliefLogger log("Empty the PageCache");
107         // Right now, the only reason we call release critical memory while not under memory pressure is if the process is about to be suspended.
108         PruningReason pruningReason = isUnderMemoryPressure() ? PruningReason::MemoryPressure : PruningReason::ProcessSuspended;
109         PageCache::singleton().pruneToSizeNow(0, pruningReason);
110     }
111
112     {
113         ReliefLogger log("Prune MemoryCache live resources");
114         MemoryCache::singleton().pruneLiveResourcesToSize(0);
115     }
116
117     {
118         ReliefLogger log("Drain CSSValuePool");
119         cssValuePool().drain();
120     }
121
122     {
123         ReliefLogger log("Discard StyleResolvers");
124         for (auto* document : Document::allDocuments())
125             document->clearStyleResolver();
126     }
127
128     {
129         ReliefLogger log("Discard all JIT-compiled code");
130         gcController().discardAllCompiledCode();
131     }
132
133     {
134         ReliefLogger log("Invalidate font cache");
135         FontCache::singleton().invalidate();
136     }
137 }
138
139 void MemoryPressureHandler::releaseMemory(bool critical)
140 {
141     if (critical)
142         releaseCriticalMemory();
143
144     releaseNoncriticalMemory();
145
146     platformReleaseMemory(critical);
147
148     {
149         ReliefLogger log("Release free FastMalloc memory");
150         // FastMalloc has lock-free thread specific caches that can only be cleared from the thread itself.
151         WorkerThread::releaseFastMallocFreeMemoryInAllThreads();
152 #if ENABLE(ASYNC_SCROLLING) && !PLATFORM(IOS)
153         ScrollingThread::dispatch(WTF::releaseFastMallocFreeMemory);
154 #endif
155         WTF::releaseFastMallocFreeMemory();
156     }
157 }
158
159 #if !PLATFORM(COCOA) && !OS(LINUX)
160 void MemoryPressureHandler::install() { }
161 void MemoryPressureHandler::uninstall() { }
162 void MemoryPressureHandler::holdOff(unsigned) { }
163 void MemoryPressureHandler::respondToMemoryPressure(bool) { }
164 void MemoryPressureHandler::platformReleaseMemory(bool) { }
165 void MemoryPressureHandler::ReliefLogger::platformLog() { }
166 size_t MemoryPressureHandler::ReliefLogger::platformMemoryUsage() { return 0; }
167 #endif
168
169 } // namespace WebCore