Bug 497495 (frame poisoning) part 2: Introduce nsIPresShell::AllocateMisc/FreeMisc functions; add an as-yet-unused "code" parameter to AllocateFrame/FreeFrame; fix up nsFrame to match; use AllocateMisc/FreeMisc for all non-frame pres arena objects; move clearing of frame objects from nsFrame::operator new to AllocateFrame. r=roc sr=dbaron
This commit is contained in:
@@ -104,9 +104,10 @@ class nsDisplayListBuilder;
|
||||
typedef short SelectionType;
|
||||
typedef PRUint32 nsFrameState;
|
||||
|
||||
#define NS_IPRESSHELL_IID \
|
||||
{ 0xfea81c36, 0xed5b, 0x41f5, \
|
||||
{ 0x89, 0x5d, 0x4c, 0x50, 0x79, 0x49, 0xad, 0x3b } }
|
||||
// eba51d41-68db-4dab-a57b-dc1a2704de87
|
||||
#define NS_IPRESSHELL_IID \
|
||||
{ 0xeba51d41, 0x68db, 0x4dab, \
|
||||
{ 0xa5, 0x7b, 0xdc, 0x1a, 0x27, 0x04, 0xde, 0x87 } }
|
||||
|
||||
// Constants for ScrollContentIntoView() function
|
||||
#define NS_PRESSHELL_SCROLL_TOP 0
|
||||
@@ -169,11 +170,19 @@ public:
|
||||
|
||||
PRBool IsDestroying() { return mIsDestroying; }
|
||||
|
||||
// All frames owned by the shell are allocated from an arena. They are also recycled
|
||||
// using free lists (separate free lists being maintained for each size_t).
|
||||
// Methods for recycling frames.
|
||||
virtual void* AllocateFrame(size_t aSize) = 0;
|
||||
virtual void FreeFrame(size_t aSize, void* aFreeChunk) = 0;
|
||||
// All frames owned by the shell are allocated from an arena. They
|
||||
// are also recycled using free lists. Separate free lists are
|
||||
// maintained for each combination of aSize and aCode. AllocateFrame
|
||||
// clears the memory that it returns.
|
||||
virtual void* AllocateFrame(size_t aSize, unsigned int aCode) = 0;
|
||||
virtual void FreeFrame(size_t aSize, unsigned int aCode, void* aChunk) = 0;
|
||||
|
||||
// Objects closely related to the frame tree, but that are not
|
||||
// actual frames (subclasses of nsFrame) are also allocated from the
|
||||
// arena, and recycled via a separate set of per-size free lists.
|
||||
// AllocateMisc does *not* clear the memory that it returns.
|
||||
virtual void* AllocateMisc(size_t aSize) = 0;
|
||||
virtual void FreeMisc(size_t aSize, void* aChunk) = 0;
|
||||
|
||||
/**
|
||||
* Stack memory allocation:
|
||||
|
||||
@@ -280,7 +280,7 @@ public:
|
||||
void* AllocateFromShell(size_t aSize)
|
||||
{
|
||||
if (mShell)
|
||||
return mShell->AllocateFrame(aSize);
|
||||
return mShell->AllocateMisc(aSize);
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
@@ -288,7 +288,7 @@ public:
|
||||
{
|
||||
NS_ASSERTION(mShell, "freeing after shutdown");
|
||||
if (mShell)
|
||||
mShell->FreeFrame(aSize, aFreeChunk);
|
||||
mShell->FreeMisc(aSize, aFreeChunk);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -659,8 +659,12 @@ public:
|
||||
nsCompatibility aCompatMode);
|
||||
NS_IMETHOD Destroy();
|
||||
|
||||
virtual NS_HIDDEN_(void*) AllocateFrame(size_t aSize);
|
||||
virtual NS_HIDDEN_(void) FreeFrame(size_t aSize, void* aFreeChunk);
|
||||
virtual NS_HIDDEN_(void*) AllocateFrame(size_t aSize, unsigned int aCode);
|
||||
virtual NS_HIDDEN_(void) FreeFrame(size_t aSize, unsigned int aCode,
|
||||
void* aChunk);
|
||||
|
||||
virtual NS_HIDDEN_(void*) AllocateMisc(size_t aSize);
|
||||
virtual NS_HIDDEN_(void) FreeMisc(size_t aSize, void* aChunk);
|
||||
|
||||
// Dynamic stack memory allocation
|
||||
virtual NS_HIDDEN_(void) PushStackMemory();
|
||||
@@ -1967,13 +1971,30 @@ PresShell::AllocateStackMemory(size_t aSize)
|
||||
}
|
||||
|
||||
void
|
||||
PresShell::FreeFrame(size_t aSize, void* aPtr)
|
||||
PresShell::FreeFrame(size_t aSize, unsigned int /*unused*/, void* aPtr)
|
||||
{
|
||||
mFrameArena.Free(aSize, aPtr);
|
||||
}
|
||||
|
||||
void*
|
||||
PresShell::AllocateFrame(size_t aSize)
|
||||
PresShell::AllocateFrame(size_t aSize, unsigned int /*unused*/)
|
||||
{
|
||||
void* result = mFrameArena.Allocate(aSize);
|
||||
|
||||
if (result) {
|
||||
memset(result, 0, aSize);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
PresShell::FreeMisc(size_t aSize, void* aPtr)
|
||||
{
|
||||
mFrameArena.Free(aSize, aPtr);
|
||||
}
|
||||
|
||||
void*
|
||||
PresShell::AllocateMisc(size_t aSize)
|
||||
{
|
||||
return mFrameArena.Allocate(aSize);
|
||||
}
|
||||
@@ -4581,7 +4602,7 @@ PresShell::IsThemeSupportEnabled()
|
||||
NS_IMETHODIMP
|
||||
PresShell::PostReflowCallback(nsIReflowCallback* aCallback)
|
||||
{
|
||||
void* result = AllocateFrame(sizeof(nsCallbackEventRequest));
|
||||
void* result = AllocateMisc(sizeof(nsCallbackEventRequest));
|
||||
if (NS_UNLIKELY(!result)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
@@ -4625,7 +4646,7 @@ PresShell::CancelReflowCallback(nsIReflowCallback* aCallback)
|
||||
mLastCallbackEventRequest = before;
|
||||
}
|
||||
|
||||
FreeFrame(sizeof(nsCallbackEventRequest), toFree);
|
||||
FreeMisc(sizeof(nsCallbackEventRequest), toFree);
|
||||
} else {
|
||||
before = node;
|
||||
node = node->next;
|
||||
@@ -4645,7 +4666,7 @@ PresShell::CancelPostedReflowCallbacks()
|
||||
mLastCallbackEventRequest = nsnull;
|
||||
}
|
||||
nsIReflowCallback* callback = node->callback;
|
||||
FreeFrame(sizeof(nsCallbackEventRequest), node);
|
||||
FreeMisc(sizeof(nsCallbackEventRequest), node);
|
||||
if (callback) {
|
||||
callback->ReflowCallbackCanceled();
|
||||
}
|
||||
@@ -4664,7 +4685,7 @@ PresShell::HandlePostedReflowCallbacks(PRBool aInterruptible)
|
||||
mLastCallbackEventRequest = nsnull;
|
||||
}
|
||||
nsIReflowCallback* callback = node->callback;
|
||||
FreeFrame(sizeof(nsCallbackEventRequest), node);
|
||||
FreeMisc(sizeof(nsCallbackEventRequest), node);
|
||||
if (callback) {
|
||||
if (callback->ReflowFinished()) {
|
||||
shouldFlush = PR_TRUE;
|
||||
|
||||
@@ -55,14 +55,14 @@ void* nsFloatManager::sCachedFloatManagers[NS_FLOAT_MANAGER_CACHE_SIZE];
|
||||
static void*
|
||||
PSArenaAllocCB(size_t aSize, void* aClosure)
|
||||
{
|
||||
return static_cast<nsIPresShell*>(aClosure)->AllocateFrame(aSize);
|
||||
return static_cast<nsIPresShell*>(aClosure)->AllocateMisc(aSize);
|
||||
}
|
||||
|
||||
// PresShell Arena free callback (for nsIntervalSet use below)
|
||||
static void
|
||||
PSArenaFreeCB(size_t aSize, void* aPtr, void* aClosure)
|
||||
{
|
||||
static_cast<nsIPresShell*>(aClosure)->FreeFrame(aSize, aPtr);
|
||||
static_cast<nsIPresShell*>(aClosure)->FreeMisc(aSize, aPtr);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -290,24 +290,17 @@ NS_NewEmptyFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
|
||||
return new (aPresShell) nsFrame(aContext);
|
||||
}
|
||||
|
||||
// Overloaded new operator. Initializes the memory to 0 and relies on an arena
|
||||
// (which comes from the presShell) to perform the allocation.
|
||||
void*
|
||||
// Overloaded new operator. Relies on an arena (which comes from the
|
||||
// presShell) to perform the allocation.
|
||||
void*
|
||||
nsFrame::operator new(size_t sz, nsIPresShell* aPresShell) CPP_THROW_NEW
|
||||
{
|
||||
// Check the recycle list first.
|
||||
void* result = aPresShell->AllocateFrame(sz);
|
||||
|
||||
if (result) {
|
||||
memset(result, 0, sz);
|
||||
}
|
||||
|
||||
return result;
|
||||
return aPresShell->AllocateFrame(sz, 0 /* dummy */);
|
||||
}
|
||||
|
||||
// Overridden to prevent the global delete from being called, since the memory
|
||||
// came out of an nsIArena instead of the global delete operator's heap.
|
||||
void
|
||||
void
|
||||
nsFrame::operator delete(void* aPtr, size_t sz)
|
||||
{
|
||||
// Don't let the memory be freed, since it will be recycled
|
||||
@@ -477,7 +470,7 @@ nsFrame::Destroy()
|
||||
if (view) {
|
||||
// Break association between view and frame
|
||||
view->SetClientData(nsnull);
|
||||
|
||||
|
||||
// Destroy the view
|
||||
view->Destroy();
|
||||
}
|
||||
@@ -489,7 +482,7 @@ nsFrame::Destroy()
|
||||
// Now that we're totally cleaned out, we need to add ourselves to the presshell's
|
||||
// recycler.
|
||||
size_t* sz = (size_t*)this;
|
||||
shell->FreeFrame(*sz, (void*)this);
|
||||
shell->FreeFrame(*sz, 0 /* dummy */, (void*)this);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
||||
@@ -134,25 +134,29 @@ public:
|
||||
* Create a new "empty" frame that maps a given piece of content into a
|
||||
* 0,0 area.
|
||||
*/
|
||||
friend nsIFrame* NS_NewEmptyFrame(nsIPresShell* aShell, nsStyleContext* aContext);
|
||||
friend nsIFrame* NS_NewEmptyFrame(nsIPresShell* aShell,
|
||||
nsStyleContext* aContext);
|
||||
|
||||
// Overloaded new operator. Initializes the memory to 0 and relies on an arena
|
||||
// (which comes from the presShell) to perform the allocation.
|
||||
// Overloaded new operator. Relies on an arena (which comes from the
|
||||
// presShell) to perform the allocation.
|
||||
void* operator new(size_t sz, nsIPresShell* aPresShell) CPP_THROW_NEW;
|
||||
|
||||
// Overridden to prevent the global delete from being called, since the memory
|
||||
// came out of an arena instead of the global delete operator's heap.
|
||||
// XXX Would like to make this private some day, but our UNIX compilers can't
|
||||
// deal with it.
|
||||
void operator delete(void* aPtr, size_t sz);
|
||||
|
||||
// We compute and store the HTML content's overflow area. So don't
|
||||
// try to compute it in the box code.
|
||||
virtual PRBool ComputesOwnOverflowArea() { return PR_TRUE; }
|
||||
|
||||
private:
|
||||
// The normal operator new is disallowed on nsFrames.
|
||||
void* operator new(size_t sz) CPP_THROW_NEW { return nsnull; }
|
||||
// Left undefined; nsFrame objects are never allocated from the heap.
|
||||
void* operator new(size_t sz) CPP_THROW_NEW;
|
||||
|
||||
protected:
|
||||
// Overridden to prevent the global delete from being called, since
|
||||
// the memory came out of an arena instead of the heap.
|
||||
//
|
||||
// Ideally this would be private and undefined, like the normal
|
||||
// operator new. Unfortunately, the C++ standard requires an
|
||||
// overridden operator delete to be accessible to any subclass that
|
||||
// defines a virtual destructor, so we can only make it protected;
|
||||
// worse, some C++ compilers will synthesize calls to this function
|
||||
// from the "deleting destructors" that they emit in case of
|
||||
// delete-expressions, so it can't even be undefined.
|
||||
void operator delete(void* aPtr, size_t sz);
|
||||
|
||||
public:
|
||||
|
||||
@@ -371,6 +375,10 @@ public:
|
||||
virtual nscoord GetFlex(nsBoxLayoutState& aBoxLayoutState);
|
||||
virtual nscoord GetBoxAscent(nsBoxLayoutState& aBoxLayoutState);
|
||||
|
||||
// We compute and store the HTML content's overflow area. So don't
|
||||
// try to compute it in the box code.
|
||||
virtual PRBool ComputesOwnOverflowArea() { return PR_TRUE; }
|
||||
|
||||
//--------------------------------------------------
|
||||
// Additional methods
|
||||
|
||||
|
||||
@@ -96,15 +96,15 @@ NS_NewLineBox(nsIPresShell* aPresShell, nsIFrame* aFrame,
|
||||
|
||||
// Overloaded new operator. Uses an arena (which comes from the presShell)
|
||||
// to perform the allocation.
|
||||
void*
|
||||
void*
|
||||
nsLineBox::operator new(size_t sz, nsIPresShell* aPresShell) CPP_THROW_NEW
|
||||
{
|
||||
return aPresShell->AllocateFrame(sz);
|
||||
return aPresShell->AllocateMisc(sz);
|
||||
}
|
||||
|
||||
// Overloaded delete operator. Doesn't actually free the memory, because we
|
||||
// use an arena
|
||||
void
|
||||
void
|
||||
nsLineBox::operator delete(void* aPtr, size_t sz)
|
||||
{
|
||||
}
|
||||
@@ -116,7 +116,7 @@ nsLineBox::Destroy(nsIPresShell* aPresShell)
|
||||
delete this;
|
||||
|
||||
// Have the pres shell recycle the memory
|
||||
aPresShell->FreeFrame(sizeof(*this), (void*)this);
|
||||
aPresShell->FreeMisc(sizeof(*this), (void*)this);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
Reference in New Issue
Block a user