[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