[webkit-dev] WebKit memory management?
Paul Pedriana
ppedriana at gmail.com
Wed Jun 4 16:33:54 PDT 2008
I have implemented a version of Maciej's suggestion #2 below, with basic
documentation and a basic test. A slight alternative would be to change
the 'new' syntax to to use a macro which would allow for a simpler
reference version that used global new/delete, but would introduce a
preprocessor macro. I can also create an example of Maciej's suggestion
#1, though it will have to wait a few hours while I finish some other work.
------------------------------------------------------------------------
// Customizable overrides of operator new/delete
//
// Provided functionality:
// T* wk_new<T>();
// T* wk_new_array<T>(count);
// void wk_delete(T* p);
// void wk_delete_array(T* p);
//
// Example usage:
// char* pChar = wk_new<char>();
// wk_delete(pChar);
//
// char* pCharArray = wk_new_array<char>(37);
// wk_delete_array(pCharArray);
//
// POD* pPOD = wk_new<POD>();
// wk_delete(pPOD);
//
// POD* pPODArray = wk_new_array<POD>(37);
// wk_delete_array(pPODArray);
//
// Object* pObject = wk_new<Object>();
// wk_delete(pObject);
//
// Object* pObjectArray = wk_new_array<Object>(37);
// wk_delete_array(pObjectArray);
//
template <typename T>
inline T* wk_new()
{
void* p = malloc(sizeof(T));
if(p)
return new(p) T;
return NULL;
}
// Note that the code below is similar to what the compiler generates
for built-in array operator new.
// This can be specialized for POD types to avoid the array size prefix
altogether.
// It can be specialized for types with natural alignment less than
uint64_t and save 4 bytes on 32 bit systems.
template <typename T>
inline T* wk_new_array(size_t count)
{
uint64_t* p = (uint64_t*)malloc(sizeof(uint64_t) + (sizeof(T) * count));
if(p)
{
*p++ = (uint64_t)count;
for(T* pObject = (T*)(void*)p, *pObjectEnd = pObject + count;
pObject != pObjectEnd; ++pObject)
new(pObject) T; // To consider: handle ctor exceptions.
}
return (T*)(void*)p;
}
// Note that the code below is similar to what the compiler generates
for built-in array operator new.
template <typename T>
inline void wk_delete(T* p)
{
if(p) // As per the C++ standard, test for NULL.
{
p->~T();
free(p);
}
}
// Note that the code below is similar to what the compiler generates
for built-in array operator delete.
// This can be specialized for POD types to avoid the array size prefix
altogether.
// It can be specialized for types with natural alignment less than
uint64_t and save 4 bytes on 32 bit systems.
template <typename T>
void wk_delete_array(T* p)
{
if(p) // As per the C++ standard, test for NULL.
{
T* pEnd = p + *((uint64_t*)p - 1);
while(pEnd-- != p)
pEnd->~T();
free((void*)((uint64_t*)p - 1));
}
}
------------------------------------------------------------------------
Basic test code:
------------------------------------------------------------------------
struct Object
{
static int ctorCount;
static int dtorCount;
Object() { ++ctorCount; }
Object(const Object&) { ++ctorCount; }
~Object() { ++dtorCount; }
Object& operator =(const Object&) { }
};
int Object::ctorCount = 0;
int Object::dtorCount = 0;
struct POD
{
int x;
};
template <typename T>
void VerifyIsAligned(T* p)
{
assert((size_t)((((uintptr_t)p ^ ((uintptr_t)p - 1)) >> 1) + 1) >=
sizeof(T));
}
void DoSomething()
{
// char
char* pChar = wk_new<char>();
wk_delete(pChar);
char* pCharArray = wk_new_array<char>(37);
wk_delete_array(pCharArray);
// double
double* pDouble = wk_new<double>();
VerifyIsAligned(pDouble);
wk_delete(pDouble);
double* pDoubleArray = wk_new_array<double>(37);
VerifyIsAligned(pDoubleArray);
wk_delete_array(pDoubleArray);
// POD
POD* pPOD = wk_new<POD>();
VerifyIsAligned(pPOD);
wk_delete(pPOD);
POD* pPODArray = wk_new_array<POD>(37);
VerifyIsAligned(pPODArray);
wk_delete_array(pPODArray);
// Object
Object* pObject = wk_new<Object>();
VerifyIsAligned(pObject);
wk_delete(pObject);
Object* pObjectArray = wk_new_array<Object>(37);
VerifyIsAligned(pObjectArray);
wk_delete_array(pObjectArray);
assert((Object::ctorCount == 38) && (Object::dtorCount == 38));
}
------------------------------------------------------------------------
>
> On Jun 3, 2008, at 10:58 PM, Paul Pedriana wrote:
>> Thanks for the response. I'm sorry, and perhaps I misunderstand, but
>> I believe your statement about inline operator new is incorrect.
>> Unless I misunderstand you, what you say is not supported by any
>> existing compiler nor is it supported by the C++ language standard.
>> In summary, the 'inline' keyword does not negate or obviate the One
>> Definition Rule. You can demonstrate the problem with the code below.
>> Feel free to correct any misunderstanding that I may have of your
>> explanation.
>
> This happens to work as intended on Mac OS X because
> WTF_PRIVATE_INLINE expands to:
>
> __private_extern__ inline __attribute__((always_inline))
>
> This prevents an externally visible definition of global operator new
> and delete from being seen.
>
> I agree this is technically wrong and I suspect it may cause problems
> on, for example, Linux platforms. I think the Qt port has turned off
> FastMalloc for this reason.
>
> I can think of two possible solutions:
>
> 1) Instead of overloading the global operator new and delete, have a
> FastAllocated base class that overloads the class operator new and
> delete, and make every class in WebCore and JavaScriptCore inherit
> from it; for non-class types, avoid using new, delete, new[] or
> delete[] (perhaps template functions could be provided). The downside
> is that I can't think of an easy way to then flag mistaken use of
> new/delete on primitive types, or forgetting to inherit from the
> FastAllocated base class. Then again, we don't try to flag mistaken
> use of malloc() instead of fastMalloc() and that has been ok.
>
> 2) Require allocation to happen in some way other than "new" and
> "delete", for instance always with template functions. Then perhaps we
> could use #defines to make any actual use of "new" and "delete" an error.
>
> Either of these would be a large change to the source, especially #2
> (#1 only needs to affect classes with no other subclass and the few
> places we use new[] on non-class types to make arrays).
>
> Perhaps someone else has a more clever idea.
>
> Regards,
> Maciej
>
>>
>
More information about the webkit-dev
mailing list