зеркало из https://github.com/mozilla/gecko-dev.git
b=16615. Two line change. Added check for case of root node being a leaf.
The rest of the changes are NOT yet in use. They willbe reviewed by Kipp before they're turned on
This commit is contained in:
Родитель
acf13df96b
Коммит
d1f8db9147
|
@ -243,7 +243,9 @@ private:
|
|||
FMPropertyDtorFunc mDtorFunc; // property specific value dtor function
|
||||
PropertyList* mNext;
|
||||
|
||||
PropertyList(nsIAtom* aName, FMPropertyDtorFunc aDtorFunc);
|
||||
PropertyList(nsIAtom* aName,
|
||||
FMPropertyDtorFunc aDtorFunc,
|
||||
nsDST::NodeArena* aDSTNodeArena);
|
||||
~PropertyList();
|
||||
|
||||
// Removes the property associated with the given frame, and destroys
|
||||
|
@ -251,8 +253,9 @@ private:
|
|||
void RemovePropertyForFrame(nsIFrame* aFrame);
|
||||
};
|
||||
|
||||
nsIPresShell* mPresShell; // weak link, because the pres shell owns us
|
||||
nsIStyleSet* mStyleSet; // weak link. pres shell holds a reference
|
||||
nsIPresShell* mPresShell; // weak link, because the pres shell owns us
|
||||
nsIStyleSet* mStyleSet; // weak link. pres shell holds a reference
|
||||
nsDST::NodeArena* mDSTNodeArena; // weak link. DST owns
|
||||
nsDST* mPrimaryFrameMap;
|
||||
FrameHashTable* mPlaceholderMap;
|
||||
UndisplayedMap* mUndisplayedMap;
|
||||
|
@ -333,6 +336,13 @@ FrameManager::Init(nsIPresShell* aPresShell,
|
|||
{
|
||||
mPresShell = aPresShell;
|
||||
mStyleSet = aStyleSet;
|
||||
|
||||
// Allocate the node arena that's shared by all the DST objects
|
||||
mDSTNodeArena = nsDST::NewMemoryArena();
|
||||
if (!mDSTNodeArena) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -381,7 +391,7 @@ FrameManager::SetPrimaryFrameFor(nsIContent* aContent,
|
|||
} else {
|
||||
// Create a new DST if necessary
|
||||
if (!mPrimaryFrameMap) {
|
||||
mPrimaryFrameMap = new nsDST;
|
||||
mPrimaryFrameMap = new nsDST(mDSTNodeArena);
|
||||
if (!mPrimaryFrameMap) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
@ -1569,7 +1579,7 @@ FrameManager::SetFrameProperty(nsIFrame* aFrame,
|
|||
}
|
||||
|
||||
} else {
|
||||
propertyList = new PropertyList(aPropertyName, aPropDtorFunc);
|
||||
propertyList = new PropertyList(aPropertyName, aPropDtorFunc, mDSTNodeArena);
|
||||
if (!propertyList) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
@ -1751,8 +1761,10 @@ UndisplayedMap::Clear(void)
|
|||
//----------------------------------------------------------------------
|
||||
|
||||
FrameManager::PropertyList::PropertyList(nsIAtom* aName,
|
||||
FMPropertyDtorFunc aDtorFunc)
|
||||
: mName(aName), mFrameValueMap(new nsDST), mDtorFunc(aDtorFunc), mNext(nsnull)
|
||||
FMPropertyDtorFunc aDtorFunc,
|
||||
nsDST::NodeArena* aDSTNodeArena)
|
||||
: mName(aName), mFrameValueMap(new nsDST(aDSTNodeArena)),
|
||||
mDtorFunc(aDtorFunc), mNext(nsnull)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,37 @@
|
|||
// It's an invariant of the tree that a two node can not have both child links
|
||||
// NULL. In that case it must be converted back to a leaf node
|
||||
|
||||
// Leaf node class
|
||||
// Definition of NodeArena class
|
||||
class nsDST::NodeArena {
|
||||
public:
|
||||
NodeArena(PRUint32 aArenaSize);
|
||||
~NodeArena();
|
||||
|
||||
// Memory management functions
|
||||
void* AllocLeafNode();
|
||||
void* AllocTwoNode();
|
||||
void FreeNode(LeafNode*);
|
||||
void FreeNode(TwoNode*);
|
||||
void FreeArenaPool();
|
||||
|
||||
// Lifetime management functions
|
||||
void AddRef() {mRefCnt++;}
|
||||
void Release();
|
||||
PRBool IsShared() const {return mRefCnt > 1;}
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
int NumArenas() const;
|
||||
PRUint32 ArenaSize() const {return mPool.arenasize;}
|
||||
#endif
|
||||
|
||||
private:
|
||||
PLArenaPool mPool;
|
||||
LeafNode* mLeafNodeFreeList;
|
||||
TwoNode* mTwoNodeFreeList;
|
||||
PRUint32 mRefCnt;
|
||||
};
|
||||
|
||||
// Definition of LeafNode class
|
||||
class nsDST::LeafNode {
|
||||
public:
|
||||
void* mKey;
|
||||
|
@ -57,7 +87,7 @@ public:
|
|||
int IsLeaf() const {return 0 == (PtrBits(mKey) & 0x1);}
|
||||
|
||||
// Overloaded placement operator for allocating from an arena
|
||||
void* operator new(size_t aSize, NodeArena& aArena) {return aArena.AllocLeafNode();}
|
||||
void* operator new(size_t aSize, NodeArena* aArena) {return aArena->AllocLeafNode();}
|
||||
|
||||
private:
|
||||
void operator delete(void*); // no implementation
|
||||
|
@ -75,7 +105,7 @@ inline nsDST::LeafNode::LeafNode(const LeafNode& aNode)
|
|||
{
|
||||
}
|
||||
|
||||
// Two node class
|
||||
// Definition of TwoNode class
|
||||
class nsDST::TwoNode : public nsDST::LeafNode {
|
||||
public:
|
||||
LeafNode* mLeft; // left subtree
|
||||
|
@ -89,7 +119,7 @@ public:
|
|||
}
|
||||
|
||||
// Overloaded placement operator for allocating from an arena
|
||||
void* operator new(size_t aSize, NodeArena& aArena) {return aArena.AllocTwoNode();}
|
||||
void* operator new(size_t aSize, NodeArena* aArena) {return aArena->AllocTwoNode();}
|
||||
|
||||
private:
|
||||
TwoNode(const TwoNode&); // no implementation
|
||||
|
@ -121,16 +151,20 @@ inline nsDST::TwoNode::TwoNode(const LeafNode& aLeafNode)
|
|||
// Arena used for fast allocation and deallocation of Node structures.
|
||||
// Maintains free-list of freed objects
|
||||
|
||||
#define NS_DST_ARENA_BLOCK_SIZE 512
|
||||
nsDST::NodeArena*
|
||||
nsDST::NewMemoryArena(PRUint32 aArenaSize)
|
||||
{
|
||||
return new NodeArena(aArenaSize);
|
||||
}
|
||||
|
||||
MOZ_DECL_CTOR_COUNTER(NodeArena);
|
||||
|
||||
// Constructor
|
||||
nsDST::NodeArena::NodeArena()
|
||||
: mLeafNodeFreeList(0), mTwoNodeFreeList(0)
|
||||
nsDST::NodeArena::NodeArena(PRUint32 aArenaSize)
|
||||
: mLeafNodeFreeList(0), mTwoNodeFreeList(0), mRefCnt(0)
|
||||
{
|
||||
MOZ_COUNT_CTOR(NodeArena);
|
||||
PL_INIT_ARENA_POOL(&mPool, "DSTNodeArena", NS_DST_ARENA_BLOCK_SIZE);
|
||||
PL_INIT_ARENA_POOL(&mPool, "DSTNodeArena", aArenaSize);
|
||||
}
|
||||
|
||||
// Destructor
|
||||
|
@ -142,6 +176,15 @@ nsDST::NodeArena::~NodeArena()
|
|||
PL_FinishArenaPool(&mPool);
|
||||
}
|
||||
|
||||
void
|
||||
nsDST::NodeArena::Release()
|
||||
{
|
||||
NS_PRECONDITION(mRefCnt > 0, "unexpected ref count");
|
||||
if (--mRefCnt == 0) {
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
// Called by the nsDST::LeafNode's overloaded placement operator when
|
||||
// allocating a new node. First checks the free list. If the free list is
|
||||
// empty, then it allocates memory from the arena
|
||||
|
@ -221,29 +264,78 @@ nsDST::NodeArena::FreeArenaPool()
|
|||
mTwoNodeFreeList = 0;
|
||||
}
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
int
|
||||
nsDST::NodeArena::NumArenas() const
|
||||
{
|
||||
// Calculate the number of arenas in use
|
||||
int numArenas = 0;
|
||||
for (PLArena* arena = mPool.first.next; arena; arena = arena->next) {
|
||||
numArenas++;
|
||||
}
|
||||
|
||||
return numArenas;
|
||||
}
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Digital search tree for doing a radix-search of pointer-based keys
|
||||
|
||||
MOZ_DECL_CTOR_COUNTER(nsDST);
|
||||
|
||||
// Constructor
|
||||
nsDST::nsDST(PtrBits aLevelZeroBit)
|
||||
: mRoot(0), mLevelZeroBit(aLevelZeroBit)
|
||||
nsDST::nsDST(NodeArena* aArena, PtrBits aLevelZeroBit)
|
||||
: mRoot(0), mArena(aArena), mLevelZeroBit(aLevelZeroBit)
|
||||
{
|
||||
NS_PRECONDITION(aArena, "no node arena");
|
||||
MOZ_COUNT_CTOR(nsDST);
|
||||
|
||||
// Add a reference to the node arena
|
||||
mArena->AddRef();
|
||||
}
|
||||
|
||||
// Destructor
|
||||
nsDST::~nsDST()
|
||||
{
|
||||
MOZ_COUNT_DTOR(nsDST);
|
||||
|
||||
// If the node arena is shared, then we'll need to explicitly
|
||||
// free each node in the tree
|
||||
if (mArena->IsShared()) {
|
||||
FreeTree(mRoot);
|
||||
}
|
||||
|
||||
// Release our reference to the node arena
|
||||
mArena->Release();
|
||||
}
|
||||
|
||||
void
|
||||
nsDST::FreeTree(LeafNode* aNode)
|
||||
{
|
||||
keepLooping:
|
||||
if (!aNode) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (aNode->IsLeaf()) {
|
||||
DestroyNode(aNode);
|
||||
|
||||
} else {
|
||||
LeafNode* left = ((TwoNode*)aNode)->mLeft;
|
||||
LeafNode* right = ((TwoNode*)aNode)->mRight;
|
||||
|
||||
DestroyNode((TwoNode*)aNode);
|
||||
FreeTree(left);
|
||||
aNode = right;
|
||||
goto keepLooping;
|
||||
}
|
||||
}
|
||||
|
||||
// Removes all nodes from the tree
|
||||
void
|
||||
nsDST::Clear()
|
||||
{
|
||||
mArena.FreeArenaPool();
|
||||
mArena->FreeArenaPool();
|
||||
mRoot = 0;
|
||||
}
|
||||
|
||||
|
@ -278,7 +370,7 @@ inline void
|
|||
nsDST::DestroyNode(LeafNode* aLeafNode)
|
||||
{
|
||||
aLeafNode->~LeafNode(); // call destructor
|
||||
mArena.FreeNode(aLeafNode); // free memory
|
||||
mArena->FreeNode(aLeafNode); // free memory
|
||||
}
|
||||
|
||||
// Called by Remove() to destroy a node. Explicitly calls the destructor
|
||||
|
@ -287,7 +379,7 @@ inline void
|
|||
nsDST::DestroyNode(TwoNode* aTwoNode)
|
||||
{
|
||||
aTwoNode->~TwoNode(); // call destructor
|
||||
mArena.FreeNode(aTwoNode); // free memory
|
||||
mArena->FreeNode(aTwoNode); // free memory
|
||||
}
|
||||
|
||||
nsDST::LeafNode*
|
||||
|
@ -546,7 +638,10 @@ nsDST::Remove(void* aKey)
|
|||
if (mRoot->Key() == aKey) {
|
||||
node = (LeafNode**)&mRoot;
|
||||
|
||||
} else if (!mRoot->IsLeaf()) {
|
||||
} else if (mRoot->IsLeaf()) {
|
||||
return 0; // no node with a matching key
|
||||
|
||||
} else {
|
||||
// Look for a node with a matching key
|
||||
node = (LeafNode**)&mRoot;
|
||||
while (1) {
|
||||
|
@ -736,12 +831,6 @@ nsDST::Dump(FILE* out) const
|
|||
pathLength += height * count;
|
||||
}
|
||||
|
||||
// Calculate the number of arenas in use
|
||||
int numArenas = 0;
|
||||
for (PLArena* arena = mArena.mPool.first.next; arena; arena = arena->next) {
|
||||
numArenas++;
|
||||
}
|
||||
|
||||
// Output the statistics
|
||||
int numTotalNodes = numLeafNodes + numTwoNodes;
|
||||
|
||||
|
@ -753,7 +842,7 @@ nsDST::Dump(FILE* out) const
|
|||
float(numLeafNodes * sizeof(LeafNode) + numTwoNodes * sizeof(TwoNode)) /
|
||||
float(numTotalNodes));
|
||||
}
|
||||
fprintf(out, " Number of arenas: %d(%d)\n", numArenas, mArena.mPool.arenasize);
|
||||
fprintf(out, " Number of arenas: %d(%d)\n", mArena->NumArenas(), mArena->ArenaSize());
|
||||
fprintf(out, " Height (maximum node level) of the tree: %d\n", height - 1);
|
||||
if (numTotalNodes > 0) {
|
||||
fprintf(out, " Average node level: %.1f\n", float(pathLength) / float(numTotalNodes));
|
||||
|
|
|
@ -41,11 +41,20 @@ class nsDST {
|
|||
public:
|
||||
typedef unsigned long PtrBits;
|
||||
|
||||
// Memory arena pool used for fast allocation and deallocation of DST nodes.
|
||||
// Maintains a free-list of freed objects.
|
||||
// Node arenas can be shared across DST objects (they don't lock when allocating
|
||||
// and freeing memory, so don't share them across threads). The DST object(s)
|
||||
// own the node arena, and you just hold a weak reference.
|
||||
class NodeArena;
|
||||
|
||||
// Create a DST. You specify the node arena to use; this allows the arena to
|
||||
// be shared.
|
||||
// By ignoring low-order pointer bits that are always 0, the tree height can
|
||||
// be reduced. Because pointer memory should be at least 32-bit aligned, the
|
||||
// default is for level 0 of the tree to start with bit 0x04 (i.e., we ignore
|
||||
// the two low-order bits)
|
||||
nsDST(PtrBits aLevelZeroBit = 0x04);
|
||||
nsDST(NodeArena* aArena, PtrBits aLevelZeroBit = 0x04);
|
||||
~nsDST();
|
||||
|
||||
void* Search(void* aKey) const;
|
||||
|
@ -58,31 +67,18 @@ public:
|
|||
void Dump(FILE*) const;
|
||||
#endif
|
||||
|
||||
// Create a memory arena pool. You can specify the size of the underlying arenas
|
||||
static NodeArena* NewMemoryArena(PRUint32 aArenaSize = 512);
|
||||
|
||||
private:
|
||||
class LeafNode;
|
||||
class TwoNode;
|
||||
struct NodeArena;
|
||||
friend class LeafNode;
|
||||
friend class TwoNode;
|
||||
friend struct NodeArena; // needs access to structs LeafNode and TwoNode
|
||||
|
||||
struct NodeArena {
|
||||
PLArenaPool mPool;
|
||||
LeafNode* mLeafNodeFreeList;
|
||||
TwoNode* mTwoNodeFreeList;
|
||||
|
||||
NodeArena();
|
||||
~NodeArena();
|
||||
|
||||
void* AllocLeafNode();
|
||||
void* AllocTwoNode();
|
||||
void FreeNode(LeafNode*);
|
||||
void FreeNode(TwoNode*);
|
||||
void FreeArenaPool();
|
||||
};
|
||||
friend class NodeArena; // needs access to structs LeafNode and TwoNode
|
||||
|
||||
LeafNode* mRoot; // root node of the tree
|
||||
NodeArena mArena;
|
||||
NodeArena* mArena;
|
||||
PtrBits mLevelZeroBit;
|
||||
|
||||
private:
|
||||
|
@ -93,6 +89,7 @@ private:
|
|||
LeafNode* ConvertToLeafNode(TwoNode** aTwoNode);
|
||||
TwoNode* ConvertToTwoNode(LeafNode** aLeafNode);
|
||||
void EnumTree(LeafNode* aNode, nsDSTNodeFunctor& aFunctor) const;
|
||||
void FreeTree(LeafNode* aNode);
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
// Diagnostic functions
|
||||
|
|
|
@ -243,7 +243,9 @@ private:
|
|||
FMPropertyDtorFunc mDtorFunc; // property specific value dtor function
|
||||
PropertyList* mNext;
|
||||
|
||||
PropertyList(nsIAtom* aName, FMPropertyDtorFunc aDtorFunc);
|
||||
PropertyList(nsIAtom* aName,
|
||||
FMPropertyDtorFunc aDtorFunc,
|
||||
nsDST::NodeArena* aDSTNodeArena);
|
||||
~PropertyList();
|
||||
|
||||
// Removes the property associated with the given frame, and destroys
|
||||
|
@ -251,8 +253,9 @@ private:
|
|||
void RemovePropertyForFrame(nsIFrame* aFrame);
|
||||
};
|
||||
|
||||
nsIPresShell* mPresShell; // weak link, because the pres shell owns us
|
||||
nsIStyleSet* mStyleSet; // weak link. pres shell holds a reference
|
||||
nsIPresShell* mPresShell; // weak link, because the pres shell owns us
|
||||
nsIStyleSet* mStyleSet; // weak link. pres shell holds a reference
|
||||
nsDST::NodeArena* mDSTNodeArena; // weak link. DST owns
|
||||
nsDST* mPrimaryFrameMap;
|
||||
FrameHashTable* mPlaceholderMap;
|
||||
UndisplayedMap* mUndisplayedMap;
|
||||
|
@ -333,6 +336,13 @@ FrameManager::Init(nsIPresShell* aPresShell,
|
|||
{
|
||||
mPresShell = aPresShell;
|
||||
mStyleSet = aStyleSet;
|
||||
|
||||
// Allocate the node arena that's shared by all the DST objects
|
||||
mDSTNodeArena = nsDST::NewMemoryArena();
|
||||
if (!mDSTNodeArena) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -381,7 +391,7 @@ FrameManager::SetPrimaryFrameFor(nsIContent* aContent,
|
|||
} else {
|
||||
// Create a new DST if necessary
|
||||
if (!mPrimaryFrameMap) {
|
||||
mPrimaryFrameMap = new nsDST;
|
||||
mPrimaryFrameMap = new nsDST(mDSTNodeArena);
|
||||
if (!mPrimaryFrameMap) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
@ -1569,7 +1579,7 @@ FrameManager::SetFrameProperty(nsIFrame* aFrame,
|
|||
}
|
||||
|
||||
} else {
|
||||
propertyList = new PropertyList(aPropertyName, aPropDtorFunc);
|
||||
propertyList = new PropertyList(aPropertyName, aPropDtorFunc, mDSTNodeArena);
|
||||
if (!propertyList) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
@ -1751,8 +1761,10 @@ UndisplayedMap::Clear(void)
|
|||
//----------------------------------------------------------------------
|
||||
|
||||
FrameManager::PropertyList::PropertyList(nsIAtom* aName,
|
||||
FMPropertyDtorFunc aDtorFunc)
|
||||
: mName(aName), mFrameValueMap(new nsDST), mDtorFunc(aDtorFunc), mNext(nsnull)
|
||||
FMPropertyDtorFunc aDtorFunc,
|
||||
nsDST::NodeArena* aDSTNodeArena)
|
||||
: mName(aName), mFrameValueMap(new nsDST(aDSTNodeArena)),
|
||||
mDtorFunc(aDtorFunc), mNext(nsnull)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче