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 "Assertions.h"
92 #include "FastMalloc.h"
93 #include "TypeTraits.h"
95 #define WTF_MAKE_FAST_ALLOCATED \
97 void* operator new(size_t, void* p) { return p; } \
98 void* operator new[](size_t, void* p) { return p; } \
100 void* operator new(size_t size) \
102 void* p = ::WTF::fastMalloc(size); \
103 ::WTF::fastMallocMatchValidateMalloc(p, ::WTF::Internal::AllocTypeClassNew); \
107 void operator delete(void* p) \
109 ::WTF::fastMallocMatchValidateFree(p, ::WTF::Internal::AllocTypeClassNew); \
110 ::WTF::fastFree(p); \
113 void* operator new[](size_t size) \
115 void* p = ::WTF::fastMalloc(size); \
116 ::WTF::fastMallocMatchValidateMalloc(p, ::WTF::Internal::AllocTypeClassNewArray); \
120 void operator delete[](void* p) \
122 ::WTF::fastMallocMatchValidateFree(p, ::WTF::Internal::AllocTypeClassNewArray); \
123 ::WTF::fastFree(p); \
126 typedef int ThisIsHereToForceASemicolonAfterThisMacro
130 // fastNew / fastDelete
132 template <typename T>
135 void* p = fastMalloc(sizeof(T));
140 fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew);
144 template <typename T, typename Arg1>
145 inline T* fastNew(Arg1 arg1)
147 void* p = fastMalloc(sizeof(T));
152 fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew);
153 return ::new(p) T(arg1);
156 template <typename T, typename Arg1, typename Arg2>
157 inline T* fastNew(Arg1 arg1, Arg2 arg2)
159 void* p = fastMalloc(sizeof(T));
164 fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew);
165 return ::new(p) T(arg1, arg2);
168 template <typename T, typename Arg1, typename Arg2, typename Arg3>
169 inline T* fastNew(Arg1 arg1, Arg2 arg2, Arg3 arg3)
171 void* p = fastMalloc(sizeof(T));
176 fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew);
177 return ::new(p) T(arg1, arg2, arg3);
180 template <typename T, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
181 inline T* fastNew(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4)
183 void* p = fastMalloc(sizeof(T));
188 fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew);
189 return ::new(p) T(arg1, arg2, arg3, arg4);
192 template <typename T, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5>
193 inline T* fastNew(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5)
195 void* p = fastMalloc(sizeof(T));
200 fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew);
201 return ::new(p) T(arg1, arg2, arg3, arg4, arg5);
206 // We define a union of pointer to an integer and pointer to T.
207 // When non-POD arrays are allocated we add a few leading bytes to tell what
208 // the size of the array is. We return to the user the pointer to T.
209 // The way to think of it is as if we allocate a struct like so:
211 // AllocAlignmentInteger m_size;
212 // T m_T[array count];
215 template <typename T>
217 AllocAlignmentInteger* size;
221 // This is a support template for fastNewArray.
222 // This handles the case wherein T has a trivial ctor and a trivial dtor.
223 template <typename T, bool trivialCtor, bool trivialDtor>
224 struct NewArrayImpl {
225 static T* fastNewArray(size_t count)
227 T* p = static_cast<T*>(fastMalloc(sizeof(T) * count));
228 fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNewArray);
233 // This is a support template for fastNewArray.
234 // This handles the case wherein T has a non-trivial ctor and a trivial dtor.
235 template <typename T>
236 struct NewArrayImpl<T, false, true> {
237 static T* fastNewArray(size_t count)
239 T* p = static_cast<T*>(fastMalloc(sizeof(T) * count));
244 fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNewArray);
246 for (T* pObject = p, *pObjectEnd = pObject + count; pObject != pObjectEnd; ++pObject)
253 // This is a support template for fastNewArray.
254 // This handles the case wherein T has a trivial ctor and a non-trivial dtor.
255 template <typename T>
256 struct NewArrayImpl<T, true, false> {
257 static T* fastNewArray(size_t count)
259 void* p = fastMalloc(sizeof(AllocAlignmentInteger) + (sizeof(T) * count));
260 ArraySize<T> a = { static_cast<AllocAlignmentInteger*>(p) };
265 fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNewArray);
267 // No need to construct the objects in this case.
273 // This is a support template for fastNewArray.
274 // This handles the case wherein T has a non-trivial ctor and a non-trivial dtor.
275 template <typename T>
276 struct NewArrayImpl<T, false, false> {
277 static T* fastNewArray(size_t count)
279 void* p = fastMalloc(sizeof(AllocAlignmentInteger) + (sizeof(T) * count));
280 ArraySize<T> a = { static_cast<AllocAlignmentInteger*>(p) };
285 fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNewArray);
288 for (T* pT = a.t, *pTEnd = pT + count; pT != pTEnd; ++pT)
294 } // namespace Internal
296 template <typename T>
297 inline T* fastNewArray(size_t count)
299 return Internal::NewArrayImpl<T, WTF::HasTrivialConstructor<T>::value, WTF::HasTrivialDestructor<T>::value>::fastNewArray(count);
302 template <typename T>
303 inline void fastDelete(T* p)
308 fastMallocMatchValidateFree(p, Internal::AllocTypeFastNew);
313 template <typename T>
314 inline void fastDeleteSkippingDestructor(T* p)
319 fastMallocMatchValidateFree(p, Internal::AllocTypeFastNew);
324 // This is a support template for fastDeleteArray.
325 // This handles the case wherein T has a trivial dtor.
326 template <typename T, bool trivialDtor>
327 struct DeleteArrayImpl {
328 static void fastDeleteArray(void* p)
330 // No need to destruct the objects in this case.
331 // We expect that fastFree checks for null.
332 fastMallocMatchValidateFree(p, Internal::AllocTypeFastNewArray);
337 // This is a support template for fastDeleteArray.
338 // This handles the case wherein T has a non-trivial dtor.
339 template <typename T>
340 struct DeleteArrayImpl<T, false> {
341 static void fastDeleteArray(T* p)
348 a.size--; // Decrement size pointer
350 T* pEnd = p + *a.size;
354 fastMallocMatchValidateFree(a.size, Internal::AllocTypeFastNewArray);
359 } // namespace Internal
361 template <typename T>
362 void fastDeleteArray(T* p)
364 Internal::DeleteArrayImpl<T, WTF::HasTrivialDestructor<T>::value>::fastDeleteArray(p);
368 template <typename T>
369 inline void fastNonNullDelete(T* p)
371 fastMallocMatchValidateFree(p, Internal::AllocTypeFastNew);
377 // This is a support template for fastDeleteArray.
378 // This handles the case wherein T has a trivial dtor.
379 template <typename T, bool trivialDtor>
380 struct NonNullDeleteArrayImpl {
381 static void fastNonNullDeleteArray(void* p)
383 fastMallocMatchValidateFree(p, Internal::AllocTypeFastNewArray);
384 // No need to destruct the objects in this case.
389 // This is a support template for fastDeleteArray.
390 // This handles the case wherein T has a non-trivial dtor.
391 template <typename T>
392 struct NonNullDeleteArrayImpl<T, false> {
393 static void fastNonNullDeleteArray(T* p)
399 T* pEnd = p + *a.size;
403 fastMallocMatchValidateFree(a.size, Internal::AllocTypeFastNewArray);
408 } // namespace Internal
410 template <typename T>
411 void fastNonNullDeleteArray(T* p)
413 Internal::NonNullDeleteArrayImpl<T, WTF::HasTrivialDestructor<T>::value>::fastNonNullDeleteArray(p);
419 using WTF::fastDeleteSkippingDestructor;
421 #endif // FastAllocBase_h