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 > >> > _______________________________________________ webkit-dev mailing list webkit-dev@lists.webkit.org http://lists.webkit.org/mailman/listinfo.cgi/webkit-dev