]> git.saurik.com Git - apple/javascriptcore.git/blob - wtf/FastAllocBase.h
e4899aba3f71911687cceeafd3f2ee73217bb1af
[apple/javascriptcore.git] / 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 // Macro: WTF_MAKE_FAST_ALLOCATED
36 // namespace WTF {
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 {
52 // WTF_MAKE_FAST_ALLOCATED
53 // ...
54 // };
55 //
56 // struct Data {
57 // WTF_MAKE_FAST_ALLOCATED
58 // public:
59 // ...
60 // };
61 //
62 // char* charPtr = fastNew<char>();
63 // fastDelete(charPtr);
64 //
65 // char* charArrayPtr = fastNewArray<char>(37);
66 // fastDeleteArray(charArrayPtr);
67 //
68 // void** voidPtrPtr = fastNew<void*>();
69 // fastDelete(voidPtrPtr);
70 //
71 // void** voidPtrArrayPtr = fastNewArray<void*>(37);
72 // fastDeleteArray(voidPtrArrayPtr);
73 //
74 // POD* podPtr = fastNew<POD>();
75 // fastDelete(podPtr);
76 //
77 // POD* podArrayPtr = fastNewArray<POD>(37);
78 // fastDeleteArray(podArrayPtr);
79 //
80 // Object* objectPtr = fastNew<Object>();
81 // fastDelete(objectPtr);
82 //
83 // Object* objectArrayPtr = fastNewArray<Object>(37);
84 // fastDeleteArray(objectArrayPtr);
85 //
86
87 #include <new>
88 #include <stdint.h>
89 #include <stdlib.h>
90 #include <string.h>
91 #include "Assertions.h"
92 #include "FastMalloc.h"
93 #include "TypeTraits.h"
94
95 #define WTF_MAKE_FAST_ALLOCATED \
96 public: \
97 void* operator new(size_t, void* p) { return p; } \
98 void* operator new[](size_t, void* p) { return p; } \
99 \
100 void* operator new(size_t size) \
101 { \
102 void* p = ::WTF::fastMalloc(size); \
103 ::WTF::fastMallocMatchValidateMalloc(p, ::WTF::Internal::AllocTypeClassNew); \
104 return p; \
105 } \
106 \
107 void operator delete(void* p) \
108 { \
109 ::WTF::fastMallocMatchValidateFree(p, ::WTF::Internal::AllocTypeClassNew); \
110 ::WTF::fastFree(p); \
111 } \
112 \
113 void* operator new[](size_t size) \
114 { \
115 void* p = ::WTF::fastMalloc(size); \
116 ::WTF::fastMallocMatchValidateMalloc(p, ::WTF::Internal::AllocTypeClassNewArray); \
117 return p; \
118 } \
119 \
120 void operator delete[](void* p) \
121 { \
122 ::WTF::fastMallocMatchValidateFree(p, ::WTF::Internal::AllocTypeClassNewArray); \
123 ::WTF::fastFree(p); \
124 } \
125 private: \
126 typedef int ThisIsHereToForceASemicolonAfterThisMacro
127
128 namespace WTF {
129
130 // fastNew / fastDelete
131
132 template <typename T>
133 inline T* fastNew()
134 {
135 void* p = fastMalloc(sizeof(T));
136
137 if (!p)
138 return 0;
139
140 fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew);
141 return ::new(p) T;
142 }
143
144 template <typename T, typename Arg1>
145 inline T* fastNew(Arg1 arg1)
146 {
147 void* p = fastMalloc(sizeof(T));
148
149 if (!p)
150 return 0;
151
152 fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew);
153 return ::new(p) T(arg1);
154 }
155
156 template <typename T, typename Arg1, typename Arg2>
157 inline T* fastNew(Arg1 arg1, Arg2 arg2)
158 {
159 void* p = fastMalloc(sizeof(T));
160
161 if (!p)
162 return 0;
163
164 fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew);
165 return ::new(p) T(arg1, arg2);
166 }
167
168 template <typename T, typename Arg1, typename Arg2, typename Arg3>
169 inline T* fastNew(Arg1 arg1, Arg2 arg2, Arg3 arg3)
170 {
171 void* p = fastMalloc(sizeof(T));
172
173 if (!p)
174 return 0;
175
176 fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew);
177 return ::new(p) T(arg1, arg2, arg3);
178 }
179
180 template <typename T, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
181 inline T* fastNew(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4)
182 {
183 void* p = fastMalloc(sizeof(T));
184
185 if (!p)
186 return 0;
187
188 fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew);
189 return ::new(p) T(arg1, arg2, arg3, arg4);
190 }
191
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)
194 {
195 void* p = fastMalloc(sizeof(T));
196
197 if (!p)
198 return 0;
199
200 fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew);
201 return ::new(p) T(arg1, arg2, arg3, arg4, arg5);
202 }
203
204 namespace Internal {
205
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:
210 // struct Array {
211 // AllocAlignmentInteger m_size;
212 // T m_T[array count];
213 // };
214
215 template <typename T>
216 union ArraySize {
217 AllocAlignmentInteger* size;
218 T* t;
219 };
220
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)
226 {
227 T* p = static_cast<T*>(fastMalloc(sizeof(T) * count));
228 fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNewArray);
229 return p;
230 }
231 };
232
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)
238 {
239 T* p = static_cast<T*>(fastMalloc(sizeof(T) * count));
240
241 if (!p)
242 return 0;
243
244 fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNewArray);
245
246 for (T* pObject = p, *pObjectEnd = pObject + count; pObject != pObjectEnd; ++pObject)
247 ::new(pObject) T;
248
249 return p;
250 }
251 };
252
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)
258 {
259 void* p = fastMalloc(sizeof(AllocAlignmentInteger) + (sizeof(T) * count));
260 ArraySize<T> a = { static_cast<AllocAlignmentInteger*>(p) };
261
262 if (!p)
263 return 0;
264
265 fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNewArray);
266 *a.size++ = count;
267 // No need to construct the objects in this case.
268
269 return a.t;
270 }
271 };
272
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)
278 {
279 void* p = fastMalloc(sizeof(AllocAlignmentInteger) + (sizeof(T) * count));
280 ArraySize<T> a = { static_cast<AllocAlignmentInteger*>(p) };
281
282 if (!p)
283 return 0;
284
285 fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNewArray);
286 *a.size++ = count;
287
288 for (T* pT = a.t, *pTEnd = pT + count; pT != pTEnd; ++pT)
289 ::new(pT) T;
290
291 return a.t;
292 }
293 };
294 } // namespace Internal
295
296 template <typename T>
297 inline T* fastNewArray(size_t count)
298 {
299 return Internal::NewArrayImpl<T, WTF::HasTrivialConstructor<T>::value, WTF::HasTrivialDestructor<T>::value>::fastNewArray(count);
300 }
301
302 template <typename T>
303 inline void fastDelete(T* p)
304 {
305 if (!p)
306 return;
307
308 fastMallocMatchValidateFree(p, Internal::AllocTypeFastNew);
309 p->~T();
310 fastFree(p);
311 }
312
313 template <typename T>
314 inline void fastDeleteSkippingDestructor(T* p)
315 {
316 if (!p)
317 return;
318
319 fastMallocMatchValidateFree(p, Internal::AllocTypeFastNew);
320 fastFree(p);
321 }
322
323 namespace Internal {
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)
329 {
330 // No need to destruct the objects in this case.
331 // We expect that fastFree checks for null.
332 fastMallocMatchValidateFree(p, Internal::AllocTypeFastNewArray);
333 fastFree(p);
334 }
335 };
336
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)
342 {
343 if (!p)
344 return;
345
346 ArraySize<T> a;
347 a.t = p;
348 a.size--; // Decrement size pointer
349
350 T* pEnd = p + *a.size;
351 while (pEnd-- != p)
352 pEnd->~T();
353
354 fastMallocMatchValidateFree(a.size, Internal::AllocTypeFastNewArray);
355 fastFree(a.size);
356 }
357 };
358
359 } // namespace Internal
360
361 template <typename T>
362 void fastDeleteArray(T* p)
363 {
364 Internal::DeleteArrayImpl<T, WTF::HasTrivialDestructor<T>::value>::fastDeleteArray(p);
365 }
366
367
368 template <typename T>
369 inline void fastNonNullDelete(T* p)
370 {
371 fastMallocMatchValidateFree(p, Internal::AllocTypeFastNew);
372 p->~T();
373 fastFree(p);
374 }
375
376 namespace Internal {
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)
382 {
383 fastMallocMatchValidateFree(p, Internal::AllocTypeFastNewArray);
384 // No need to destruct the objects in this case.
385 fastFree(p);
386 }
387 };
388
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)
394 {
395 ArraySize<T> a;
396 a.t = p;
397 a.size--;
398
399 T* pEnd = p + *a.size;
400 while (pEnd-- != p)
401 pEnd->~T();
402
403 fastMallocMatchValidateFree(a.size, Internal::AllocTypeFastNewArray);
404 fastFree(a.size);
405 }
406 };
407
408 } // namespace Internal
409
410 template <typename T>
411 void fastNonNullDeleteArray(T* p)
412 {
413 Internal::NonNullDeleteArrayImpl<T, WTF::HasTrivialDestructor<T>::value>::fastNonNullDeleteArray(p);
414 }
415
416
417 } // namespace WTF
418
419 using WTF::fastDeleteSkippingDestructor;
420
421 #endif // FastAllocBase_h