[bmalloc] Bmalloc DebugHeap should have dump and scavenge features
[WebKit-https.git] / Source / bmalloc / bmalloc / DebugHeap.cpp
1 /*
2  * Copyright (C) 2016-2018 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 "DebugHeap.h"
27
28 #include "Algorithm.h"
29 #include "BAssert.h"
30 #include "BPlatform.h"
31 #include "VMAllocate.h"
32 #include <cstdlib>
33 #include <thread>
34
35 namespace bmalloc {
36
37 DebugHeap* debugHeapCache { nullptr };
38     
39 #if BOS(DARWIN)
40
41 DebugHeap::DebugHeap(std::lock_guard<Mutex>&)
42     : m_zone(malloc_create_zone(0, 0))
43     , m_pageSize(vmPageSize())
44 {
45     malloc_set_zone_name(m_zone, "WebKit Using System Malloc");
46 }
47
48 void* DebugHeap::malloc(size_t size, bool crashOnFailure)
49 {
50     void* result = malloc_zone_malloc(m_zone, size);
51     if (!result && crashOnFailure)
52         BCRASH();
53     return result;
54 }
55
56 void* DebugHeap::memalign(size_t alignment, size_t size, bool crashOnFailure)
57 {
58     void* result = malloc_zone_memalign(m_zone, alignment, size);
59     if (!result && crashOnFailure)
60         BCRASH();
61     return result;
62 }
63
64 void* DebugHeap::realloc(void* object, size_t size, bool crashOnFailure)
65 {
66     void* result = malloc_zone_realloc(m_zone, object, size);
67     if (!result && crashOnFailure)
68         BCRASH();
69     return result;
70 }
71
72 void DebugHeap::free(void* object)
73 {
74     malloc_zone_free(m_zone, object);
75 }
76
77 void DebugHeap::scavenge()
78 {
79     // Currently |goal| does not affect on the behavior of malloc_zone_pressure_relief if (1) we only scavenge one zone and (2) it is not nanomalloc.
80     constexpr size_t goal = 0;
81     malloc_zone_pressure_relief(m_zone, goal);
82 }
83
84 void DebugHeap::dump()
85 {
86     constexpr bool verbose = true;
87     malloc_zone_print(m_zone, verbose);
88 }
89
90 #else
91
92 DebugHeap::DebugHeap(std::lock_guard<Mutex>&)
93     : m_pageSize(vmPageSize())
94 {
95 }
96
97 void* DebugHeap::malloc(size_t size, bool crashOnFailure)
98 {
99     void* result = ::malloc(size);
100     if (!result && crashOnFailure)
101         BCRASH();
102     return result;
103 }
104
105 void* DebugHeap::memalign(size_t alignment, size_t size, bool crashOnFailure)
106 {
107     void* result;
108     if (posix_memalign(&result, alignment, size)) {
109         if (crashOnFailure)
110             BCRASH();
111         return nullptr;
112     }
113     return result;
114 }
115
116 void* DebugHeap::realloc(void* object, size_t size, bool crashOnFailure)
117 {
118     void* result = ::realloc(object, size);
119     if (!result && crashOnFailure)
120         BCRASH();
121     return result;
122 }
123
124 void DebugHeap::free(void* object)
125 {
126     ::free(object);
127 }
128
129 void DebugHeap::scavenge()
130 {
131 }
132
133 void DebugHeap::dump()
134 {
135 }
136
137 #endif
138
139 // FIXME: This looks an awful lot like the code in wtf/Gigacage.cpp for large allocation.
140 // https://bugs.webkit.org/show_bug.cgi?id=175086
141
142 void* DebugHeap::memalignLarge(size_t alignment, size_t size)
143 {
144     alignment = roundUpToMultipleOf(m_pageSize, alignment);
145     size = roundUpToMultipleOf(m_pageSize, size);
146     void* result = tryVMAllocate(alignment, size);
147     if (!result)
148         return nullptr;
149     {
150         std::lock_guard<std::mutex> locker(m_lock);
151         m_sizeMap[result] = size;
152     }
153     return result;
154 }
155
156 void DebugHeap::freeLarge(void* base)
157 {
158     if (!base)
159         return;
160     
161     size_t size;
162     {
163         std::lock_guard<std::mutex> locker(m_lock);
164         size = m_sizeMap[base];
165         size_t numErased = m_sizeMap.erase(base);
166         RELEASE_BASSERT(numErased == 1);
167     }
168     
169     vmDeallocate(base, size);
170 }
171
172 } // namespace bmalloc