2 * Copyright (C) 2013 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #include "wtf/Partitions.h"
34 #include "wtf/Alias.h"
35 #include "wtf/DefaultAllocator.h"
36 #include "wtf/FastMalloc.h"
37 #include "wtf/MainThread.h"
41 int Partitions::s_initializationLock
= 0;
42 bool Partitions::s_initialized
= false;
44 PartitionAllocatorGeneric
Partitions::m_fastMallocAllocator
;
45 PartitionAllocatorGeneric
Partitions::m_bufferAllocator
;
46 SizeSpecificPartitionAllocator
<3328> Partitions::m_nodeAllocator
;
47 SizeSpecificPartitionAllocator
<1024> Partitions::m_layoutAllocator
;
48 HistogramEnumerationFunction
Partitions::m_histogramEnumeration
= nullptr;
50 void Partitions::initialize()
52 spinLockLock(&s_initializationLock
);
55 partitionAllocGlobalInit(&Partitions::handleOutOfMemory
);
56 m_fastMallocAllocator
.init();
57 m_bufferAllocator
.init();
58 m_nodeAllocator
.init();
59 m_layoutAllocator
.init();
63 spinLockUnlock(&s_initializationLock
);
66 void Partitions::setHistogramEnumeration(HistogramEnumerationFunction histogramEnumeration
)
68 ASSERT(!m_histogramEnumeration
);
69 m_histogramEnumeration
= histogramEnumeration
;
72 void Partitions::shutdown()
74 // We could ASSERT here for a memory leak within the partition, but it leads
75 // to very hard to diagnose ASSERTs, so it's best to leave leak checking for
76 // the valgrind and heapcheck bots, which run without partitions.
77 (void) m_layoutAllocator
.shutdown();
78 (void) m_nodeAllocator
.shutdown();
79 (void) m_bufferAllocator
.shutdown();
80 (void) m_fastMallocAllocator
.shutdown();
83 void Partitions::decommitFreeableMemory()
85 ASSERT(isMainThread());
87 partitionPurgeMemoryGeneric(bufferPartition(), PartitionPurgeDecommitEmptyPages
);
88 partitionPurgeMemoryGeneric(fastMallocPartition(), PartitionPurgeDecommitEmptyPages
);
89 partitionPurgeMemory(nodePartition(), PartitionPurgeDecommitEmptyPages
);
90 partitionPurgeMemory(layoutPartition(), PartitionPurgeDecommitEmptyPages
);
93 void Partitions::reportMemoryUsageHistogram()
95 static size_t supportedMaxSizeInMB
= 4 * 1024;
96 static size_t observedMaxSizeInMB
= 0;
98 if (!m_histogramEnumeration
)
100 // We only report the memory in the main thread.
103 // +1 is for rounding up the sizeInMB.
104 size_t sizeInMB
= Partitions::totalSizeOfCommittedPages() / 1024 / 1024 + 1;
105 if (sizeInMB
>= supportedMaxSizeInMB
)
106 sizeInMB
= supportedMaxSizeInMB
- 1;
107 if (sizeInMB
> observedMaxSizeInMB
) {
108 // Send a UseCounter only when we see the highest memory usage
110 m_histogramEnumeration("PartitionAlloc.CommittedSize", sizeInMB
, supportedMaxSizeInMB
);
111 observedMaxSizeInMB
= sizeInMB
;
115 void Partitions::dumpMemoryStats(bool isLightDump
, PartitionStatsDumper
* partitionStatsDumper
)
117 // Object model and rendering partitions are not thread safe and can be
118 // accessed only on the main thread.
119 ASSERT(isMainThread());
121 partitionDumpStatsGeneric(fastMallocPartition(), "fast_malloc", isLightDump
, partitionStatsDumper
);
122 partitionDumpStatsGeneric(bufferPartition(), "buffer", isLightDump
, partitionStatsDumper
);
123 partitionDumpStats(nodePartition(), "node", isLightDump
, partitionStatsDumper
);
124 partitionDumpStats(layoutPartition(), "layout", isLightDump
, partitionStatsDumper
);
127 static NEVER_INLINE
void partitionsOutOfMemoryUsing2G()
129 size_t signature
= 2UL * 1024 * 1024 * 1024;
134 static NEVER_INLINE
void partitionsOutOfMemoryUsing1G()
136 size_t signature
= 1UL * 1024 * 1024 * 1024;
141 static NEVER_INLINE
void partitionsOutOfMemoryUsing512M()
143 size_t signature
= 512 * 1024 * 1024;
148 static NEVER_INLINE
void partitionsOutOfMemoryUsing256M()
150 size_t signature
= 256 * 1024 * 1024;
155 static NEVER_INLINE
void partitionsOutOfMemoryUsing128M()
157 size_t signature
= 128 * 1024 * 1024;
162 static NEVER_INLINE
void partitionsOutOfMemoryUsing64M()
164 size_t signature
= 64 * 1024 * 1024;
169 static NEVER_INLINE
void partitionsOutOfMemoryUsing32M()
171 size_t signature
= 32 * 1024 * 1024;
176 static NEVER_INLINE
void partitionsOutOfMemoryUsing16M()
178 size_t signature
= 16 * 1024 * 1024;
183 static NEVER_INLINE
void partitionsOutOfMemoryUsingLessThan16M()
185 size_t signature
= 16 * 1024 * 1024 - 1;
190 void Partitions::handleOutOfMemory()
192 volatile size_t totalUsage
= totalSizeOfCommittedPages();
194 if (totalUsage
>= 2UL * 1024 * 1024 * 1024)
195 partitionsOutOfMemoryUsing2G();
196 if (totalUsage
>= 1UL * 1024 * 1024 * 1024)
197 partitionsOutOfMemoryUsing1G();
198 if (totalUsage
>= 512 * 1024 * 1024)
199 partitionsOutOfMemoryUsing512M();
200 if (totalUsage
>= 256 * 1024 * 1024)
201 partitionsOutOfMemoryUsing256M();
202 if (totalUsage
>= 128 * 1024 * 1024)
203 partitionsOutOfMemoryUsing128M();
204 if (totalUsage
>= 64 * 1024 * 1024)
205 partitionsOutOfMemoryUsing64M();
206 if (totalUsage
>= 32 * 1024 * 1024)
207 partitionsOutOfMemoryUsing32M();
208 if (totalUsage
>= 16 * 1024 * 1024)
209 partitionsOutOfMemoryUsing16M();
210 partitionsOutOfMemoryUsingLessThan16M();