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
This commit is contained in:
buster%netscape.com 2001-02-12 06:54:31 +00:00
parent f57f7ebd62
commit 0bce73b69f
4 changed files with 208 additions and 12 deletions

View File

@ -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<nsIPresShell> 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;
}

View File

@ -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);

View File

@ -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<nsIPresShell> 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;
}

View File

@ -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);