9fcbbc1c483789afa8553a06e67159e9bbe009d0
[WebKit-https.git] / JavaScriptCore / wtf / FastAllocBase.h
1 /*
2  * Copyright (C) 2008, 2009 Paul Pedriana <ppedriana@ea.com>. 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  *
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.
16  *
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.
27  */
28
29 #ifndef FastAllocBase_h
30 #define FastAllocBase_h
31
32 // Provides customizable overrides of fastMalloc/fastFree and operator new/delete
33 //
34 // Provided functionality:
35 //    namespace WTF {
36 //        class FastAllocBase;
37 //
38 //        T*    fastNew<T>();
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);
46 //    }
47 //
48 // FastDelete assumes that the underlying
49 //
50 // Example usage:
51 //    class Widget : public FastAllocBase { ... };
52 //
53 //    char* charPtr = fastNew<char>();
54 //    fastDelete(charPtr);
55 //
56 //    char* charArrayPtr = fastNewArray<char>(37);
57 //    fastDeleteArray(charArrayPtr);
58 //
59 //    void** voidPtrPtr = fastNew<void*>();
60 //    fastDelete(voidPtrPtr);
61 //
62 //    void** voidPtrArrayPtr = fastNewArray<void*>(37);
63 //    fastDeleteArray(voidPtrArrayPtr);
64 //
65 //    POD* podPtr = fastNew<POD>();
66 //    fastDelete(podPtr);
67 //
68 //    POD* podArrayPtr = fastNewArray<POD>(37);
69 //    fastDeleteArray(podArrayPtr);
70 //
71 //    Object* objectPtr = fastNew<Object>();
72 //    fastDelete(objectPtr);
73 //
74 //    Object* objectArrayPtr = fastNewArray<Object>(37);
75 //    fastDeleteArray(objectArrayPtr);
76 //
77
78 #include <new>
79 #include <stdint.h>
80 #include <stdlib.h>
81 #include <string.h>
82 #include "Assertions.h"
83 #include "FastMalloc.h"
84 #include "TypeTraits.h"
85
86 namespace WTF {
87
88     class FastAllocBase {
89     public:
90         // Placement operator new.
91         void* operator new(size_t, void* p) { return p; }
92         void* operator new[](size_t, void* p) { return p; }
93
94         void* operator new(size_t size)
95         {
96             void* p = fastMalloc(size);
97             fastMallocMatchValidateMalloc(p, Internal::AllocTypeClassNew);
98             return p;
99         }
100
101         void operator delete(void* p)
102         {
103             fastMallocMatchValidateFree(p, Internal::AllocTypeClassNew);
104             fastFree(p);
105         }
106
107         void* operator new[](size_t size)
108         {
109             void* p = fastMalloc(size);
110             fastMallocMatchValidateMalloc(p, Internal::AllocTypeClassNewArray);
111             return p;
112         }
113
114         void operator delete[](void* p)
115         {
116             fastMallocMatchValidateFree(p, Internal::AllocTypeClassNewArray);
117             fastFree(p);
118         }
119     };
120
121     // fastNew / fastDelete
122
123     template <typename T>
124     inline T* fastNew()
125     {
126         void* p = fastMalloc(sizeof(T));
127
128         if (!p)
129             return 0;
130
131         fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew);
132         return ::new(p) T;
133     }
134
135     template <typename T, typename Arg1>
136     inline T* fastNew(Arg1 arg1)
137     {
138         void* p = fastMalloc(sizeof(T));
139
140         if (!p)
141             return 0;
142
143         fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew);
144         return ::new(p) T(arg1);
145     }
146
147     template <typename T, typename Arg1, typename Arg2>
148     inline T* fastNew(Arg1 arg1, Arg2 arg2)
149     {
150         void* p = fastMalloc(sizeof(T));
151
152         if (!p)
153             return 0;
154
155         fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew);
156         return ::new(p) T(arg1, arg2);
157     }
158
159     template <typename T, typename Arg1, typename Arg2, typename Arg3>
160     inline T* fastNew(Arg1 arg1, Arg2 arg2, Arg3 arg3)
161     {
162         void* p = fastMalloc(sizeof(T));
163
164         if (!p)
165             return 0;
166
167         fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew);
168         return ::new(p) T(arg1, arg2, arg3);
169     }
170
171     template <typename T, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
172     inline T* fastNew(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4)
173     {
174         void* p = fastMalloc(sizeof(T));
175
176         if (!p)
177             return 0;
178
179         fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew);
180         return ::new(p) T(arg1, arg2, arg3, arg4);
181     }
182
183     template <typename T, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5>
184     inline T* fastNew(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5)
185     {
186         void* p = fastMalloc(sizeof(T));
187
188         if (!p)
189             return 0;
190
191         fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew);
192         return ::new(p) T(arg1, arg2, arg3, arg4, arg5);
193     }
194
195     namespace Internal {
196
197         // We define a union of pointer to an integer and pointer to T.
198         // When non-POD arrays are allocated we add a few leading bytes to tell what
199         // the size of the array is. We return to the user the pointer to T.
200         // The way to think of it is as if we allocate a struct like so:
201         //    struct Array {
202         //        AllocAlignmentInteger m_size;
203         //        T m_T[array count];
204         //    };
205
206         template <typename T>
207         union ArraySize {
208             AllocAlignmentInteger* size;
209             T* t;
210         };
211
212         // This is a support template for fastNewArray.
213         // This handles the case wherein T has a trivial ctor and a trivial dtor.
214         template <typename T, bool trivialCtor, bool trivialDtor>
215         struct NewArrayImpl {
216             static T* fastNewArray(size_t count)
217             {
218                 T* p = static_cast<T*>(fastMalloc(sizeof(T) * count));
219                 fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNewArray);
220                 return p;
221             }
222         };
223
224         // This is a support template for fastNewArray.
225         // This handles the case wherein T has a non-trivial ctor and a trivial dtor.
226         template <typename T>
227         struct NewArrayImpl<T, false, true> {
228             static T* fastNewArray(size_t count)
229             {
230                 T* p = static_cast<T*>(fastMalloc(sizeof(T) * count));
231
232                 if (!p)
233                     return 0;
234
235                 fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNewArray);
236
237                 for (T* pObject = p, *pObjectEnd = pObject + count; pObject != pObjectEnd; ++pObject)
238                     ::new(pObject) T;
239
240                 return p;
241             }
242         };
243
244         // This is a support template for fastNewArray.
245         // This handles the case wherein T has a trivial ctor and a non-trivial dtor.
246         template <typename T>
247         struct NewArrayImpl<T, true, false> {
248             static T* fastNewArray(size_t count)
249             {
250                 void* p = fastMalloc(sizeof(AllocAlignmentInteger) + (sizeof(T) * count));
251                 ArraySize<T> a = { static_cast<AllocAlignmentInteger*>(p) };
252
253                 if (!p)
254                     return 0;
255
256                 fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNewArray);
257                 *a.size++ = count;
258                 // No need to construct the objects in this case.
259
260                 return a.t;
261             }
262         };
263
264         // This is a support template for fastNewArray.
265         // This handles the case wherein T has a non-trivial ctor and a non-trivial dtor.
266         template <typename T>
267         struct NewArrayImpl<T, false, false> {
268             static T* fastNewArray(size_t count)
269             {
270                 void* p = fastMalloc(sizeof(AllocAlignmentInteger) + (sizeof(T) * count));
271                 ArraySize<T> a = { static_cast<AllocAlignmentInteger*>(p) };
272
273                 if (!p)
274                     return 0;
275
276                 fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNewArray);
277                 *a.size++ = count;
278
279                 for (T* pT = a.t, *pTEnd = pT + count; pT != pTEnd; ++pT)
280                     ::new(pT) T;
281
282                 return a.t;
283             }
284         };
285     } // namespace Internal
286
287     template <typename T>
288     inline T* fastNewArray(size_t count)
289     {
290         return Internal::NewArrayImpl<T, WTF::HasTrivialConstructor<T>::value, WTF::HasTrivialDestructor<T>::value>::fastNewArray(count);
291     }
292
293     template <typename T>
294     inline void fastDelete(T* p)
295     {
296         if (!p)
297             return;
298
299         fastMallocMatchValidateFree(p, Internal::AllocTypeFastNew);
300         p->~T();
301         fastFree(p);
302     }
303
304     namespace Internal {
305         // This is a support template for fastDeleteArray.
306         // This handles the case wherein T has a trivial dtor.
307         template <typename T, bool trivialDtor>
308         struct DeleteArrayImpl {
309             static void fastDeleteArray(void* p)
310             {
311                 // No need to destruct the objects in this case.
312                 // We expect that fastFree checks for null.
313                 fastMallocMatchValidateFree(p, Internal::AllocTypeFastNewArray);
314                 fastFree(p);
315             }
316         };
317
318         // This is a support template for fastDeleteArray.
319         // This handles the case wherein T has a non-trivial dtor.
320         template <typename T>
321         struct DeleteArrayImpl<T, false> {
322             static void fastDeleteArray(T* p)
323             {
324                 if (!p)
325                     return;
326
327                 ArraySize<T> a;
328                 a.t = p;
329                 a.size--; // Decrement size pointer
330
331                 T* pEnd = p + *a.size;
332                 while (pEnd-- != p)
333                     pEnd->~T();
334
335                 fastMallocMatchValidateFree(a.size, Internal::AllocTypeFastNewArray);
336                 fastFree(a.size);
337             }
338         };
339
340     } // namespace Internal
341
342     template <typename T>
343     void fastDeleteArray(T* p)
344     {
345         Internal::DeleteArrayImpl<T, WTF::HasTrivialDestructor<T>::value>::fastDeleteArray(p);
346     }
347
348
349     template <typename T>
350     inline void fastNonNullDelete(T* p)
351     {
352         fastMallocMatchValidateFree(p, Internal::AllocTypeFastNew);
353         p->~T();
354         fastFree(p);
355     }
356
357     namespace Internal {
358         // This is a support template for fastDeleteArray.
359         // This handles the case wherein T has a trivial dtor.
360         template <typename T, bool trivialDtor>
361         struct NonNullDeleteArrayImpl {
362             static void fastNonNullDeleteArray(void* p)
363             {
364                 fastMallocMatchValidateFree(p, Internal::AllocTypeFastNewArray);
365                 // No need to destruct the objects in this case.
366                 fastFree(p);
367             }
368         };
369
370         // This is a support template for fastDeleteArray.
371         // This handles the case wherein T has a non-trivial dtor.
372         template <typename T>
373         struct NonNullDeleteArrayImpl<T, false> {
374             static void fastNonNullDeleteArray(T* p)
375             {
376                 ArraySize<T> a;
377                 a.t = p;
378                 a.size--;
379
380                 T* pEnd = p + *a.size;
381                 while (pEnd-- != p)
382                     pEnd->~T();
383
384                 fastMallocMatchValidateFree(a.size, Internal::AllocTypeFastNewArray);
385                 fastFree(a.size);
386             }
387         };
388
389     } // namespace Internal
390
391     template <typename T>
392     void fastNonNullDeleteArray(T* p)
393     {
394         Internal::NonNullDeleteArrayImpl<T, WTF::HasTrivialDestructor<T>::value>::fastNonNullDeleteArray(p);
395     }
396
397
398 } // namespace WTF
399
400 // Using WTF::FastAllocBase to avoid using FastAllocBase's explicit qualification by WTF::.
401 using WTF::FastAllocBase;
402
403 #endif // FastAllocBase_h