GC constraint solving should be parallel
[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 struct FastMallocStatistics {
74     size_t reservedVMBytes;
75     size_t committedVMBytes;
76     size_t freeListBytes;
77 };
78 WTF_EXPORT_PRIVATE FastMallocStatistics fastMallocStatistics();
79
80 // This defines a type which holds an unsigned integer and is the same
81 // size as the minimally aligned memory allocation.
82 typedef unsigned long long AllocAlignmentInteger;
83
84 inline TryMallocReturnValue::TryMallocReturnValue(void* data)
85     : m_data(data)
86 {
87 }
88
89 inline TryMallocReturnValue::TryMallocReturnValue(TryMallocReturnValue&& source)
90     : m_data(source.m_data)
91 {
92     source.m_data = nullptr;
93 }
94
95 inline TryMallocReturnValue::~TryMallocReturnValue()
96 {
97     ASSERT(!m_data);
98 }
99
100 template<typename T> inline bool TryMallocReturnValue::getValue(T*& data)
101 {
102     data = static_cast<T*>(m_data);
103     m_data = nullptr;
104     return data;
105 }
106
107 // C++ STL allocator implementation. You can integrate fastMalloc into STL containers.
108 // e.g. std::unordered_map<Key, Value, std::hash<Key>, std::equal_to<Key>, FastAllocator<std::pair<const Key, Value>>>.
109 template<typename T>
110 class FastAllocator {
111 public:
112     using value_type = T;
113
114     FastAllocator() = default;
115
116     template<typename U> FastAllocator(const FastAllocator<U>&) { }
117
118     T* allocate(size_t count)
119     {
120         return reinterpret_cast<T*>(fastMalloc(sizeof(T) * count));
121     }
122
123     void deallocate(T* pointer, size_t)
124     {
125         fastFree(pointer);
126     }
127
128 #if defined(__GLIBCXX__) && (!defined(_GLIBCXX_RELEASE) || _GLIBCXX_RELEASE < 6)
129     // This allocator also supports pre-C++11 STL allocator interface. This is a workaround for GCC < 6, which std::list
130     // does not support C++11 allocator. Note that _GLIBCXX_RELEASE is only defined after GCC 7 release. So currently
131     // this workaround is enabled in GCC 6 too.
132     // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55409
133
134     using pointer = value_type*;
135     using const_pointer = typename std::pointer_traits<pointer>::template rebind<value_type const>;
136     using void_pointer = typename std::pointer_traits<pointer>::template rebind<void>;
137     using const_void_pointer = typename std::pointer_traits<pointer>::template rebind<const void>;
138
139     using reference = T&;
140     using const_reference = const T&;
141
142     using difference_type = typename std::pointer_traits<pointer>::difference_type;
143     using size_type = std::make_unsigned_t<difference_type>;
144
145     template <class U> struct rebind {
146         using other = FastAllocator<U>;
147     };
148
149     value_type* allocate(std::size_t count, const_void_pointer)
150     {
151         return allocate(count);
152     }
153
154     template <class U, class ...Args>
155     void construct(U* p, Args&& ...args)
156     {
157         new (const_cast<void*>(static_cast<const void*>(p))) U(std::forward<Args>(args)...);
158     }
159
160     template <class U>
161     void destroy(U* p)
162     {
163         p->~U();
164     }
165
166     std::size_t max_size() const
167     {
168         return std::numeric_limits<size_type>::max();
169     }
170
171     FastAllocator<T> select_on_container_copy_construction() const
172     {
173         return *this;
174     }
175
176     using propagate_on_container_copy_assignment = std::false_type;
177     using propagate_on_container_move_assignment = std::false_type;
178     using propagate_on_container_swap = std::false_type;
179     using is_always_equal = std::is_empty<FastAllocator>;
180 #endif // defined(__GLIBCXX__) && (!defined(_GLIBCXX_RELEASE) || _GLIBCXX_RELEASE < 6)
181 };
182
183 template<typename T, typename U> inline bool operator==(const FastAllocator<T>&, const FastAllocator<U>&) { return true; }
184 template<typename T, typename U> inline bool operator!=(const FastAllocator<T>&, const FastAllocator<U>&) { return false; }
185
186 struct FastMalloc {
187     static void* malloc(size_t size) { return fastMalloc(size); }
188     
189     static void* tryMalloc(size_t size)
190     {
191         auto result = tryFastMalloc(size);
192         void* realResult;
193         if (result.getValue(realResult))
194             return realResult;
195         return nullptr;
196     }
197     
198     static void* realloc(void* p, size_t size) { return fastRealloc(p, size); }
199     
200     static void free(void* p) { fastFree(p); }
201 };
202
203 } // namespace WTF
204
205 #if !defined(NDEBUG)
206 using WTF::fastSetMaxSingleAllocationSize;
207 #endif
208
209 using WTF::FastAllocator;
210 using WTF::FastMalloc;
211 using WTF::isFastMallocEnabled;
212 using WTF::fastCalloc;
213 using WTF::fastFree;
214 using WTF::fastMalloc;
215 using WTF::fastMallocGoodSize;
216 using WTF::fastMallocSize;
217 using WTF::fastRealloc;
218 using WTF::fastStrDup;
219 using WTF::fastZeroedMalloc;
220 using WTF::tryFastAlignedMalloc;
221 using WTF::tryFastCalloc;
222 using WTF::tryFastMalloc;
223 using WTF::tryFastZeroedMalloc;
224 using WTF::fastAlignedMalloc;
225 using WTF::fastAlignedFree;
226
227 #if COMPILER(GCC_OR_CLANG) && OS(DARWIN)
228 #define WTF_PRIVATE_INLINE __private_extern__ inline __attribute__((always_inline))
229 #elif COMPILER(GCC_OR_CLANG)
230 #define WTF_PRIVATE_INLINE inline __attribute__((always_inline))
231 #elif COMPILER(MSVC)
232 #define WTF_PRIVATE_INLINE __forceinline
233 #else
234 #define WTF_PRIVATE_INLINE inline
235 #endif
236
237 #define WTF_MAKE_FAST_ALLOCATED_IMPL \
238     void* operator new(size_t, void* p) { return p; } \
239     void* operator new[](size_t, void* p) { return p; } \
240     \
241     void* operator new(size_t size) \
242     { \
243         return ::WTF::fastMalloc(size); \
244     } \
245     \
246     void operator delete(void* p) \
247     { \
248         ::WTF::fastFree(p); \
249     } \
250     \
251     void* operator new[](size_t size) \
252     { \
253         return ::WTF::fastMalloc(size); \
254     } \
255     \
256     void operator delete[](void* p) \
257     { \
258         ::WTF::fastFree(p); \
259     } \
260     void* operator new(size_t, NotNullTag, void* location) \
261     { \
262         ASSERT(location); \
263         return location; \
264     } \
265
266 #define WTF_MAKE_FAST_ALLOCATED \
267 public: \
268     WTF_MAKE_FAST_ALLOCATED_IMPL \
269 private: \
270 typedef int __thisIsHereToForceASemicolonAfterThisMacro
271
272 #define WTF_MAKE_STRUCT_FAST_ALLOCATED \
273     WTF_MAKE_FAST_ALLOCATED_IMPL \
274 typedef int __thisIsHereToForceASemicolonAfterThisMacro
275
276 #endif /* WTF_FastMalloc_h */