Maybe move this work into a WebKit bug? dave
On Jun 18, 2008, at 5:09 PM, Paul Pedriana wrote: > I've created a working wtf/New.h file and a basic unit test for it. > It implements both of Maciej's recent proposals, which were > essentially 1: provide an allocation base class and 2: provide a > global allocator. I've done basic testing of this within my WebKit > build but haven't converted every usage of new/malloc to it on my > disk. This file wraps both malloc-based allocation and new-based > allocation and implements an AllocBase class. This version passes > everything to FastMalloc and so has the same behavior as current. I > thought I'd post this before doing any additional work. > > This version works via a templated function, which is essentially > what a C++ compiler generates on its own for new/delete. An > alternative would be to use a macro; the benefit would be that the > macro could be simply #defined to be new / delete for default users, > and the downside is that it would be a macro, which I understand is > something WebKit likes to avoid when possible. > > I've attached both New.h and NewTest.cpp to this email, but perhaps > the mailing list server will scrub it away, and so here is New.h: > > > -------------------------------------------------------------------------------- > // -*- mode: c++; c-basic-offset: 4 -*- > > > #ifndef WTF_New_h > #define WTF_New_h > > > // Provides customizable overrides of Malloc/Free and operator new/ > delete > // > // Provided functionality: > // class AllocBase{ ... }; > // > // void* Malloc(size_t n) > // void* ZeroedMalloc(size_t n) > // void* Calloc(size_t n_elements, size_t element_size) > // void Free(void* p) > // void* Realloc(void* p, size_t n) > // > // T* New<T>(); > // T* NewArray<T>(count); > // void Delete(T* p); > // void DeleteArray(T* p); > // > // Example usage: > // class Widget : public AllocBase { ... }; > // > // char* pChar = New<char>(); > // Delete(pChar); > // > // char* pCharArray = NewArray<char>(37); > // DeleteArray(pCharArray); > // > // void** pVoidPtr = New<void*>(); > // Delete(pVoidPtr); > // > // void** pVoidPtrArray = NewArray<void*>(37); > // DeleteArray(pVoidPtrArray); > // > // POD* pPOD = New<POD>(); > // Delete(pPOD); > // > // POD* pPODArray = NewArray<POD>(37); > // DeleteArray(pPODArray); > // > // Object* pObject = New<Object>(); > // Delete(pObject); > // > // Object* pObjectArray = NewArray<Object>(37); > // DeleteArray(pObjectArray); > // > > > #include <stdlib.h> > #include <new> > #include <string.h> > #include <stdint.h> > #include <wtf/Assertions.h> > #include <wtf/FastMalloc.h> > > > // Define type traits that allow us to optimize templated array new/ > delete. > // These could possibly go into a separate header file if useful. > // Recent versions of GCC's libstdc++ and VC++ have support for type > traits. > // To do: Include other compilers/libraries that support type_traits. > #if (defined(__GLIBCXX__) && (__GLIBCXX__ >= 20070724)) || > (defined(_MSC_VER) && (_MSC_VER >= 1500)) > #include <type_traits> > > namespace WTF { > using std::has_trivial_constructor; > using std::has_trivial_destructor; > } > > #else > namespace WTF { > > // This compiler doesn't provide type traits, so we provide a > basic small set. > template <typename T, T v> > struct integral_constant > { > static const T value = v; > typedef T value_type; > typedef integral_constant<T, v> type; > }; > > typedef integral_constant<bool, true> true_type; > typedef integral_constant<bool, false> false_type; > > > template <typename T> struct has_trivial_constructor : public > false_type{}; > template <typename T> struct has_trivial_destructor : public > false_type{}; > > // At least handle the case of scalar types. > // Ideally this would include volatile variations as well. > template <typename T> struct has_trivial_constructor<T*> : > public true_type{}; > template <typename T> struct has_trivial_destructor<T*> : > public true_type{}; > > template <> struct > has_trivial_constructor<float> : public > true_type{}; > template <> struct has_trivial_constructor<const > float> : public true_type{}; > template <> struct > has_trivial_constructor<double> : public > true_type{}; > template <> struct has_trivial_constructor<const > double> : public true_type{}; > template <> struct has_trivial_constructor<long > double> : public true_type{}; > template <> struct has_trivial_constructor<const long > double> : public true_type{}; > template <> struct has_trivial_constructor<unsigned > char> : public true_type{}; > template <> struct has_trivial_constructor<const unsigned > char> : public true_type{}; > template <> struct has_trivial_constructor<unsigned > short> : public true_type{}; > template <> struct has_trivial_constructor<const unsigned > short> : public true_type{}; > template <> struct has_trivial_constructor<unsigned > int> : public true_type{}; > template <> struct has_trivial_constructor<const unsigned > int> : public true_type{}; > template <> struct has_trivial_constructor<unsigned > long> : public true_type{}; > template <> struct has_trivial_constructor<const unsigned > long> : public true_type{}; > template <> struct has_trivial_constructor<unsigned long > long> : public true_type{}; > template <> struct has_trivial_constructor<const unsigned long > long> : public true_type{}; > template <> struct has_trivial_constructor<signed > char> : public true_type{}; > template <> struct has_trivial_constructor<const signed > char> : public true_type{}; > template <> struct has_trivial_constructor<signed > short> : public true_type{}; > template <> struct has_trivial_constructor<const signed > short> : public true_type{}; > template <> struct has_trivial_constructor<signed > int> : public true_type{}; > template <> struct has_trivial_constructor<const signed > int> : public true_type{}; > template <> struct has_trivial_constructor<signed > long> : public true_type{}; > template <> struct has_trivial_constructor<const signed > long> : public true_type{}; > template <> struct has_trivial_constructor<signed long > long> : public true_type{}; > template <> struct has_trivial_constructor<const signed long > long> : public true_type{}; > template <> struct > has_trivial_constructor<bool> : public > true_type{}; > template <> struct has_trivial_constructor<const > bool> : public true_type{}; > template <> struct > has_trivial_constructor<char> : public > true_type{}; > template <> struct has_trivial_constructor<const > char> : public true_type{}; > #if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED) > template <> struct > has_trivial_constructor<wchar_t> : public true_type{}; > template <> struct has_trivial_constructor<const > wchar_t> : public true_type{}; > #endif > > template <> struct > has_trivial_destructor<float> : public true_type{}; > template <> struct has_trivial_destructor<const > float> : public true_type{}; > template <> struct > has_trivial_destructor<double> : public true_type{}; > template <> struct has_trivial_destructor<const > double> : public true_type{}; > template <> struct has_trivial_destructor<long > double> : public true_type{}; > template <> struct has_trivial_destructor<const long > double> : public true_type{}; > template <> struct has_trivial_destructor<unsigned > char> : public true_type{}; > template <> struct has_trivial_destructor<const unsigned > char> : public true_type{}; > template <> struct has_trivial_destructor<unsigned > short> : public true_type{}; > template <> struct has_trivial_destructor<const unsigned > short> : public true_type{}; > template <> struct has_trivial_destructor<unsigned > int> : public true_type{}; > template <> struct has_trivial_destructor<const unsigned > int> : public true_type{}; > template <> struct has_trivial_destructor<unsigned > long> : public true_type{}; > template <> struct has_trivial_destructor<const unsigned > long> : public true_type{}; > template <> struct has_trivial_destructor<unsigned long > long> : public true_type{}; > template <> struct has_trivial_destructor<const unsigned long > long> : public true_type{}; > template <> struct has_trivial_destructor<signed > char> : public true_type{}; > template <> struct has_trivial_destructor<const signed > char> : public true_type{}; > template <> struct has_trivial_destructor<signed > short> : public true_type{}; > template <> struct has_trivial_destructor<const signed > short> : public true_type{}; > template <> struct has_trivial_destructor<signed > int> : public true_type{}; > template <> struct has_trivial_destructor<const signed > int> : public true_type{}; > template <> struct has_trivial_destructor<signed > long> : public true_type{}; > template <> struct has_trivial_destructor<const signed > long> : public true_type{}; > template <> struct has_trivial_destructor<signed long > long> : public true_type{}; > template <> struct has_trivial_destructor<const signed long > long> : public true_type{}; > template <> struct > has_trivial_destructor<bool> : public true_type{}; > template <> struct has_trivial_destructor<const > bool> : public true_type{}; > template <> struct > has_trivial_destructor<char> : public true_type{}; > template <> struct has_trivial_destructor<const > char> : public true_type{}; > #if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED) > template <> struct > has_trivial_destructor<wchar_t> : public true_type{}; > template <> struct has_trivial_destructor<const > wchar_t> : public true_type{}; > #endif > > } // namespace WTF > > #endif > > > > > namespace WTF { > > > > /////////////////////////////////////////////////////////////////////////////// > // AllocBase base class > /////////////////////////////////////////////////////////////////////////////// > > class AllocBase { > public: > void* operator new(size_t size) { > return fastMalloc(size); > } > > void operator delete(void* p) { > fastFree(p); // We don't need to check for NULL; the compiler > does this. > } > > void* operator new[](size_t size) { > return fastMalloc(size); > } > > void operator delete[](void* p) { > fastFree(p); // We don't need to check for NULL; the compiler > does this. > } > }; > > > > > /////////////////////////////////////////////////////////////////////////////// > // Malloc / Free > /////////////////////////////////////////////////////////////////////////////// > > inline void* Malloc(size_t n) { > return fastMalloc(n); > } > > > inline void* ZeroedMalloc(size_t n) { > void* const p = fastMalloc(n); > if(p) > memset(p, 0, n); > return p; > } > > > inline void* Calloc(size_t n_elements, size_t element_size) { > return fastCalloc(n_elements, element_size); > } > > > inline void Free(void* p) { > fastFree(p); > } > > > inline void* Realloc(void* p, size_t n) { > return fastRealloc(p, n); > } > > > > > > /////////////////////////////////////////////////////////////////////////////// > // New / Delete > /////////////////////////////////////////////////////////////////////////////// > > template <typename T> > inline T* New() { > void* p = fastMalloc(sizeof(T)); > > if(p) > return ::new(p) T; > > return NULL; > } > > > > // This is a support template for NewArray. > // This handles the case whereby T has a trivial ctor and a trivial > dtor. > template <typename T, bool trivialCtor, bool trivialDtor> > struct NewArrayImpl { > static T* NewArray(size_t count) { > return (T*)fastMalloc(sizeof(T) * count); > } > }; > > // This is a support template for NewArray. > // This handles the case whereby T has a non-trivial ctor and a > trivial dtor. > template <typename T> > struct NewArrayImpl<T, false, true> { > static T* NewArray(size_t count) { > uint64_t* p = (uint64_t*)fastMalloc(sizeof(uint64_t) + > (sizeof(T) * count)); > > if(p) { > *p++ = (uint64_t)count; > > for(T* pObject = (T*)p, *pObjectEnd = pObject + count; > pObject != pObjectEnd; ++pObject) > ::new(pObject) T; // To consider: handle ctor > exceptions if exceptions are enabled by the compiler. > } > > return (T*)p; > } > }; > > // This is a support template for NewArray. > // This handles the case whereby T has a trivial ctor and a non- > trivial dtor. > template <typename T> > struct NewArrayImpl<T, true, false> { > static T* NewArray(size_t count) { > uint64_t* p = (uint64_t*)fastMalloc(sizeof(uint64_t) + > (sizeof(T) * count)); > > if(p) { > *p++ = (uint64_t)count; > // No need to construct the objects in this case. > } > > return (T*)p; > } > }; > > // This is a support template for NewArray. > // This handles the case whereby T has a non-trivial ctor and a non- > trivial dtor. > template <typename T> > struct NewArrayImpl<T, false, false> { > static T* NewArray(size_t count) { > uint64_t* p = (uint64_t*)fastMalloc(sizeof(uint64_t) + > (sizeof(T) * count)); > > if(p) { > *p++ = (uint64_t)count; > > for(T* pObject = (T*)p, *pObjectEnd = pObject + count; > pObject != pObjectEnd; ++pObject) > ::new(pObject) T; // To consider: handle ctor > exceptions if exceptions are enabled by the compiler. > } > > return (T*)p; > } > }; > > > template <typename T> > inline T* NewArray(size_t count) { > return NewArrayImpl<T, WTF::has_trivial_constructor<T>::value, > WTF::has_trivial_destructor<T>::value>::NewArray(count); > } > > > > > template <typename T> > inline void Delete(T* p) { > if(p) {// As per the C++ standard, test for NULL. > p->~T(); > fastFree(p); > } > } > > > // This is a support template for DeleteArray. > // This handles the case whereby T has a trivial dtor. > template <typename T, bool trivialDtor> > struct DeleteArrayImpl { > static void DeleteArray(void* p) { > if(p) { // As per the C++ standard, test for NULL. > // No need to destruct the objects in this case. > fastFree(p); > } > } > }; > > // This is a support template for DeleteArray. > // This handles the case whereby T has a non-trivial dtor. > template <typename T> > struct DeleteArrayImpl<T, false> { > static void DeleteArray(T* p) { > if(p) { // As per the C++ standard, test for NULL. > T* pEnd = p + *((uint64_t*)p - 1); > while(pEnd-- != p) > pEnd->~T(); > > fastFree((void*)((uint64_t*)p - 1)); > } > } > }; > > > template <typename T> > void DeleteArray(T* p) { > DeleteArrayImpl<T, > WTF::has_trivial_destructor<T>::value>::DeleteArray(p); > } > > > } // namespace WTF > > > #endif // WTF_New_h > -------------------------------------------------------------------------------- > > > > > > > > > // -*- mode: c++; c-basic-offset: 4 -*- > > > #ifndef WTF_New_h > #define WTF_New_h > > > // Provides customizable overrides of fastMalloc/fastFree and > operator new/delete > // > // Provided functionality: > // class AllocBase{ ... }; > // > // void* Malloc(size_t n) > // void* ZeroedMalloc(size_t n) > // void* Calloc(size_t n_elements, size_t element_size) > // void Free(void* p) > // void* Realloc(void* p, size_t n) > // > // T* New<T>(); > // T* NewArray<T>(count); > // void Delete(T* p); > // void DeleteArray(T* p); > // > // Example usage: > // class Widget : public AllocBase { ... }; > // > // char* pChar = New<char>(); > // Delete(pChar); > // > // char* pCharArray = NewArray<char>(37); > // DeleteArray(pCharArray); > // > // void** pVoidPtr = New<void*>(); > // Delete(pVoidPtr); > // > // void** pVoidPtrArray = NewArray<void*>(37); > // DeleteArray(pVoidPtrArray); > // > // POD* pPOD = New<POD>(); > // Delete(pPOD); > // > // POD* pPODArray = NewArray<POD>(37); > // DeleteArray(pPODArray); > // > // Object* pObject = New<Object>(); > // Delete(pObject); > // > // Object* pObjectArray = NewArray<Object>(37); > // DeleteArray(pObjectArray); > // > > > #include <stdlib.h> > #include <new> > #include <string.h> > #include <stdint.h> > #include <wtf/Assertions.h> > #include <wtf/FastMalloc.h> > > > // Define type traits that allow us to optimize templated array new/ > delete. > // These could possibly go into a separate header file if useful. > // Recent versions of GCC's libstdc++ and VC++ have support for type > traits. > // To do: Include other compilers/libraries that support type_traits. > #if (defined(__GLIBCXX__) && (__GLIBCXX__ >= 20070724)) || > (defined(_MSC_VER) && (_MSC_VER >= 1500)) > #include <type_traits> > > namespace WTF { > using std::has_trivial_constructor; > using std::has_trivial_destructor; > } > > #else > namespace WTF { > > // This compiler doesn't provide type traits, so we provide a > basic small set. > template <typename T, T v> > struct integral_constant > { > static const T value = v; > typedef T value_type; > typedef integral_constant<T, v> type; > }; > > typedef integral_constant<bool, true> true_type; > typedef integral_constant<bool, false> false_type; > > > template <typename T> struct has_trivial_constructor : public > false_type{}; > template <typename T> struct has_trivial_destructor : public > false_type{}; > > // At least handle the case of scalar types. > // Ideally this would include volatile variations as well. > template <typename T> struct has_trivial_constructor<T*> : > public true_type{}; > template <typename T> struct has_trivial_destructor<T*> : > public true_type{}; > > template <> struct > has_trivial_constructor<float> : public > true_type{}; > template <> struct has_trivial_constructor<const > float> : public true_type{}; > template <> struct > has_trivial_constructor<double> : public > true_type{}; > template <> struct has_trivial_constructor<const > double> : public true_type{}; > template <> struct has_trivial_constructor<long > double> : public true_type{}; > template <> struct has_trivial_constructor<const long > double> : public true_type{}; > template <> struct has_trivial_constructor<unsigned > char> : public true_type{}; > template <> struct has_trivial_constructor<const unsigned > char> : public true_type{}; > template <> struct has_trivial_constructor<unsigned > short> : public true_type{}; > template <> struct has_trivial_constructor<const unsigned > short> : public true_type{}; > template <> struct has_trivial_constructor<unsigned > int> : public true_type{}; > template <> struct has_trivial_constructor<const unsigned > int> : public true_type{}; > template <> struct has_trivial_constructor<unsigned > long> : public true_type{}; > template <> struct has_trivial_constructor<const unsigned > long> : public true_type{}; > template <> struct has_trivial_constructor<unsigned long > long> : public true_type{}; > template <> struct has_trivial_constructor<const unsigned > long long> : public true_type{}; > template <> struct has_trivial_constructor<signed > char> : public true_type{}; > template <> struct has_trivial_constructor<const signed > char> : public true_type{}; > template <> struct has_trivial_constructor<signed > short> : public true_type{}; > template <> struct has_trivial_constructor<const signed > short> : public true_type{}; > template <> struct has_trivial_constructor<signed > int> : public true_type{}; > template <> struct has_trivial_constructor<const signed > int> : public true_type{}; > template <> struct has_trivial_constructor<signed > long> : public true_type{}; > template <> struct has_trivial_constructor<const signed > long> : public true_type{}; > template <> struct has_trivial_constructor<signed long > long> : public true_type{}; > template <> struct has_trivial_constructor<const signed long > long> : public true_type{}; > template <> struct > has_trivial_constructor<bool> : public > true_type{}; > template <> struct has_trivial_constructor<const > bool> : public true_type{}; > template <> struct > has_trivial_constructor<char> : public > true_type{}; > template <> struct has_trivial_constructor<const > char> : public true_type{}; > #if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED) > template <> struct > has_trivial_constructor<wchar_t> : public true_type{}; > template <> struct has_trivial_constructor<const > wchar_t> : public true_type{}; > #endif > > template <> struct > has_trivial_destructor<float> : public true_type{}; > template <> struct has_trivial_destructor<const > float> : public true_type{}; > template <> struct > has_trivial_destructor<double> : public true_type{}; > template <> struct has_trivial_destructor<const > double> : public true_type{}; > template <> struct has_trivial_destructor<long > double> : public true_type{}; > template <> struct has_trivial_destructor<const long > double> : public true_type{}; > template <> struct has_trivial_destructor<unsigned > char> : public true_type{}; > template <> struct has_trivial_destructor<const unsigned > char> : public true_type{}; > template <> struct has_trivial_destructor<unsigned > short> : public true_type{}; > template <> struct has_trivial_destructor<const unsigned > short> : public true_type{}; > template <> struct has_trivial_destructor<unsigned > int> : public true_type{}; > template <> struct has_trivial_destructor<const unsigned > int> : public true_type{}; > template <> struct has_trivial_destructor<unsigned > long> : public true_type{}; > template <> struct has_trivial_destructor<const unsigned > long> : public true_type{}; > template <> struct has_trivial_destructor<unsigned long > long> : public true_type{}; > template <> struct has_trivial_destructor<const unsigned long > long> : public true_type{}; > template <> struct has_trivial_destructor<signed > char> : public true_type{}; > template <> struct has_trivial_destructor<const signed > char> : public true_type{}; > template <> struct has_trivial_destructor<signed > short> : public true_type{}; > template <> struct has_trivial_destructor<const signed > short> : public true_type{}; > template <> struct has_trivial_destructor<signed > int> : public true_type{}; > template <> struct has_trivial_destructor<const signed > int> : public true_type{}; > template <> struct has_trivial_destructor<signed > long> : public true_type{}; > template <> struct has_trivial_destructor<const signed > long> : public true_type{}; > template <> struct has_trivial_destructor<signed long > long> : public true_type{}; > template <> struct has_trivial_destructor<const signed long > long> : public true_type{}; > template <> struct > has_trivial_destructor<bool> : public true_type{}; > template <> struct has_trivial_destructor<const > bool> : public true_type{}; > template <> struct > has_trivial_destructor<char> : public true_type{}; > template <> struct has_trivial_destructor<const > char> : public true_type{}; > #if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED) > template <> struct > has_trivial_destructor<wchar_t> : public true_type{}; > template <> struct has_trivial_destructor<const > wchar_t> : public true_type{}; > #endif > > } // namespace WTF > > #endif > > > > > namespace WTF { > > > > /////////////////////////////////////////////////////////////////////////////// > // AllocBase base class > /////////////////////////////////////////////////////////////////////////////// > > class AllocBase { > public: > void* operator new(size_t size) { > return fastMalloc(size); > } > > void operator delete(void* p) { > fastFree(p); // We don't need to check for NULL; the > compiler does this. > } > > void* operator new[](size_t size) { > return fastMalloc(size); > } > > void operator delete[](void* p) { > fastFree(p); // We don't need to check for NULL; the > compiler does this. > } > }; > > > > > /////////////////////////////////////////////////////////////////////////////// > // Malloc / Free > /////////////////////////////////////////////////////////////////////////////// > > inline void* Malloc(size_t n) { > return fastMalloc(n); > } > > > inline void* ZeroedMalloc(size_t n) { > void* const p = fastMalloc(n); > if(p) > memset(p, 0, n); > return p; > } > > > inline void* Calloc(size_t n_elements, size_t element_size) { > return fastCalloc(n_elements, element_size); > } > > > inline void Free(void* p) { > fastFree(p); > } > > > inline void* Realloc(void* p, size_t n) { > return fastRealloc(p, n); > } > > > > > > /////////////////////////////////////////////////////////////////////////////// > // New / Delete > /////////////////////////////////////////////////////////////////////////////// > > template <typename T> > inline T* New() { > void* p = fastMalloc(sizeof(T)); > > if(p) > return ::new(p) T; > > return NULL; > } > > > > // This is a support template for NewArray. > // This handles the case whereby T has a trivial ctor and a trivial > dtor. > template <typename T, bool trivialCtor, bool trivialDtor> > struct NewArrayImpl { > static T* NewArray(size_t count) { > return (T*)fastMalloc(sizeof(T) * count); > } > }; > > // This is a support template for NewArray. > // This handles the case whereby T has a non-trivial ctor and a > trivial dtor. > template <typename T> > struct NewArrayImpl<T, false, true> { > static T* NewArray(size_t count) { > uint64_t* p = (uint64_t*)fastMalloc(sizeof(uint64_t) + > (sizeof(T) * count)); > > if(p) { > *p++ = (uint64_t)count; > > for(T* pObject = (T*)p, *pObjectEnd = pObject + count; > pObject != pObjectEnd; ++pObject) > ::new(pObject) T; // To consider: handle ctor > exceptions if exceptions are enabled by the compiler. > } > > return (T*)p; > } > }; > > // This is a support template for NewArray. > // This handles the case whereby T has a trivial ctor and a non- > trivial dtor. > template <typename T> > struct NewArrayImpl<T, true, false> { > static T* NewArray(size_t count) { > uint64_t* p = (uint64_t*)fastMalloc(sizeof(uint64_t) + > (sizeof(T) * count)); > > if(p) { > *p++ = (uint64_t)count; > // No need to construct the objects in this case. > } > > return (T*)p; > } > }; > > // This is a support template for NewArray. > // This handles the case whereby T has a non-trivial ctor and a non- > trivial dtor. > template <typename T> > struct NewArrayImpl<T, false, false> { > static T* NewArray(size_t count) { > uint64_t* p = (uint64_t*)fastMalloc(sizeof(uint64_t) + > (sizeof(T) * count)); > > if(p) { > *p++ = (uint64_t)count; > > for(T* pObject = (T*)p, *pObjectEnd = pObject + count; > pObject != pObjectEnd; ++pObject) > ::new(pObject) T; // To consider: handle ctor > exceptions if exceptions are enabled by the compiler. > } > > return (T*)p; > } > }; > > > template <typename T> > inline T* NewArray(size_t count) { > return NewArrayImpl<T, WTF::has_trivial_constructor<T>::value, > WTF::has_trivial_destructor<T>::value>::NewArray(count); > } > > > > > template <typename T> > inline void Delete(T* p) { > if(p) {// As per the C++ standard, test for NULL. > p->~T(); > fastFree(p); > } > } > > > // This is a support template for DeleteArray. > // This handles the case whereby T has a trivial dtor. > template <typename T, bool trivialDtor> > struct DeleteArrayImpl { > static void DeleteArray(void* p) { > if(p) { // As per the C++ standard, test for NULL. > // No need to destruct the objects in this case. > fastFree(p); > } > } > }; > > // This is a support template for DeleteArray. > // This handles the case whereby T has a non-trivial dtor. > template <typename T> > struct DeleteArrayImpl<T, false> { > static void DeleteArray(T* p) { > if(p) { // As per the C++ standard, test for NULL. > T* pEnd = p + *((uint64_t*)p - 1); > while(pEnd-- != p) > pEnd->~T(); > > fastFree((void*)((uint64_t*)p - 1)); > } > } > }; > > > template <typename T> > void DeleteArray(T* p) { > DeleteArrayImpl<T, > WTF::has_trivial_destructor<T>::value>::DeleteArray(p); > } > > > } // namespace WTF > > > #endif // WTF_New_h > > > > > > > > > > > > // -*- mode: c++; c-basic-offset: 4 -*- > > > #include <wtf/New.h> > #include <wtf/Assertions.h> > > > > /////////////////////////////////////////////////////////////////////////////// > // Inherited > /////////////////////////////////////////////////////////////////////////////// > > class Inherited : public WTF::AllocBase > { > public: > static int ctorCount; > static int dtorCount; > > int x; > > Inherited() { ++ctorCount; } > Inherited(const Inherited&) { ++ctorCount; } > ~Inherited() { ++dtorCount; } > Inherited& operator =(const Inherited&) { return *this; } > }; > > int Inherited::ctorCount = 0; > int Inherited::dtorCount = 0; > > > > /////////////////////////////////////////////////////////////////////////////// > // POD > /////////////////////////////////////////////////////////////////////////////// > > struct POD > { > int x; > }; > > > > /////////////////////////////////////////////////////////////////////////////// > // Object > /////////////////////////////////////////////////////////////////////////////// > > class Object > { > public: > static int ctorCount; > static int dtorCount; > > int x; > > Object() { ++ctorCount; } > Object(const Object&) { ++ctorCount; } > ~Object() { ++dtorCount; } > Object& operator =(const Object&) { return *this; } > }; > > int Object::ctorCount = 0; > int Object::dtorCount = 0; > > > > /////////////////////////////////////////////////////////////////////////////// > // VerifyIsAligned > /////////////////////////////////////////////////////////////////////////////// > > template <typename T> > bool VerifyIsAligned(T* p) > { > const bool isAligned = ((size_t)((((uintptr_t)p ^ ((uintptr_t)p - > 1)) >> 1) + 1) >= sizeof(T)); > ASSERT(isAligned); > return isAligned; > } > > > > > /////////////////////////////////////////////////////////////////////////////// > // Assert that global new/delete are never called. > /////////////////////////////////////////////////////////////////////////////// > > void* operator new(size_t) throw() { > ASSERT(false); > return NULL; > } > > void operator delete(void*) { > ASSERT(false); > } > > void* operator new[](size_t) throw() { > ASSERT(false); > return NULL; > } > > void operator delete[](void*) { > ASSERT(false); > } > > > > /////////////////////////////////////////////////////////////////////////////// > // TestWTFNew > /////////////////////////////////////////////////////////////////////////////// > bool TestWTFNew(); > > bool TestWTFNew() > { > using namespace WTF; > > bool success = true; > size_t i; > void* p; > > // AllocBase > AllocBase* pAllocBase = new AllocBase; > VerifyIsAligned(pAllocBase); > delete pAllocBase; > > AllocBase* pAllocBaseArray = new AllocBase[37]; > VerifyIsAligned(pAllocBaseArray); > delete[] pAllocBaseArray; > > > // AllocBase / Inherited > Inherited* pInherited = new Inherited; > VerifyIsAligned(pInherited); > pInherited->x = 1; > delete pInherited; > > Inherited* pInheritedArray = new Inherited[37]; > VerifyIsAligned(pInheritedArray); > for(i = 0; i < 37; ++i) > pInheritedArray[i].x = 1; > delete[] pInheritedArray; > > ASSERT((Inherited::ctorCount == 38) && (Inherited::dtorCount == > 38)); > success == success && ((Inherited::ctorCount == 38) && > (Inherited::dtorCount == 38)); > > > // Malloc > p = Malloc(37); > memset(p, 1, 37); > Free(p); > > > // Realloc > p = Malloc(37); > memset(p, 1, 37); > p = Realloc(p, 40); > for(i = 0; i < 37; ++i) > ASSERT(*(char*)p == 1); > Free(p); > > > // Realloc > p = Realloc(NULL, 37); > memset(p, 1, 37); > Free(p); > > > // ZeroedMalloc > p = ZeroedMalloc(37); > for(i = 0; i < 37; ++i) > ASSERT(*(char*)p == 0); > Free(p); > > > // Calloc > p = Calloc(3, 37); > for(i = 0; i < (3 * 37); ++i) > ASSERT(*(char*)p == 0); > Free(p); > > > // char > char* pChar = New<char>(); > Delete(pChar); > > char* pCharArray = NewArray<char>(37); > for(i = 0; i < 37; ++i) > pCharArray[i] = 1; > DeleteArray(pCharArray); > > > // double > double* pDouble = New<double>(); > VerifyIsAligned(pDouble); > *pDouble = 1; > Delete(pDouble); > > double* pDoubleArray = NewArray<double>(37); > VerifyIsAligned(pDoubleArray); > for(i = 0; i < 37; ++i) > pDoubleArray[i] = 1; > DeleteArray(pDoubleArray); > > > // void* > void** pVoidPtr = New<void*>(); > Delete(pVoidPtr); > > void** pVoidPtrArray = NewArray<void*>(37); > for(i = 0; i < 37; ++i) > pVoidPtrArray[i] = NULL; > DeleteArray(pVoidPtrArray); > > > // POD > POD* pPOD = New<POD>(); > VerifyIsAligned(pPOD); > pPOD->x = 1; > Delete(pPOD); > > POD* pPODArray = NewArray<POD>(37); > VerifyIsAligned(pPODArray); > for(i = 0; i < 37; ++i) > pPODArray[i].x = 1; > DeleteArray(pPODArray); > > > // Object > Object* pObject = New<Object>(); > VerifyIsAligned(pObject); > pObject->x = 1; > Delete(pObject); > > Object* pObjectArray = NewArray<Object>(37); > VerifyIsAligned(pObjectArray); > for(i = 0; i < 37; ++i) > pObjectArray[i].x = 1; > DeleteArray(pObjectArray); > > ASSERT((Object::ctorCount == 38) && (Object::dtorCount == 38)); > success == success && ((Object::ctorCount == 38) && > (Object::dtorCount == 38)); > > return success; > } > > > > _______________________________________________ > webkit-dev mailing list > webkit-dev@lists.webkit.org > http://lists.webkit.org/mailman/listinfo.cgi/webkit-dev _______________________________________________ webkit-dev mailing list webkit-dev@lists.webkit.org http://lists.webkit.org/mailman/listinfo.cgi/webkit-dev