Unreviewed, rolling out r234489.
[WebKit-https.git] / Source / WTF / wtf / FastMalloc.h
1 /*
2  *  Copyright (C) 2005-2009, 2015-2016 Apple Inc. All rights reserved.
3  *
4  *  This library is free software; you can redistribute it and/or
5  *  modify it under the terms of the GNU Library General Public
6  *  License as published by the Free Software Foundation; either
7  *  version 2 of the License, or (at your option) any later version.
8  *
9  *  This library is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  *  Library General Public License for more details.
13  *
14  *  You should have received a copy of the GNU Library General Public License
15  *  along with this library; see the file COPYING.LIB.  If not, write to
16  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  *  Boston, MA 02110-1301, USA.
18  *
19  */
20
21 #ifndef WTF_FastMalloc_h
22 #define WTF_FastMalloc_h
23
24 #include <new>
25 #include <stdlib.h>
26 #include <wtf/StdLibExtras.h>
27
28 namespace WTF {
29
30 #if !defined(NDEBUG)
31 WTF_EXPORT_PRIVATE void fastSetMaxSingleAllocationSize(size_t);
32 #endif
33
34 class TryMallocReturnValue {
35 public:
36     TryMallocReturnValue(void*);
37     TryMallocReturnValue(TryMallocReturnValue&&);
38     ~TryMallocReturnValue();
39     template<typename T> bool getValue(T*&) WARN_UNUSED_RETURN;
40 private:
41     void operator=(TryMallocReturnValue&&) = delete;
42     mutable void* m_data;
43 };
44
45 WTF_EXPORT_PRIVATE bool isFastMallocEnabled();
46
47 // These functions call CRASH() if an allocation fails.
48 WTF_EXPORT_PRIVATE void* fastMalloc(size_t) RETURNS_NONNULL;
49 WTF_EXPORT_PRIVATE void* fastZeroedMalloc(size_t) RETURNS_NONNULL;
50 WTF_EXPORT_PRIVATE void* fastCalloc(size_t numElements, size_t elementSize) RETURNS_NONNULL;
51 WTF_EXPORT_PRIVATE void* fastRealloc(void*, size_t) RETURNS_NONNULL;
52 WTF_EXPORT_PRIVATE char* fastStrDup(const char*) RETURNS_NONNULL;
53
54 WTF_EXPORT_PRIVATE TryMallocReturnValue tryFastMalloc(size_t);
55 WTF_EXPORT_PRIVATE TryMallocReturnValue tryFastZeroedMalloc(size_t);
56 WTF_EXPORT_PRIVATE TryMallocReturnValue tryFastCalloc(size_t numElements, size_t elementSize);
57
58 WTF_EXPORT_PRIVATE void fastFree(void*);
59
60 // Allocations from fastAlignedMalloc() must be freed using fastAlignedFree().
61 WTF_EXPORT_PRIVATE void* fastAlignedMalloc(size_t alignment, size_t) RETURNS_NONNULL;
62 WTF_EXPORT_PRIVATE void* tryFastAlignedMalloc(size_t alignment, size_t);
63 WTF_EXPORT_PRIVATE void fastAlignedFree(void*);
64
65 WTF_EXPORT_PRIVATE size_t fastMallocSize(const void*);
66
67 // FIXME: This is non-helpful; fastMallocGoodSize will be removed soon.
68 WTF_EXPORT_PRIVATE size_t fastMallocGoodSize(size_t);
69
70 WTF_EXPORT_PRIVATE void releaseFastMallocFreeMemory();
71 WTF_EXPORT_PRIVATE void releaseFastMallocFreeMemoryForThisThread();
72
73 WTF_EXPORT_PRIVATE void fastCommitAlignedMemory(void*, size_t);
74 WTF_EXPORT_PRIVATE void fastDecommitAlignedMemory(void*, size_t);
75
76 WTF_EXPORT_PRIVATE void fastEnableMiniMode();
77
78 struct FastMallocStatistics {
79     size_t reservedVMBytes;
80     size_t committedVMBytes;
81     size_t freeListBytes;
82 };
83 WTF_EXPORT_PRIVATE FastMallocStatistics fastMallocStatistics();
84
85 // This defines a type which holds an unsigned integer and is the same
86 // size as the minimally aligned memory allocation.
87 typedef unsigned long long AllocAlignmentInteger;
88
89 inline TryMallocReturnValue::TryMallocReturnValue(void* data)
90     : m_data(data)
91 {
92 }
93
94 inline TryMallocReturnValue::TryMallocReturnValue(TryMallocReturnValue&& source)
95     : m_data(source.m_data)
96 {
97     source.m_data = nullptr;
98 }
99
100 inline TryMallocReturnValue::~TryMallocReturnValue()
101 {
102     ASSERT(!m_data);
103 }
104
105 template<typename T> inline bool TryMallocReturnValue::getValue(T*& data)
106 {
107     data = static_cast<T*>(m_data);
108     m_data = nullptr;
109     return data;
110 }
111
112 // C++ STL allocator implementation. You can integrate fastMalloc into STL containers.
113 // e.g. std::unordered_map<Key, Value, std::hash<Key>, std::equal_to<Key>, FastAllocator<std::pair<const Key, Value>>>.
114 template<typename T>
115 class FastAllocator {
116 public:
117     using value_type = T;
118
119     FastAllocator() = default;
120
121     template<typename U> FastAllocator(const FastAllocator<U>&) { }
122
123     T* allocate(size_t count)
124     {
125         return reinterpret_cast<T*>(fastMalloc(sizeof(T) * count));
126     }
127
128     void deallocate(T* pointer, size_t)
129     {
130         fastFree(pointer);
131     }
132
133 #if defined(__GLIBCXX__) && (!defined(_GLIBCXX_RELEASE) || _GLIBCXX_RELEASE < 6)
134     // This allocator also supports pre-C++11 STL allocator interface. This is a workaround for GCC < 6, which std::list
135     // does not support C++11 allocator. Note that _GLIBCXX_RELEASE is only defined after GCC 7 release. So currently
136     // this workaround is enabled in GCC 6 too.
137     // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55409
138
139     using pointer = value_type*;
140     using const_pointer = typename std::pointer_traits<pointer>::template rebind<value_type const>;
141     using void_pointer = typename std::pointer_traits<pointer>::template rebind<void>;
142     using const_void_pointer = typename std::pointer_traits<pointer>::template rebind<const void>;
143
144     using reference = T&;
145     using const_reference = const T&;
146
147     using difference_type = typename std::pointer_traits<pointer>::difference_type;
148     using size_type = std::make_unsigned_t<difference_type>;
149
150     template <class U> struct rebind {
151         using other = FastAllocator<U>;
152     };
153
154     value_type* allocate(std::size_t count, const_void_pointer)
155     {
156         return allocate(count);
157     }
158
159     template <class U, class ...Args>
160     void construct(U* p, Args&& ...args)
161     {
162         new (const_cast<void*>(static_cast<const void*>(p))) U(std::forward<Args>(args)...);
163     }
164
165     template <class U>
166     void destroy(U* p)
167     {
168         p->~U();
169     }
170
171     std::size_t max_size() const
172     {
173         return std::numeric_limits<size_type>::max();
174     }
175
176     FastAllocator<T> select_on_container_copy_construction() const
177     {
178         return *this;
179     }
180
181     using propagate_on_container_copy_assignment = std::false_type;
182     using propagate_on_container_move_assignment = std::false_type;
183     using propagate_on_container_swap = std::false_type;
184     using is_always_equal = std::is_empty<FastAllocator>;
185 #endif // defined(__GLIBCXX__) && (!defined(_GLIBCXX_RELEASE) || _GLIBCXX_RELEASE < 6)
186 };
187
188 template<typename T, typename U> inline bool operator==(const FastAllocator<T>&, const FastAllocator<U>&) { return true; }
189 template<typename T, typename U> inline bool operator!=(const FastAllocator<T>&, const FastAllocator<U>&) { return false; }
190
191 struct FastMalloc {
192     static void* malloc(size_t size) { return fastMalloc(size); }
193     
194     static void* tryMalloc(size_t size)
195     {
196         auto result = tryFastMalloc(size);
197         void* realResult;
198         if (result.getValue(realResult))
199             return realResult;
200         return nullptr;
201     }
202     
203     static void* realloc(void* p, size_t size) { return fastRealloc(p, size); }
204     
205     static void free(void* p) { fastFree(p); }
206 };
207
208 template<typename T>
209 struct FastFree {
210     static_assert(std::is_trivially_destructible<T>::value, "");
211
212     void operator()(T* pointer) const
213     {
214         fastFree(const_cast<typename std::remove_cv<T>::type*>(pointer));
215     }
216 };
217
218 template<typename T>
219 struct FastFree<T[]> {
220     static_assert(std::is_trivially_destructible<T>::value, "");
221
222     void operator()(T* pointer) const
223     {
224         fastFree(const_cast<typename std::remove_cv<T>::type*>(pointer));
225     }
226 };
227
228 } // namespace WTF
229
230 #if !defined(NDEBUG)
231 using WTF::fastSetMaxSingleAllocationSize;
232 #endif
233
234 using WTF::FastAllocator;
235 using WTF::FastMalloc;
236 using WTF::FastFree;
237 using WTF::isFastMallocEnabled;
238 using WTF::fastCalloc;
239 using WTF::fastFree;
240 using WTF::fastMalloc;
241 using WTF::fastMallocGoodSize;
242 using WTF::fastMallocSize;
243 using WTF::fastRealloc;
244 using WTF::fastStrDup;
245 using WTF::fastZeroedMalloc;
246 using WTF::tryFastAlignedMalloc;
247 using WTF::tryFastCalloc;
248 using WTF::tryFastMalloc;
249 using WTF::tryFastZeroedMalloc;
250 using WTF::fastAlignedMalloc;
251 using WTF::fastAlignedFree;
252
253 #if COMPILER(GCC_OR_CLANG) && OS(DARWIN)
254 #define WTF_PRIVATE_INLINE __private_extern__ inline __attribute__((always_inline))
255 #elif COMPILER(GCC_OR_CLANG)
256 #define WTF_PRIVATE_INLINE inline __attribute__((always_inline))
257 #elif COMPILER(MSVC)
258 #define WTF_PRIVATE_INLINE __forceinline
259 #else
260 #define WTF_PRIVATE_INLINE inline
261 #endif
262
263 #define WTF_MAKE_FAST_ALLOCATED_IMPL \
264     void* operator new(size_t, void* p) { return p; } \
265     void* operator new[](size_t, void* p) { return p; } \
266     \
267     void* operator new(size_t size) \
268     { \
269         return ::WTF::fastMalloc(size); \
270     } \
271     \
272     void operator delete(void* p) \
273     { \
274         ::WTF::fastFree(p); \
275     } \
276     \
277     void* operator new[](size_t size) \
278     { \
279         return ::WTF::fastMalloc(size); \
280     } \
281     \
282     void operator delete[](void* p) \
283     { \
284         ::WTF::fastFree(p); \
285     } \
286     void* operator new(size_t, NotNullTag, void* location) \
287     { \
288         ASSERT(location); \
289         return location; \
290     } \
291
292 #define WTF_MAKE_FAST_ALLOCATED \
293 public: \
294     WTF_MAKE_FAST_ALLOCATED_IMPL \
295 private: \
296 typedef int __thisIsHereToForceASemicolonAfterThisMacro
297
298 #define WTF_MAKE_STRUCT_FAST_ALLOCATED \
299     WTF_MAKE_FAST_ALLOCATED_IMPL \
300 typedef int __thisIsHereToForceASemicolonAfterThisMacro
301
302 #endif /* WTF_FastMalloc_h */