]> git.saurik.com Git - apple/javascriptcore.git/blame - wtf/FastAllocBase.h
JavaScriptCore-621.1.tar.gz
[apple/javascriptcore.git] / wtf / FastAllocBase.h
CommitLineData
ba379fdc
A
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
86namespace 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
f9bf01c6
A
304 template <typename T>
305 inline void fastDeleteSkippingDestructor(T* p)
306 {
307 if (!p)
308 return;
309
310 fastMallocMatchValidateFree(p, Internal::AllocTypeFastNew);
311 fastFree(p);
312 }
313
ba379fdc
A
314 namespace Internal {
315 // This is a support template for fastDeleteArray.
316 // This handles the case wherein T has a trivial dtor.
317 template <typename T, bool trivialDtor>
318 struct DeleteArrayImpl {
319 static void fastDeleteArray(void* p)
320 {
321 // No need to destruct the objects in this case.
322 // We expect that fastFree checks for null.
323 fastMallocMatchValidateFree(p, Internal::AllocTypeFastNewArray);
324 fastFree(p);
325 }
326 };
327
328 // This is a support template for fastDeleteArray.
329 // This handles the case wherein T has a non-trivial dtor.
330 template <typename T>
331 struct DeleteArrayImpl<T, false> {
332 static void fastDeleteArray(T* p)
333 {
334 if (!p)
335 return;
336
337 ArraySize<T> a;
338 a.t = p;
339 a.size--; // Decrement size pointer
340
341 T* pEnd = p + *a.size;
342 while (pEnd-- != p)
343 pEnd->~T();
344
345 fastMallocMatchValidateFree(a.size, Internal::AllocTypeFastNewArray);
346 fastFree(a.size);
347 }
348 };
349
350 } // namespace Internal
351
352 template <typename T>
353 void fastDeleteArray(T* p)
354 {
355 Internal::DeleteArrayImpl<T, WTF::HasTrivialDestructor<T>::value>::fastDeleteArray(p);
356 }
357
358
359 template <typename T>
360 inline void fastNonNullDelete(T* p)
361 {
362 fastMallocMatchValidateFree(p, Internal::AllocTypeFastNew);
363 p->~T();
364 fastFree(p);
365 }
366
367 namespace Internal {
368 // This is a support template for fastDeleteArray.
369 // This handles the case wherein T has a trivial dtor.
370 template <typename T, bool trivialDtor>
371 struct NonNullDeleteArrayImpl {
372 static void fastNonNullDeleteArray(void* p)
373 {
374 fastMallocMatchValidateFree(p, Internal::AllocTypeFastNewArray);
375 // No need to destruct the objects in this case.
376 fastFree(p);
377 }
378 };
379
380 // This is a support template for fastDeleteArray.
381 // This handles the case wherein T has a non-trivial dtor.
382 template <typename T>
383 struct NonNullDeleteArrayImpl<T, false> {
384 static void fastNonNullDeleteArray(T* p)
385 {
386 ArraySize<T> a;
387 a.t = p;
388 a.size--;
389
390 T* pEnd = p + *a.size;
391 while (pEnd-- != p)
392 pEnd->~T();
393
394 fastMallocMatchValidateFree(a.size, Internal::AllocTypeFastNewArray);
395 fastFree(a.size);
396 }
397 };
398
399 } // namespace Internal
400
401 template <typename T>
402 void fastNonNullDeleteArray(T* p)
403 {
404 Internal::NonNullDeleteArrayImpl<T, WTF::HasTrivialDestructor<T>::value>::fastNonNullDeleteArray(p);
405 }
406
407
408} // namespace WTF
409
ba379fdc 410using WTF::FastAllocBase;
f9bf01c6 411using WTF::fastDeleteSkippingDestructor;
ba379fdc
A
412
413#endif // FastAllocBase_h