1 /* 2 * Copyright (C) 2008, 2009 Paul Pedriana <ppedriana (at) 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 422