[webkit-dev] Update on memory allocation control proposal...
David Hyatt
hyatt at apple.com
Wed Jun 18 15:15:50 PDT 2008
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 at lists.webkit.org
> http://lists.webkit.org/mailman/listinfo.cgi/webkit-dev
More information about the webkit-dev
mailing list