From 0bce73b69f2cfa458eeefca6c9afe5ef522acdb2 Mon Sep 17 00:00:00 2001 From: "buster%netscape.com" Date: Mon, 12 Feb 2001 06:54:31 +0000 Subject: [PATCH] bug 64696 (DOM UI events should be allocated from a recycler) r=attinasi sr=waterson git-svn-id: svn://10.0.0.236/trunk@86808 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/content/events/src/nsDOMEvent.cpp | 86 +++++++++++++++++++++-- mozilla/content/events/src/nsDOMEvent.h | 24 +++++++ mozilla/layout/events/src/nsDOMEvent.cpp | 86 +++++++++++++++++++++-- mozilla/layout/events/src/nsDOMEvent.h | 24 +++++++ 4 files changed, 208 insertions(+), 12 deletions(-) diff --git a/mozilla/content/events/src/nsDOMEvent.cpp b/mozilla/content/events/src/nsDOMEvent.cpp index 63e6d4fc94f..a710501c592 100644 --- a/mozilla/content/events/src/nsDOMEvent.cpp +++ b/mozilla/content/events/src/nsDOMEvent.cpp @@ -18,6 +18,7 @@ * Rights Reserved. * * Contributor(s): + * Steve Clark (buster@netscape.com) */ #include "nsCOMPtr.h" @@ -56,7 +57,75 @@ static char* mEventNames[] = { "DOMAttrModified", "DOMCharacterDataModified" }; -nsDOMEvent::nsDOMEvent(nsIPresContext* aPresContext, nsEvent* aEvent, const nsAReadableString& aEventType) { +/* declare static class data */ +nsDOMEvent nsDOMEvent::gEventPool; +PRBool nsDOMEvent::gEventPoolInUse=PR_FALSE; + +#ifdef NS_DEBUG // metrics for measuring event pool use +static PRInt32 numEvents=0; +static PRInt32 numNewEvents=0; +static PRInt32 numDelEvents=0; +static PRInt32 numAllocFromPool=0; +//#define NOISY_EVENT_LEAKS // define NOISY_EVENT_LEAKS to get metrics printed to stdout for all nsDOMEvent allocations +#endif + +// allocate the memory for the object from the recycler, if possible +// otherwise, just grab it from the heap. +void* +nsDOMEvent::operator new(size_t aSize) +{ + +#ifdef NS_DEBUG + numEvents++; +#endif + + void *result = nsnull; + + if (!gEventPoolInUse) { +#ifdef NS_DEBUG + numAllocFromPool++; +#endif + result = &gEventPool; + gEventPoolInUse = PR_TRUE; + } + else { +#ifdef NS_DEBUG + numNewEvents++; +#endif + result = ::operator new(aSize); + } + + if (result) { + nsCRT::zero(result, aSize); + } + + return result; +} + +// Overridden to prevent the global delete from being called on objects from +// the recycler. Otherwise, just pass through to the global delete operator. +void +nsDOMEvent::operator delete(void* aPtr) +{ + if (aPtr==&gEventPool) { + gEventPoolInUse = PR_FALSE; + } + else { +#ifdef NS_DEBUG + numDelEvents++; +#endif + ::operator delete(aPtr); + } +#if defined(NS_DEBUG) && defined(NOISY_EVENT_LEAKS) + printf("total events =%d, from pool = %d, concurrent live events = %d\n", + numEvents, numAllocFromPool, numNewEvents-numDelEvents); +#endif +} + + + +nsDOMEvent::nsDOMEvent(nsIPresContext* aPresContext, nsEvent* aEvent, const nsAReadableString& aEventType) +{ mPresContext = aPresContext; if (mPresContext) NS_ADDREF(mPresContext); @@ -123,7 +192,15 @@ nsDOMEvent::nsDOMEvent(nsIPresContext* aPresContext, nsEvent* aEvent, const nsAR NS_INIT_REFCNT(); } -nsDOMEvent::~nsDOMEvent() { +nsDOMEvent::~nsDOMEvent() +{ + NS_ASSERT_OWNINGTHREAD(nsDOMEvent); + + nsCOMPtr shell; + if (mPresContext) + { // we were arena-allocated, prepare to recycle myself + mPresContext->GetShell(getter_AddRefs(shell)); + } NS_IF_RELEASE(mPresContext); NS_IF_RELEASE(mTarget); NS_IF_RELEASE(mCurrentTarget); @@ -592,10 +669,6 @@ NS_METHOD nsDOMEvent::GetCharCode(PRUint32* aCharCode) break; case NS_KEY_PRESS: *aCharCode = ((nsKeyEvent*)mEvent)->charCode; -#if defined(NS_DEBUG) && defined(DEBUG_buster) - if (0==*aCharCode) - printf("GetCharCode used correctly but no valid key!\n"); -#endif break; default: break; @@ -1213,6 +1286,7 @@ nsresult NS_NewDOMUIEvent(nsIDOMEvent** aInstancePtrResult, nsEvent *aEvent) { nsDOMEvent* it = new nsDOMEvent(aPresContext, aEvent, aEventType); + if (nsnull == it) { return NS_ERROR_OUT_OF_MEMORY; } diff --git a/mozilla/content/events/src/nsDOMEvent.h b/mozilla/content/events/src/nsDOMEvent.h index ca118ff7371..c7091e603a5 100644 --- a/mozilla/content/events/src/nsDOMEvent.h +++ b/mozilla/content/events/src/nsDOMEvent.h @@ -172,8 +172,32 @@ public: NS_IMETHOD GetCompositionReply(nsTextEventReply** aReply); NS_IMETHOD GetReconversionReply(nsReconversionEventReply** aReply); + /** Overloaded new operator. Initializes the memory to 0. + * Relies on a recycler to perform the allocation, + * optionally from a pool. + */ + void* operator new(size_t sz); + + /** Overloaded delete operator. Relies on a recycler to either + * recycle the object or call the global delete operator, as needed. + */ + void operator delete(void* aPtr); + protected: + nsDOMEvent() {}; // private constructor for pool, not for general use + + /** event pool used as a simple recycler for objects of this class */ + static nsDOMEvent gEventPool; + + /** bit to say whether the event pool is in use or not. + * note that it would be trivial to make this a bitmap if we ever + * wanted to increase the size of the pool from one. But with our + * current usage pattern, we almost never have more than a single + * nsDOMEvent active in memory at a time under normal circumstances. + */ + static PRBool gEventPoolInUse; + //Internal helper funcs nsresult GetScrollInfo(nsIScrollableView** aScrollableView, float* aP2T, float* aT2P); nsresult SetEventType(const nsAReadableString& aEventTypeArg); diff --git a/mozilla/layout/events/src/nsDOMEvent.cpp b/mozilla/layout/events/src/nsDOMEvent.cpp index 63e6d4fc94f..a710501c592 100644 --- a/mozilla/layout/events/src/nsDOMEvent.cpp +++ b/mozilla/layout/events/src/nsDOMEvent.cpp @@ -18,6 +18,7 @@ * Rights Reserved. * * Contributor(s): + * Steve Clark (buster@netscape.com) */ #include "nsCOMPtr.h" @@ -56,7 +57,75 @@ static char* mEventNames[] = { "DOMAttrModified", "DOMCharacterDataModified" }; -nsDOMEvent::nsDOMEvent(nsIPresContext* aPresContext, nsEvent* aEvent, const nsAReadableString& aEventType) { +/* declare static class data */ +nsDOMEvent nsDOMEvent::gEventPool; +PRBool nsDOMEvent::gEventPoolInUse=PR_FALSE; + +#ifdef NS_DEBUG // metrics for measuring event pool use +static PRInt32 numEvents=0; +static PRInt32 numNewEvents=0; +static PRInt32 numDelEvents=0; +static PRInt32 numAllocFromPool=0; +//#define NOISY_EVENT_LEAKS // define NOISY_EVENT_LEAKS to get metrics printed to stdout for all nsDOMEvent allocations +#endif + +// allocate the memory for the object from the recycler, if possible +// otherwise, just grab it from the heap. +void* +nsDOMEvent::operator new(size_t aSize) +{ + +#ifdef NS_DEBUG + numEvents++; +#endif + + void *result = nsnull; + + if (!gEventPoolInUse) { +#ifdef NS_DEBUG + numAllocFromPool++; +#endif + result = &gEventPool; + gEventPoolInUse = PR_TRUE; + } + else { +#ifdef NS_DEBUG + numNewEvents++; +#endif + result = ::operator new(aSize); + } + + if (result) { + nsCRT::zero(result, aSize); + } + + return result; +} + +// Overridden to prevent the global delete from being called on objects from +// the recycler. Otherwise, just pass through to the global delete operator. +void +nsDOMEvent::operator delete(void* aPtr) +{ + if (aPtr==&gEventPool) { + gEventPoolInUse = PR_FALSE; + } + else { +#ifdef NS_DEBUG + numDelEvents++; +#endif + ::operator delete(aPtr); + } +#if defined(NS_DEBUG) && defined(NOISY_EVENT_LEAKS) + printf("total events =%d, from pool = %d, concurrent live events = %d\n", + numEvents, numAllocFromPool, numNewEvents-numDelEvents); +#endif +} + + + +nsDOMEvent::nsDOMEvent(nsIPresContext* aPresContext, nsEvent* aEvent, const nsAReadableString& aEventType) +{ mPresContext = aPresContext; if (mPresContext) NS_ADDREF(mPresContext); @@ -123,7 +192,15 @@ nsDOMEvent::nsDOMEvent(nsIPresContext* aPresContext, nsEvent* aEvent, const nsAR NS_INIT_REFCNT(); } -nsDOMEvent::~nsDOMEvent() { +nsDOMEvent::~nsDOMEvent() +{ + NS_ASSERT_OWNINGTHREAD(nsDOMEvent); + + nsCOMPtr shell; + if (mPresContext) + { // we were arena-allocated, prepare to recycle myself + mPresContext->GetShell(getter_AddRefs(shell)); + } NS_IF_RELEASE(mPresContext); NS_IF_RELEASE(mTarget); NS_IF_RELEASE(mCurrentTarget); @@ -592,10 +669,6 @@ NS_METHOD nsDOMEvent::GetCharCode(PRUint32* aCharCode) break; case NS_KEY_PRESS: *aCharCode = ((nsKeyEvent*)mEvent)->charCode; -#if defined(NS_DEBUG) && defined(DEBUG_buster) - if (0==*aCharCode) - printf("GetCharCode used correctly but no valid key!\n"); -#endif break; default: break; @@ -1213,6 +1286,7 @@ nsresult NS_NewDOMUIEvent(nsIDOMEvent** aInstancePtrResult, nsEvent *aEvent) { nsDOMEvent* it = new nsDOMEvent(aPresContext, aEvent, aEventType); + if (nsnull == it) { return NS_ERROR_OUT_OF_MEMORY; } diff --git a/mozilla/layout/events/src/nsDOMEvent.h b/mozilla/layout/events/src/nsDOMEvent.h index ca118ff7371..c7091e603a5 100644 --- a/mozilla/layout/events/src/nsDOMEvent.h +++ b/mozilla/layout/events/src/nsDOMEvent.h @@ -172,8 +172,32 @@ public: NS_IMETHOD GetCompositionReply(nsTextEventReply** aReply); NS_IMETHOD GetReconversionReply(nsReconversionEventReply** aReply); + /** Overloaded new operator. Initializes the memory to 0. + * Relies on a recycler to perform the allocation, + * optionally from a pool. + */ + void* operator new(size_t sz); + + /** Overloaded delete operator. Relies on a recycler to either + * recycle the object or call the global delete operator, as needed. + */ + void operator delete(void* aPtr); + protected: + nsDOMEvent() {}; // private constructor for pool, not for general use + + /** event pool used as a simple recycler for objects of this class */ + static nsDOMEvent gEventPool; + + /** bit to say whether the event pool is in use or not. + * note that it would be trivial to make this a bitmap if we ever + * wanted to increase the size of the pool from one. But with our + * current usage pattern, we almost never have more than a single + * nsDOMEvent active in memory at a time under normal circumstances. + */ + static PRBool gEventPoolInUse; + //Internal helper funcs nsresult GetScrollInfo(nsIScrollableView** aScrollableView, float* aP2T, float* aT2P); nsresult SetEventType(const nsAReadableString& aEventTypeArg);