2 * Copyright (C) 2008, 2009 Paul Pedriana <ppedriana@ea.com>. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14 * its contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #ifndef FastAllocBase_h
30 #define FastAllocBase_h
32 // Provides customizable overrides of fastMalloc/fastFree and operator new/delete
34 // Provided functionality:
35 // Macro: WTF_MAKE_FAST_ALLOCATED
39 // T* fastNew<T>(arg);
40 // T* fastNew<T>(arg, arg);
41 // T* fastNewArray<T>(count);
42 // void fastDelete(T* p);
43 // void fastDeleteArray(T* p);
44 // void fastNonNullDelete(T* p);
45 // void fastNonNullDeleteArray(T* p);
48 // FastDelete assumes that the underlying
52 // WTF_MAKE_FAST_ALLOCATED
57 // WTF_MAKE_FAST_ALLOCATED
62 // char* charPtr = fastNew<char>();
63 // fastDelete(charPtr);
65 // char* charArrayPtr = fastNewArray<char>(37);
66 // fastDeleteArray(charArrayPtr);
68 // void** voidPtrPtr = fastNew<void*>();
69 // fastDelete(voidPtrPtr);
71 // void** voidPtrArrayPtr = fastNewArray<void*>(37);
72 // fastDeleteArray(voidPtrArrayPtr);
74 // POD* podPtr = fastNew<POD>();
75 // fastDelete(podPtr);
77 // POD* podArrayPtr = fastNewArray<POD>(37);
78 // fastDeleteArray(podArrayPtr);
80 // Object* objectPtr = fastNew<Object>();
81 // fastDelete(objectPtr);
83 // Object* objectArrayPtr = fastNewArray<Object>(37);
84 // fastDeleteArray(objectArrayPtr);
91 #include <wtf/Assertions.h>
92 #include <wtf/FastMalloc.h>
93 #include <wtf/StdLibExtras.h>
94 #include <wtf/TypeTraits.h>
96 #define WTF_MAKE_FAST_ALLOCATED \
98 void* operator new(size_t, void* p) { return p; } \
99 void* operator new[](size_t, void* p) { return p; } \
101 void* operator new(size_t size) \
103 void* p = ::WTF::fastMalloc(size); \
104 ::WTF::fastMallocMatchValidateMalloc(p, ::WTF::Internal::AllocTypeClassNew); \
108 void operator delete(void* p) \
110 ::WTF::fastMallocMatchValidateFree(p, ::WTF::Internal::AllocTypeClassNew); \
111 ::WTF::fastFree(p); \
114 void* operator new[](size_t size) \
116 void* p = ::WTF::fastMalloc(size); \
117 ::WTF::fastMallocMatchValidateMalloc(p, ::WTF::Internal::AllocTypeClassNewArray); \
121 void operator delete[](void* p) \
123 ::WTF::fastMallocMatchValidateFree(p, ::WTF::Internal::AllocTypeClassNewArray); \
124 ::WTF::fastFree(p); \
126 void* operator new(size_t, NotNullTag, void* location) \
132 typedef int __thisIsHereToForceASemicolonAfterThisMacro
136 // fastNew / fastDelete
138 template <typename T>
141 void* p = fastMalloc(sizeof(T));
146 fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew);
150 template <typename T, typename Arg1>
151 inline T* fastNew(Arg1 arg1)
153 void* p = fastMalloc(sizeof(T));
158 fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew);
159 return ::new (p) T(arg1);
162 template <typename T, typename Arg1, typename Arg2>
163 inline T* fastNew(Arg1 arg1, Arg2 arg2)
165 void* p = fastMalloc(sizeof(T));
170 fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew);
171 return ::new (p) T(arg1, arg2);
174 template <typename T, typename Arg1, typename Arg2, typename Arg3>
175 inline T* fastNew(Arg1 arg1, Arg2 arg2, Arg3 arg3)
177 void* p = fastMalloc(sizeof(T));
182 fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew);
183 return ::new (p) T(arg1, arg2, arg3);
186 template <typename T, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
187 inline T* fastNew(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4)
189 void* p = fastMalloc(sizeof(T));
194 fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew);
195 return ::new (p) T(arg1, arg2, arg3, arg4);
198 template <typename T, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5>
199 inline T* fastNew(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5)
201 void* p = fastMalloc(sizeof(T));
206 fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew);
207 return ::new (p) T(arg1, arg2, arg3, arg4, arg5);
212 // We define a union of pointer to an integer and pointer to T.
213 // When non-POD arrays are allocated we add a few leading bytes to tell what
214 // the size of the array is. We return to the user the pointer to T.
215 // The way to think of it is as if we allocate a struct like so:
217 // AllocAlignmentInteger m_size;
218 // T m_T[array count];
221 template <typename T>
223 AllocAlignmentInteger* size;
227 // This is a support template for fastNewArray.
228 // This handles the case wherein T has a trivial ctor and a trivial dtor.
229 template <typename T, bool trivialCtor, bool trivialDtor>
230 struct NewArrayImpl {
231 static T* fastNewArray(size_t count)
233 T* p = static_cast<T*>(fastMalloc(sizeof(T) * count));
234 fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNewArray);
239 // This is a support template for fastNewArray.
240 // This handles the case wherein T has a non-trivial ctor and a trivial dtor.
241 template <typename T>
242 struct NewArrayImpl<T, false, true> {
243 static T* fastNewArray(size_t count)
245 T* p = static_cast<T*>(fastMalloc(sizeof(T) * count));
250 fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNewArray);
252 for (T* pObject = p, *pObjectEnd = pObject + count; pObject != pObjectEnd; ++pObject)
259 // This is a support template for fastNewArray.
260 // This handles the case wherein T has a trivial ctor and a non-trivial dtor.
261 template <typename T>
262 struct NewArrayImpl<T, true, false> {
263 static T* fastNewArray(size_t count)
265 void* p = fastMalloc(sizeof(AllocAlignmentInteger) + (sizeof(T) * count));
266 ArraySize<T> a = { static_cast<AllocAlignmentInteger*>(p) };
271 fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNewArray);
273 // No need to construct the objects in this case.
279 // This is a support template for fastNewArray.
280 // This handles the case wherein T has a non-trivial ctor and a non-trivial dtor.
281 template <typename T>
282 struct NewArrayImpl<T, false, false> {
283 static T* fastNewArray(size_t count)
285 void* p = fastMalloc(sizeof(AllocAlignmentInteger) + (sizeof(T) * count));
286 ArraySize<T> a = { static_cast<AllocAlignmentInteger*>(p) };
291 fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNewArray);
294 for (T* pT = a.t, *pTEnd = pT + count; pT != pTEnd; ++pT)
300 } // namespace Internal
302 template <typename T>
303 inline T* fastNewArray(size_t count)
305 return Internal::NewArrayImpl<T, WTF::HasTrivialConstructor<T>::value, WTF::HasTrivialDestructor<T>::value>::fastNewArray(count);
308 template <typename T>
309 inline void fastDelete(T* p)
314 fastMallocMatchValidateFree(p, Internal::AllocTypeFastNew);
319 template <typename T>
320 inline void fastDeleteSkippingDestructor(T* p)
325 fastMallocMatchValidateFree(p, Internal::AllocTypeFastNew);
330 // This is a support template for fastDeleteArray.
331 // This handles the case wherein T has a trivial dtor.
332 template <typename T, bool trivialDtor>
333 struct DeleteArrayImpl {
334 static void fastDeleteArray(void* p)
336 // No need to destruct the objects in this case.
337 // We expect that fastFree checks for null.
338 fastMallocMatchValidateFree(p, Internal::AllocTypeFastNewArray);
343 // This is a support template for fastDeleteArray.
344 // This handles the case wherein T has a non-trivial dtor.
345 template <typename T>
346 struct DeleteArrayImpl<T, false> {
347 static void fastDeleteArray(T* p)
354 a.size--; // Decrement size pointer
356 T* pEnd = p + *a.size;
360 fastMallocMatchValidateFree(a.size, Internal::AllocTypeFastNewArray);
365 } // namespace Internal
367 template <typename T>
368 void fastDeleteArray(T* p)
370 Internal::DeleteArrayImpl<T, WTF::HasTrivialDestructor<T>::value>::fastDeleteArray(p);
374 template <typename T>
375 inline void fastNonNullDelete(T* p)
377 fastMallocMatchValidateFree(p, Internal::AllocTypeFastNew);
383 // This is a support template for fastDeleteArray.
384 // This handles the case wherein T has a trivial dtor.
385 template <typename T, bool trivialDtor>
386 struct NonNullDeleteArrayImpl {
387 static void fastNonNullDeleteArray(void* p)
389 fastMallocMatchValidateFree(p, Internal::AllocTypeFastNewArray);
390 // No need to destruct the objects in this case.
395 // This is a support template for fastDeleteArray.
396 // This handles the case wherein T has a non-trivial dtor.
397 template <typename T>
398 struct NonNullDeleteArrayImpl<T, false> {
399 static void fastNonNullDeleteArray(T* p)
405 T* pEnd = p + *a.size;
409 fastMallocMatchValidateFree(a.size, Internal::AllocTypeFastNewArray);
414 } // namespace Internal
416 template <typename T>
417 void fastNonNullDeleteArray(T* p)
419 Internal::NonNullDeleteArrayImpl<T, WTF::HasTrivialDestructor<T>::value>::fastNonNullDeleteArray(p);
425 using WTF::fastDeleteSkippingDestructor;
427 #endif // FastAllocBase_h