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