зеркало из https://github.com/mozilla/pjs.git
Bug 497495 (frame poisoning) part 1: Move the frame arena code to its own file and rename the class to nsPresArena. r=roc
This commit is contained in:
Родитель
086bdac791
Коммит
46f7d5e4cd
|
@ -133,6 +133,7 @@ CPPSRCS = \
|
|||
nsLayoutDebugger.cpp \
|
||||
nsLayoutHistoryState.cpp \
|
||||
nsLayoutUtils.cpp \
|
||||
nsPresArena.cpp \
|
||||
nsPresContext.cpp \
|
||||
nsPresShell.cpp \
|
||||
nsPresState.cpp \
|
||||
|
|
|
@ -0,0 +1,197 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: set ts=2 sw=2 et tw=78:
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Steve Clark <buster@netscape.com>
|
||||
* Håkan Waara <hwaara@chello.se>
|
||||
* Dan Rosen <dr@netscape.com>
|
||||
* Daniel Glazman <glazman@netscape.com>
|
||||
* Mats Palmgren <mats.palmgren@bredband.net>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/* arena allocation for the frame tree and closely-related objects */
|
||||
|
||||
#include "nsPresArena.h"
|
||||
#include "nsCRT.h"
|
||||
#include "nsDebug.h"
|
||||
#include "prmem.h"
|
||||
|
||||
// Uncomment this to disable arenas, instead forwarding to
|
||||
// malloc for every allocation.
|
||||
//#define DEBUG_TRACEMALLOC_PRESARENA 1
|
||||
|
||||
#ifndef DEBUG_TRACEMALLOC_PRESARENA
|
||||
|
||||
// Even on 32-bit systems, we allocate objects from the frame arena
|
||||
// that require 8-byte alignment. The cast to PRUword is needed
|
||||
// because plarena isn't as careful about mask construction as it
|
||||
// ought to be.
|
||||
#define ALIGN_SHIFT 3
|
||||
#define PL_ARENA_CONST_ALIGN_MASK ((PRUword(1) << ALIGN_SHIFT) - 1)
|
||||
#include "plarena.h"
|
||||
|
||||
// Largest chunk size we recycle
|
||||
static const size_t MAX_RECYCLED_SIZE = 400;
|
||||
|
||||
// Recycler array entry N (0 <= N < NUM_RECYCLERS) holds chunks of
|
||||
// size (N+1) << ALIGN_SHIFT, thus we need this many array entries.
|
||||
static const size_t NUM_RECYCLERS = MAX_RECYCLED_SIZE >> ALIGN_SHIFT;
|
||||
|
||||
// Size to use for PLArena block allocations.
|
||||
static const size_t ARENA_PAGE_SIZE = 4096;
|
||||
|
||||
struct nsPresArena::State {
|
||||
void* mRecyclers[NUM_RECYCLERS];
|
||||
PLArenaPool mPool;
|
||||
|
||||
State()
|
||||
{
|
||||
PL_INIT_ARENA_POOL(&mPool, "PresArena", ARENA_PAGE_SIZE);
|
||||
memset(mRecyclers, 0, sizeof(mRecyclers));
|
||||
}
|
||||
|
||||
~State()
|
||||
{
|
||||
PL_FinishArenaPool(&mPool);
|
||||
}
|
||||
|
||||
void* Allocate(size_t aSize)
|
||||
{
|
||||
void* result = nsnull;
|
||||
|
||||
// Recycler lists are indexed by aligned size
|
||||
aSize = PL_ARENA_ALIGN(&mPool, aSize);
|
||||
|
||||
// Check recyclers first
|
||||
if (aSize <= MAX_RECYCLED_SIZE) {
|
||||
const size_t index = (aSize >> ALIGN_SHIFT) - 1;
|
||||
result = mRecyclers[index];
|
||||
if (result) {
|
||||
// Need to move to the next object
|
||||
void* next = *((void**)result);
|
||||
mRecyclers[index] = next;
|
||||
}
|
||||
}
|
||||
|
||||
if (!result) {
|
||||
// Allocate a new chunk from the arena
|
||||
PL_ARENA_ALLOCATE(result, &mPool, aSize);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void Free(size_t aSize, void* aPtr)
|
||||
{
|
||||
// Recycler lists are indexed by aligned size
|
||||
aSize = PL_ARENA_ALIGN(&mPool, aSize);
|
||||
|
||||
// See if it's a size that we recycle
|
||||
if (aSize <= MAX_RECYCLED_SIZE) {
|
||||
const size_t index = (aSize >> ALIGN_SHIFT) - 1;
|
||||
void* currentTop = mRecyclers[index];
|
||||
mRecyclers[index] = aPtr;
|
||||
*((void**)aPtr) = currentTop;
|
||||
}
|
||||
#if defined DEBUG_dbaron || defined DEBUG_zack
|
||||
else {
|
||||
fprintf(stderr,
|
||||
"WARNING: nsPresArena::FreeFrame leaking chunk of %lu bytes.\n",
|
||||
aSize);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
#else
|
||||
// Stub implementation that just forwards everything to malloc.
|
||||
|
||||
struct nsPresArena::State
|
||||
{
|
||||
void* Allocate(size_t aSize)
|
||||
{
|
||||
return PR_Malloc(aSize);
|
||||
}
|
||||
|
||||
void Free(size_t /*unused*/, void* aPtr)
|
||||
{
|
||||
PR_Free(aPtr);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // DEBUG_TRACEMALLOC_PRESARENA
|
||||
|
||||
// Public interface
|
||||
nsPresArena::nsPresArena()
|
||||
: mState(new nsPresArena::State())
|
||||
#ifdef DEBUG
|
||||
, mAllocCount(0)
|
||||
#endif
|
||||
{}
|
||||
|
||||
nsPresArena::~nsPresArena()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
NS_ASSERTION(mAllocCount == 0,
|
||||
"Some PresArena objects were not freed");
|
||||
#endif
|
||||
delete mState;
|
||||
}
|
||||
|
||||
void*
|
||||
nsPresArena::Allocate(size_t aSize)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(aSize > 0, "PresArena cannot allocate zero bytes");
|
||||
void* result = mState->Allocate(aSize);
|
||||
#ifdef DEBUG
|
||||
if (result)
|
||||
mAllocCount++;
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
nsPresArena::Free(size_t aSize, void* aPtr)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(aSize > 0, "PresArena cannot free zero bytes");
|
||||
#ifdef DEBUG
|
||||
// Mark the memory with 0xdd in DEBUG builds so that there will be
|
||||
// problems if someone tries to access memory that they've freed.
|
||||
memset(aPtr, 0xdd, aSize);
|
||||
mAllocCount--;
|
||||
#endif
|
||||
mState->Free(aSize, aPtr);
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: set ts=2 sw=2 et tw=78:
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Steve Clark <buster@netscape.com>
|
||||
* Håkan Waara <hwaara@chello.se>
|
||||
* Dan Rosen <dr@netscape.com>
|
||||
* Daniel Glazman <glazman@netscape.com>
|
||||
* Mats Palmgren <mats.palmgren@bredband.net>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#ifndef nsPresArena_h___
|
||||
#define nsPresArena_h___
|
||||
|
||||
#include "nscore.h"
|
||||
|
||||
class nsPresArena {
|
||||
public:
|
||||
nsPresArena();
|
||||
~nsPresArena();
|
||||
|
||||
// Memory management functions
|
||||
NS_HIDDEN_(void*) Allocate(size_t aSize);
|
||||
NS_HIDDEN_(void) Free(size_t aSize, void* aPtr);
|
||||
|
||||
private:
|
||||
struct State;
|
||||
State* mState;
|
||||
#ifdef DEBUG
|
||||
PRUint32 mAllocCount;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
|
@ -51,12 +51,10 @@
|
|||
*
|
||||
* Date Modified by Description of modification
|
||||
* 05/03/2000 IBM Corp. Observer events for reflow states
|
||||
*/
|
||||
*/
|
||||
|
||||
/* a presentation of a document, part 2 */
|
||||
|
||||
#define PL_ARENA_CONST_ALIGN_MASK 3
|
||||
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsPresContext.h"
|
||||
#include "nsIContent.h"
|
||||
|
@ -117,6 +115,7 @@
|
|||
#include "nsIDOMNSHTMLInputElement.h" //optimization for ::DoXXX commands
|
||||
#include "nsIDOMNSHTMLTextAreaElement.h"
|
||||
#include "nsViewsCID.h"
|
||||
#include "nsPresArena.h"
|
||||
#include "nsFrameManager.h"
|
||||
#include "nsXPCOM.h"
|
||||
#include "nsISupportsPrimitives.h"
|
||||
|
@ -124,7 +123,6 @@
|
|||
#include "nsILineIterator.h" // for ScrollContentIntoView
|
||||
#include "nsTimer.h"
|
||||
#include "nsWeakPtr.h"
|
||||
#include "plarena.h"
|
||||
#include "pldhash.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsIObserver.h"
|
||||
|
@ -434,9 +432,6 @@ protected:
|
|||
#define NS_MAX_REFLOW_TIME 1000000
|
||||
static PRInt32 gMaxRCProcessingTime = -1;
|
||||
|
||||
// Largest chunk size we recycle
|
||||
static const size_t gMaxRecycledSize = 400;
|
||||
|
||||
#define MARK_INCREMENT 50
|
||||
#define BLOCK_INCREMENT 4044 /* a bit under 4096, for malloc overhead */
|
||||
|
||||
|
@ -633,135 +628,6 @@ StackArena::Pop()
|
|||
mPos = mMarks[mStackTop].mPos;
|
||||
}
|
||||
|
||||
// Uncomment this to disable the frame arena.
|
||||
//#define DEBUG_TRACEMALLOC_FRAMEARENA 1
|
||||
|
||||
// Memory is allocated 4-byte aligned. We have recyclers for chunks up to
|
||||
// 200 bytes
|
||||
class FrameArena {
|
||||
public:
|
||||
FrameArena(PRUint32 aArenaSize = 4096);
|
||||
~FrameArena();
|
||||
|
||||
// Memory management functions
|
||||
NS_HIDDEN_(void*) AllocateFrame(size_t aSize);
|
||||
NS_HIDDEN_(void) FreeFrame(size_t aSize, void* aPtr);
|
||||
|
||||
private:
|
||||
#ifdef DEBUG
|
||||
// Number of frames in the pool
|
||||
PRUint32 mFrameCount;
|
||||
#endif
|
||||
|
||||
#if !defined(DEBUG_TRACEMALLOC_FRAMEARENA)
|
||||
// Underlying arena pool
|
||||
PLArenaPool mPool;
|
||||
|
||||
// The recycler array is sparse with the indices being multiples of 4,
|
||||
// i.e., 0, 4, 8, 12, 16, 20, ...
|
||||
void* mRecyclers[gMaxRecycledSize >> 2];
|
||||
#endif
|
||||
};
|
||||
|
||||
FrameArena::FrameArena(PRUint32 aArenaSize)
|
||||
#ifdef DEBUG
|
||||
: mFrameCount(0)
|
||||
#endif
|
||||
{
|
||||
#if !defined(DEBUG_TRACEMALLOC_FRAMEARENA)
|
||||
// Initialize the arena pool
|
||||
PL_INIT_ARENA_POOL(&mPool, "FrameArena", aArenaSize);
|
||||
|
||||
// Zero out the recyclers array
|
||||
memset(mRecyclers, 0, sizeof(mRecyclers));
|
||||
#endif
|
||||
}
|
||||
|
||||
FrameArena::~FrameArena()
|
||||
{
|
||||
NS_ASSERTION(mFrameCount == 0,
|
||||
"Some objects allocated with AllocateFrame were not freed");
|
||||
|
||||
#if !defined(DEBUG_TRACEMALLOC_FRAMEARENA)
|
||||
// Free the arena in the pool and finish using it
|
||||
PL_FinishArenaPool(&mPool);
|
||||
#endif
|
||||
}
|
||||
|
||||
void*
|
||||
FrameArena::AllocateFrame(size_t aSize)
|
||||
{
|
||||
void* result = nsnull;
|
||||
|
||||
#if defined(DEBUG_TRACEMALLOC_FRAMEARENA)
|
||||
|
||||
result = PR_Malloc(aSize);
|
||||
|
||||
#else
|
||||
|
||||
// Ensure we have correct alignment for pointers. Important for Tru64
|
||||
aSize = PR_ROUNDUP(aSize, sizeof(void*));
|
||||
|
||||
// Check recyclers first
|
||||
if (aSize < gMaxRecycledSize) {
|
||||
const int index = aSize >> 2;
|
||||
|
||||
result = mRecyclers[index];
|
||||
if (result) {
|
||||
// Need to move to the next object
|
||||
void* next = *((void**)result);
|
||||
mRecyclers[index] = next;
|
||||
}
|
||||
}
|
||||
|
||||
if (!result) {
|
||||
// Allocate a new chunk from the arena
|
||||
PL_ARENA_ALLOCATE(result, &mPool, aSize);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
if (result != nsnull)
|
||||
++mFrameCount;
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
FrameArena::FreeFrame(size_t aSize, void* aPtr)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
--mFrameCount;
|
||||
|
||||
// Mark the memory with 0xdd in DEBUG builds so that there will be
|
||||
// problems if someone tries to access memory that they've freed.
|
||||
memset(aPtr, 0xdd, aSize);
|
||||
#endif
|
||||
#if defined(DEBUG_TRACEMALLOC_FRAMEARENA)
|
||||
PR_Free(aPtr);
|
||||
#else
|
||||
// Ensure we have correct alignment for pointers. Important for Tru64
|
||||
aSize = PR_ROUNDUP(aSize, sizeof(void*));
|
||||
|
||||
// See if it's a size that we recycle
|
||||
if (aSize < gMaxRecycledSize) {
|
||||
const int index = aSize >> 2;
|
||||
void* currentTop = mRecyclers[index];
|
||||
mRecyclers[index] = aPtr;
|
||||
*((void**)aPtr) = currentTop;
|
||||
}
|
||||
#ifdef DEBUG_dbaron
|
||||
else {
|
||||
fprintf(stderr,
|
||||
"WARNING: FrameArena::FreeFrame leaking chunk of %d bytes.\n",
|
||||
aSize);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
struct nsCallbackEventRequest
|
||||
{
|
||||
nsIReflowCallback* callback;
|
||||
|
@ -1184,7 +1050,7 @@ protected:
|
|||
nsRefPtr<nsCaret> mCaret;
|
||||
nsRefPtr<nsCaret> mOriginalCaret;
|
||||
PRInt16 mSelectionFlags;
|
||||
FrameArena mFrameArena;
|
||||
nsPresArena mFrameArena;
|
||||
StackArena mStackArena;
|
||||
nsCOMPtr<nsIDragService> mDragService;
|
||||
|
||||
|
@ -2103,13 +1969,13 @@ PresShell::AllocateStackMemory(size_t aSize)
|
|||
void
|
||||
PresShell::FreeFrame(size_t aSize, void* aPtr)
|
||||
{
|
||||
mFrameArena.FreeFrame(aSize, aPtr);
|
||||
mFrameArena.Free(aSize, aPtr);
|
||||
}
|
||||
|
||||
void*
|
||||
PresShell::AllocateFrame(size_t aSize)
|
||||
{
|
||||
return mFrameArena.AllocateFrame(aSize);
|
||||
return mFrameArena.Allocate(aSize);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
Загрузка…
Ссылка в новой задаче