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
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-dev

Reply via email to