XIF DTD now depends on a single stack rather than

multiple stacks.
r=akkana
Moved Node recycling to DTD Utils so that the recycler could
be used across DTDs.
r=rickg
Also fixed bug 27136.


git-svn-id: svn://10.0.0.236/trunk@66309 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
harishd%netscape.com 2000-04-18 21:10:28 +00:00
parent aab7fba560
commit 9cd3c6e67f
14 changed files with 1518 additions and 1622 deletions

View File

@ -165,68 +165,14 @@ CNavDTD::CNavDTD() : nsIDTD(),
InitializeElementTable();
}
mNodeRecycler=0;
#ifdef RICKG_DEBUG
//DebugDumpContainmentRules2(*this,"c:/temp/DTDRules.new","New CNavDTD Containment Rules");
nsHTMLElement::DebugDumpContainment("c:/temp/contain.new","ElementTable Rules");
nsHTMLElement::DebugDumpMembership("c:/temp/membership.out");
nsHTMLElement::DebugDumpContainType("c:/temp/ctnrules.out");
#endif
#ifdef NS_DEBUG
gNodeCount=0;
#endif
}
/**
* This method creates a new parser node. It tries to get one from
* the recycle list before allocating a new one.
* @update gess1/8/99
* @param
* @return valid node*
*/
nsCParserNode* CNavDTD::CreateNode(void) {
nsCParserNode* result=0;
if(0<mSharedNodes.GetSize()) {
result=(nsCParserNode*)mSharedNodes.Pop();
}
else{
result=new nsCParserNode();
#ifdef NS_DEBUG
#if 1
gNodeCount++;
#endif
#endif
}
return result;
}
/**
* This method recycles a given node
* @update gess1/8/99
* @param
* @return
*/
void CNavDTD::RecycleNode(nsCParserNode* aNode) {
if(aNode && (!aNode->mUseCount)) {
if(aNode->mToken) {
if(!aNode->mToken->mUseCount) {
mTokenRecycler->RecycleToken(aNode->mToken);
}
}
CToken* theToken=0;
while((theToken=(CToken*)aNode->PopAttributeToken())){
if(!theToken->mUseCount) {
mTokenRecycler->RecycleToken(theToken);
}
}
mSharedNodes.Push(aNode);
}
}
/**
@ -290,26 +236,7 @@ CNavDTD::~CNavDTD(){
if(mTempContext)
delete mTempContext;
nsCParserNode* theNode=0;
#ifdef NS_DEBUG
#if 0
PRInt32 count=gNodeCount-mSharedNodes.GetSize();
if(count) {
printf("%i of %i nodes leaked!\n",count,gNodeCount);
}
#endif
#endif
#if 1
while((theNode=(nsCParserNode*)mSharedNodes.Pop())){
delete theNode;
}
#endif
#ifdef NS_DEBUG
gNodeCount=0;
#endif
// delete mNodeRecycler;
NS_IF_RELEASE(mSink);
NS_IF_RELEASE(mDTDDebug);
@ -470,6 +397,8 @@ nsresult CNavDTD::WillBuildModel( const CParserContext& aParserContext,nsIConte
* @return error code (almost always NS_OK)
*/
nsresult CNavDTD::BuildModel(nsIParser* aParser,nsITokenizer* aTokenizer,nsITokenObserver* anObserver,nsIContentSink* aSink) {
NS_PRECONDITION(mBodyContext!=nsnull,"Create a context before calling build model");
nsresult result=NS_OK;
if(aTokenizer) {
@ -480,6 +409,11 @@ nsresult CNavDTD::BuildModel(nsIParser* aParser,nsITokenizer* aTokenizer,nsIToke
if(mTokenizer) {
mTokenRecycler=(CTokenRecycler*)mTokenizer->GetTokenRecycler();
result=mBodyContext->GetNodeRecycler(mNodeRecycler); // Get a copy...
if(NS_FAILED(result)) return result;
if(mSink) {
if(!mBodyContext->GetCount()) {
@ -579,7 +513,7 @@ nsresult CNavDTD::DidBuildModel(nsresult anErrorCode,PRBool aNotifySink,nsIParse
nsEntryStack *theChildStyles=0;
nsCParserNode* theNode=(nsCParserNode*)mBodyContext->Pop(theChildStyles);
theNode->mUseCount=0;
RecycleNode(theNode);
mNodeRecycler->RecycleNode(theNode,mTokenRecycler);
if(theChildStyles) {
delete theChildStyles;
}
@ -1319,7 +1253,7 @@ nsresult CNavDTD::HandleStartToken(CToken* aToken) {
//Begin by gathering up attributes...
nsCParserNode* theNode=CreateNode();
nsCParserNode* theNode=mNodeRecycler->CreateNode();
theNode->Init(aToken,mLineNumber,mTokenRecycler);
eHTMLTags theChildTag=(eHTMLTags)aToken->GetTypeID();
@ -1431,7 +1365,7 @@ nsresult CNavDTD::HandleStartToken(CToken* aToken) {
}//if
} //if
RecycleNode(theNode);
mNodeRecycler->RecycleNode(theNode,mTokenRecycler);
return result;
}
@ -1790,7 +1724,7 @@ nsresult CNavDTD::HandleEntityToken(CToken* aToken) {
nsresult result=NS_OK;
eHTMLTags theParentTag=mBodyContext->Last();
nsCParserNode* theNode=CreateNode();
nsCParserNode* theNode=mNodeRecycler->CreateNode();
if(theNode) {
theNode->Init(aToken,mLineNumber,0);
PRBool theParentContains=-1; //set to -1 to force CanOmit to recompute...
@ -1805,7 +1739,7 @@ nsresult CNavDTD::HandleEntityToken(CToken* aToken) {
#endif
result=AddLeaf(theNode);
RecycleNode(theNode);
mNodeRecycler->RecycleNode(theNode,mTokenRecycler);
}
return result;
}
@ -1828,7 +1762,7 @@ nsresult CNavDTD::HandleCommentToken(CToken* aToken) {
nsString& theComment=aToken->GetStringValueXXX();
mLineNumber += (theComment).CountChar(kNewLine);
nsCParserNode* theNode=CreateNode();
nsCParserNode* theNode=mNodeRecycler->CreateNode();
if(theNode) {
theNode->Init(aToken,mLineNumber,0);
@ -1841,7 +1775,7 @@ nsresult CNavDTD::HandleCommentToken(CToken* aToken) {
result=(mSink) ? mSink->AddComment(*theNode) : NS_OK;
RecycleNode(theNode);
mNodeRecycler->RecycleNode(theNode,mTokenRecycler);
MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::HandleCommentToken(), this=%p\n", this));
START_TIMER();
@ -1905,7 +1839,7 @@ nsresult CNavDTD::HandleProcessingInstructionToken(CToken* aToken){
nsresult result=NS_OK;
nsCParserNode* theNode=CreateNode();
nsCParserNode* theNode=mNodeRecycler->CreateNode();
if(theNode) {
theNode->Init(aToken,mLineNumber,0);
@ -1918,7 +1852,7 @@ nsresult CNavDTD::HandleProcessingInstructionToken(CToken* aToken){
result=(mSink) ? mSink->AddProcessingInstruction(*theNode) : NS_OK;
RecycleNode(theNode);
mNodeRecycler->RecycleNode(theNode,mTokenRecycler);
MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::HandleProcessingInstructionToken(), this=%p\n", this));
START_TIMER();
@ -1954,7 +1888,7 @@ nsresult CNavDTD::HandleDocTypeDeclToken(CToken* aToken){
}
docTypeStr.Cut(0,2); // Now remove "<!" from the begining
nsCParserNode* theNode=CreateNode();
nsCParserNode* theNode=mNodeRecycler->CreateNode();
if(theNode) {
theNode->Init(aToken,mLineNumber,0);
@ -1962,7 +1896,7 @@ nsresult CNavDTD::HandleDocTypeDeclToken(CToken* aToken){
MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::HandleDocTypeDeclToken(), this=%p\n", this));
result = (mSink)? mSink->AddDocTypeDecl(*theNode,mParseMode):NS_OK;
RecycleNode(theNode);
mNodeRecycler->RecycleNode(theNode,mTokenRecycler);
MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::HandleDocTypeDeclToken(), this=%p\n", this));
START_TIMER();
@ -2459,7 +2393,7 @@ nsresult CNavDTD::OpenTransientStyles(eHTMLTags aChildTag){
//if the node tag can't contain the child tag, then remove the child tag from the style stack
nsCParserNode* theRemovedNode=(nsCParserNode*)theStack->Remove(sindex,theNodeTag);
if(theRemovedNode) {
RecycleNode(theRemovedNode);
mNodeRecycler->RecycleNode(theRemovedNode,mTokenRecycler);
}
theEntry--; //back up by one
}
@ -2529,7 +2463,7 @@ nsresult CNavDTD::PopStyle(eHTMLTags aTag){
if(nsHTMLElement::IsResidualStyleTag(aTag)) {
nsCParserNode* theNode=(nsCParserNode*)mBodyContext->PopStyle(aTag);
if(theNode) {
RecycleNode(theNode);
mNodeRecycler->RecycleNode(theNode,mTokenRecycler);
}
}
#endif
@ -3197,7 +3131,7 @@ nsresult CNavDTD::CloseContainersTo(PRInt32 anIndex,eHTMLTags aTarget, PRBool aC
}
#endif
}//if anode
RecycleNode(theNode);
mNodeRecycler->RecycleNode(theNode,mTokenRecycler);
}

View File

@ -106,6 +106,7 @@ class nsEntryStack;
class nsITokenizer;
class nsCParserNode;
class CTokenRecycler;
class CNodeRecycler;
/***************************************************************
Now the main event: CNavDTD.
@ -483,8 +484,6 @@ protected:
nsresult DidHandleStartTag(nsCParserNode& aNode,eHTMLTags aChildTag);
nsresult HandleOmittedTag(CToken* aToken,eHTMLTags aChildTag,eHTMLTags aParent,nsIParserNode *aNode);
nsresult HandleSavedTokens(PRInt32 anIndex);
nsCParserNode* CreateNode(void);
void RecycleNode(nsCParserNode* aNode);
void RecycleNodes(nsEntryStack *aNodeStack);
nsIHTMLContentSink* mSink;
@ -507,6 +506,7 @@ protected:
nsParser* mParser;
nsITokenizer* mTokenizer;
CTokenRecycler* mTokenRecycler;
CNodeRecycler* mNodeRecycler;
nsDeque mMisplacedContent;
nsDeque mSkippedContent;
PRBool mHasOpenScript;
@ -526,10 +526,6 @@ protected:
PRBool mIsFormContainer;
nsAutoString mMimeType;
#ifdef NS_DEBUG
PRInt32 gNodeCount;
#endif
};
inline nsresult NS_NewNavHTMLDTD(nsIDTD** aInstancePtrResult)

View File

@ -33,8 +33,10 @@
MOZ_DECL_CTOR_COUNTER(nsEntryStack);
MOZ_DECL_CTOR_COUNTER(nsDTDContext);
MOZ_DECL_CTOR_COUNTER(CTokenRecycler);
MOZ_DECL_CTOR_COUNTER(CNodeRecycler);
MOZ_DECL_CTOR_COUNTER(CObserverService);
/**************************************************************************************
A few notes about how residual style handling is performed:
@ -373,7 +375,7 @@ PRInt32 nsEntryStack::GetTopmostIndexOf(eHTMLTags aTag) const {
/***************************************************************
Now define the dtdcontext class
***************************************************************/
CNodeRecycler* nsDTDContext::mNodeRecycler=0;
/**
*
@ -454,6 +456,15 @@ nsIParserNode* nsDTDContext::Pop(nsEntryStack *&aChildStyleStack) {
return result;
}
/**
*
* @update harishd 04/07/00
*/
nsIParserNode* nsDTDContext::Pop() {
nsEntryStack *theTempStyleStack=0; // This has no use here...
return Pop(theTempStyleStack);
}
/**
*
@ -640,6 +651,30 @@ nsIParserNode* nsDTDContext::RemoveStyle(eHTMLTags aTag){
return result;
}
/**
*
* @update harishd 04/10/00
*/
nsresult nsDTDContext::GetNodeRecycler(CNodeRecycler*& aNodeRecycler){
nsresult result=NS_OK;
if(!mNodeRecycler) {
mNodeRecycler=new CNodeRecycler();
if(mNodeRecycler==0) result=NS_ERROR_OUT_OF_MEMORY;
}
aNodeRecycler=mNodeRecycler;
return result;
}
/**
*
* @update hairshd 04/10/00
*/
void nsDTDContext::FreeNodeRecycler(){
if(mNodeRecycler) {
delete mNodeRecycler;
}
}
/**************************************************************
Now define the tokenrecycler class...
**************************************************************/
@ -801,6 +836,75 @@ CToken* CTokenRecycler::CreateTokenOfType(eHTMLTokenTypes aType,eHTMLTags aTag)
return result;
}
CNodeRecycler::CNodeRecycler(): mSharedNodes(0) {
MOZ_COUNT_CTOR(CTokenRecycler);
#ifdef NS_DEBUG
gNodeCount=0;
#endif
}
CNodeRecycler::~CNodeRecycler() {
MOZ_COUNT_DTOR(CTokenRecycler);
nsCParserNode* theNode=0;
#ifdef NS_DEBUG
#if 0
PRInt32 count=gNodeCount-mSharedNodes.GetSize();
if(count) {
printf("%i of %i nodes leaked!\n",count,gNodeCount);
}
#endif
#endif
while((theNode=(nsCParserNode*)mSharedNodes.Pop())){
delete theNode;
}
}
void CNodeRecycler::RecycleNode(nsCParserNode* aNode,nsITokenRecycler* aTokenRecycler) {
if(aNode && (!aNode->mUseCount)) {
// If the node contains tokens there better me a token recycler..
if(aTokenRecycler) {
if(aNode->mToken) {
if(!aNode->mToken->mUseCount) {
aTokenRecycler->RecycleToken(aNode->mToken);
}
}
CToken* theToken=0;
while((theToken=(CToken*)aNode->PopAttributeToken())){
if(!theToken->mUseCount) {
aTokenRecycler->RecycleToken(theToken);
}
}
}
mSharedNodes.Push(aNode);
}
}
nsCParserNode* CNodeRecycler::CreateNode(void) {
nsCParserNode* result=0;
if(0<mSharedNodes.GetSize()) {
result=(nsCParserNode*)mSharedNodes.Pop();
}
else{
result=new nsCParserNode();
#ifdef NS_DEBUG
#if 1
gNodeCount++;
#endif
#endif
}
return result;
}
void DebugDumpContainmentRules(nsIDTD& theDTD,const char* aFilename,const char* aTitle) {
#ifdef RICKG_DEBUG

View File

@ -41,8 +41,11 @@
#include "nsITokenizer.h"
#include "nsString.h"
#include "nsIElementObserver.h"
#include "nsIParserNode.h"
class nsIParserNode;
class nsCParserNode;
class CNodeRecycler;
void DebugDumpContainmentRules(nsIDTD& theDTD,const char* aFilename,const char* aTitle);
@ -138,6 +141,8 @@ public:
void Push(const nsIParserNode* aNode,nsEntryStack* aStyleStack=0);
nsIParserNode* Pop(nsEntryStack*& aChildStack);
nsIParserNode* Pop();
nsIParserNode* PeekNode() { return mStack.NodeAt(mStack.mCount-1); }
eHTMLTags First(void) const;
eHTMLTags Last(void) const;
nsTagEntry* LastEntry(void) const;
@ -157,17 +162,21 @@ public:
nsIParserNode* PopStyle(eHTMLTags aTag);
nsIParserNode* RemoveStyle(eHTMLTags aTag);
nsresult GetNodeRecycler(CNodeRecycler*& aNodeRecycler);
static void FreeNodeRecycler(void);
nsEntryStack mStack; //this will hold a list of tagentries...
PRInt32 mResidualStyleCount;
PRInt32 mContextTopIndex;
static CNodeRecycler* mNodeRecycler;
#ifdef NS_DEBUG
enum { eMaxTags = 100 };
eHTMLTags mXTags[eMaxTags];
#endif
};
/**************************************************************
Now define the token deallocator class...
**************************************************************/
@ -207,6 +216,29 @@ protected:
#endif
};
/************************************************************************
CNodeRecycler class implementation.
This class is used to recycle nodes.
By using this simple class, we cut down on the number of nodes
that get created during the run of the system.
************************************************************************/
class CNodeRecycler {
public:
CNodeRecycler();
virtual ~CNodeRecycler();
virtual nsCParserNode* CreateNode(void);
virtual void RecycleNode(nsCParserNode* aNode,nsITokenRecycler* aTokenRecycler=0);
protected:
nsDeque mSharedNodes;
#ifdef NS_DEBUG
PRInt32 gNodeCount;
#endif
};
/************************************************************************
ITagHandler class offers an API for taking care of specific tokens.
************************************************************************/

View File

@ -195,6 +195,7 @@ nsParserModule::Shutdown()
nsXMLTokenizer::FreeTokenRecycler();
nsExpatTokenizer::FreeTokenRecycler();
// nsTextTokenizer::FreeTokenRecycler();
nsDTDContext::FreeNodeRecycler();
nsParser::FreeSharedObjects();
mInitialized = PR_FALSE;
}

File diff suppressed because it is too large Load Diff

View File

@ -48,6 +48,11 @@ class CTokenHandler;
class nsIDTDDebug;
class nsIHTMLContentSink;
class nsITokenizer;
class nsDTDContext;
class nsEntryStack;
class nsCParserNode;
class CTokenRecycler;
class CNodeRecycler;
//*** This enum is used to define the known universe of XIF tags.
//*** The use of this table doesn't preclude of from using non-standard
@ -244,10 +249,6 @@ class nsXIFDTD : public nsIDTD {
* --------------[ Sets DTD to STOP mode ]----------------
* It's recommended to use this method in accordance with
* the parser's terminate() method.
*
* @update harishd 07/22/99
* @param
* @return
*/
virtual nsresult Terminate(void);
@ -275,9 +276,6 @@ class nsXIFDTD : public nsIDTD {
* This method gets called to determine whether a given
* tag is itself a container
*
* @update gess 12/1/99
* @param aTag -- tag to test for containership
* @return PR_TRUE if given tag can contain other tags
*/
virtual PRBool IsHTMLContainer(eHTMLTags aTag) const;
@ -296,52 +294,37 @@ class nsXIFDTD : public nsIDTD {
/**
* This method gets called when a start token has been consumed and needs
* to be handled (possibly added to content model via sink).
* @update gpk 06/18/98
* @param aToken is the start token to be handled
* @return TRUE if the token was handled.
*/
nsresult HandleStartToken(CToken* aToken);
/**
* This method gets called when an end token has been consumed and needs
* to be handled (possibly added to content model via sink).
* @update gpk 06/18/98
* @param aToken is the end token to be handled
* @return TRUE if the token was handled.
*/
nsresult HandleEndToken(CToken* aToken);
/**
* This method gets called when an entity token has been consumed and needs
* to be handled (possibly added to content model via sink).
* @update gpk 06/18/98
* @param aToken is the entity token to be handled
* @return TRUE if the token was handled.
*/
nsresult HandleEntityToken(CToken* aToken);
/**
* This method gets called when a comment token has been consumed and needs
* to be handled (possibly added to content model via sink).
* @update gpk 06/18/98
* @param aToken is the comment token to be handled
* @return TRUE if the token was handled.
*/
nsresult HandleCommentToken(CToken* aToken);
nsresult HandleCommentToken(CToken* aToken,nsIParserNode& aNode);
/**
* This method gets called when an attribute token has been consumed and needs
* to be handled (possibly added to content model via sink).
* @update gpk 06/18/98
* @param aToken is the attribute token to be handled
* @return TRUE if the token was handled.
*/
nsresult HandleAttributeToken(CToken* aToken);
nsresult HandleAttributeToken(CToken* aToken,nsIParserNode& aNode);
nsresult HandleWhiteSpaceToken(CToken* aToken);
nsresult HandleTextToken(CToken* aToken);
nsresult HandleContainer(nsIParserNode& aNode);
nsresult HandleDefaultToken(CToken* aToken,nsIParserNode& aNode);
PRBool CanHandleDefaultTag(eXIFTags aTag, PRInt32& aIsContainer);
private:
@ -410,78 +393,65 @@ private:
* @return ptr to recycler (or null)
*/
virtual nsITokenRecycler* GetTokenRecycler(void);
eHTMLTags GetStartTag(const nsIParserNode& aNode, nsString& aName);
private:
void ProcessEncodeTag(const nsIParserNode& aNode);
void ProcessEntityTag(const nsIParserNode& aNode);
void ProcessDocumentInfoTag(const nsIParserNode& aNode);
nsresult ProcessEncodeTag(const nsIParserNode& aNode);
nsresult ProcessEntityTag(const nsIParserNode& aNode);
nsresult ProcessDocumentInfoTag(const nsIParserNode& aNode);
void BeginCSSStyleSheet(const nsIParserNode& aNode);
void EndCSSStyleSheet(const nsIParserNode& aNode);
nsresult BeginCSSStyleSheet(const nsIParserNode& aNode);
nsresult EndCSSStyleSheet(const nsIParserNode& aNode);
void BeginCSSStyleRule(const nsIParserNode& aNode);
void EndCSSStyleRule(const nsIParserNode& aNode);
nsresult BeginCSSStyleRule(const nsIParserNode& aNode);
nsresult EndCSSStyleRule(const nsIParserNode& aNode);
void AddCSSSelector(const nsIParserNode& aNode);
void AddCSSDeclaration(const nsIParserNode& aNode);
void BeginCSSDeclarationList(const nsIParserNode& aNode);
void EndCSSDeclarationList(const nsIParserNode& aNode);
void AddAttribute(nsIParserNode& aNode);
void PushHTMLTag(const eHTMLTags aTag, const nsString& aName);
void PopHTMLTag(eHTMLTags& aTag, nsString*& aName);
nsresult AddCSSSelector(const nsIParserNode& aNode);
nsresult AddCSSDeclaration(const nsIParserNode& aNode);
nsresult BeginCSSDeclarationList(const nsIParserNode& aNode);
nsresult EndCSSDeclarationList(const nsIParserNode& aNode);
PRBool GetAttributePair(nsIParserNode& aNode, nsString& aKey, nsString& aValue);
PRBool GetAttribute(const nsIParserNode& aNode, const nsString& aKey, nsString& aValue);
void BeginStartTag(const nsIParserNode& aNode);
void AddEndTag(const nsIParserNode& aNode);
void AddEndCommentTag(const nsIParserNode& aNode);
PRBool StartTopOfStack();
nsIParserNode* PeekNode();
CToken* PeekToken();
void PushNodeAndToken(nsString& aName);
void PopAndDelete();
protected:
nsresult WillHandleToken(CToken* aToken,eHTMLTokenTypes& aType);
nsresult DidHandleToken(CToken* aToken, nsresult aResult=NS_OK);
nsresult WillHandleStartToken(CToken* aToken,eXIFTags aTag, nsIParserNode& aNode);
nsresult DidHandleStartToken(CToken* aToken,eXIFTags aTag, nsIParserNode& aNode);
nsresult PreprocessStack();
PRBool CanContainFormElement(eXIFTags aParent,eXIFTags aChild) const;
nsresult CollectAttributes(nsCParserNode& aNode,PRInt32 aCount);
nsresult CollectSkippedContent(nsCParserNode& aNode,PRInt32& aCount);
nsresult CollectContentComment(CToken* aToken,nsCParserNode& aNode);
nsParser* mParser;
nsIHTMLContentSink* mSink;
PRBool mLeafBits[100];
eXIFTags mContextStack[100];
PRInt32 mContextStackPos;
PRBool mHasOpenForm;
PRBool mHasOpenMap;
nsIDTDDebug* mDTDDebug;
nsVoidArray mNodeStack;
nsVoidArray mTokenStack;
PRInt32 mHTMLStackPos;
eHTMLTags mHTMLTagStack[512];
nsAutoString* mHTMLNameStack[512];
PRBool mInContent;
nsString mBuffer;
PRInt32 mMaxCSSSelectorWidth;
PRInt32 mCSSDeclarationCount;
PRInt32 mCSSSelectorCount;
PRBool mLowerCaseTags;
PRBool mLowerCaseAttributes;
nsITokenizer* mTokenizer;
nsString mCharset;
nsDTDContext* mXIFContext;
CTokenRecycler* mTokenRecycler;
CNodeRecycler* mNodeRecycler;
nsresult mDTDState;
nsString mContainerKey;
nsString mEncodeKey;
nsString mCSSStyleSheetKey;
nsString mCSSSelectorKey;
nsString mCSSDeclarationKey;
nsString mGenericKey;
PRInt32 mLineNumber;
};

View File

@ -165,68 +165,14 @@ CNavDTD::CNavDTD() : nsIDTD(),
InitializeElementTable();
}
mNodeRecycler=0;
#ifdef RICKG_DEBUG
//DebugDumpContainmentRules2(*this,"c:/temp/DTDRules.new","New CNavDTD Containment Rules");
nsHTMLElement::DebugDumpContainment("c:/temp/contain.new","ElementTable Rules");
nsHTMLElement::DebugDumpMembership("c:/temp/membership.out");
nsHTMLElement::DebugDumpContainType("c:/temp/ctnrules.out");
#endif
#ifdef NS_DEBUG
gNodeCount=0;
#endif
}
/**
* This method creates a new parser node. It tries to get one from
* the recycle list before allocating a new one.
* @update gess1/8/99
* @param
* @return valid node*
*/
nsCParserNode* CNavDTD::CreateNode(void) {
nsCParserNode* result=0;
if(0<mSharedNodes.GetSize()) {
result=(nsCParserNode*)mSharedNodes.Pop();
}
else{
result=new nsCParserNode();
#ifdef NS_DEBUG
#if 1
gNodeCount++;
#endif
#endif
}
return result;
}
/**
* This method recycles a given node
* @update gess1/8/99
* @param
* @return
*/
void CNavDTD::RecycleNode(nsCParserNode* aNode) {
if(aNode && (!aNode->mUseCount)) {
if(aNode->mToken) {
if(!aNode->mToken->mUseCount) {
mTokenRecycler->RecycleToken(aNode->mToken);
}
}
CToken* theToken=0;
while((theToken=(CToken*)aNode->PopAttributeToken())){
if(!theToken->mUseCount) {
mTokenRecycler->RecycleToken(theToken);
}
}
mSharedNodes.Push(aNode);
}
}
/**
@ -290,26 +236,7 @@ CNavDTD::~CNavDTD(){
if(mTempContext)
delete mTempContext;
nsCParserNode* theNode=0;
#ifdef NS_DEBUG
#if 0
PRInt32 count=gNodeCount-mSharedNodes.GetSize();
if(count) {
printf("%i of %i nodes leaked!\n",count,gNodeCount);
}
#endif
#endif
#if 1
while((theNode=(nsCParserNode*)mSharedNodes.Pop())){
delete theNode;
}
#endif
#ifdef NS_DEBUG
gNodeCount=0;
#endif
// delete mNodeRecycler;
NS_IF_RELEASE(mSink);
NS_IF_RELEASE(mDTDDebug);
@ -470,6 +397,8 @@ nsresult CNavDTD::WillBuildModel( const CParserContext& aParserContext,nsIConte
* @return error code (almost always NS_OK)
*/
nsresult CNavDTD::BuildModel(nsIParser* aParser,nsITokenizer* aTokenizer,nsITokenObserver* anObserver,nsIContentSink* aSink) {
NS_PRECONDITION(mBodyContext!=nsnull,"Create a context before calling build model");
nsresult result=NS_OK;
if(aTokenizer) {
@ -480,6 +409,11 @@ nsresult CNavDTD::BuildModel(nsIParser* aParser,nsITokenizer* aTokenizer,nsIToke
if(mTokenizer) {
mTokenRecycler=(CTokenRecycler*)mTokenizer->GetTokenRecycler();
result=mBodyContext->GetNodeRecycler(mNodeRecycler); // Get a copy...
if(NS_FAILED(result)) return result;
if(mSink) {
if(!mBodyContext->GetCount()) {
@ -579,7 +513,7 @@ nsresult CNavDTD::DidBuildModel(nsresult anErrorCode,PRBool aNotifySink,nsIParse
nsEntryStack *theChildStyles=0;
nsCParserNode* theNode=(nsCParserNode*)mBodyContext->Pop(theChildStyles);
theNode->mUseCount=0;
RecycleNode(theNode);
mNodeRecycler->RecycleNode(theNode,mTokenRecycler);
if(theChildStyles) {
delete theChildStyles;
}
@ -1319,7 +1253,7 @@ nsresult CNavDTD::HandleStartToken(CToken* aToken) {
//Begin by gathering up attributes...
nsCParserNode* theNode=CreateNode();
nsCParserNode* theNode=mNodeRecycler->CreateNode();
theNode->Init(aToken,mLineNumber,mTokenRecycler);
eHTMLTags theChildTag=(eHTMLTags)aToken->GetTypeID();
@ -1431,7 +1365,7 @@ nsresult CNavDTD::HandleStartToken(CToken* aToken) {
}//if
} //if
RecycleNode(theNode);
mNodeRecycler->RecycleNode(theNode,mTokenRecycler);
return result;
}
@ -1790,7 +1724,7 @@ nsresult CNavDTD::HandleEntityToken(CToken* aToken) {
nsresult result=NS_OK;
eHTMLTags theParentTag=mBodyContext->Last();
nsCParserNode* theNode=CreateNode();
nsCParserNode* theNode=mNodeRecycler->CreateNode();
if(theNode) {
theNode->Init(aToken,mLineNumber,0);
PRBool theParentContains=-1; //set to -1 to force CanOmit to recompute...
@ -1805,7 +1739,7 @@ nsresult CNavDTD::HandleEntityToken(CToken* aToken) {
#endif
result=AddLeaf(theNode);
RecycleNode(theNode);
mNodeRecycler->RecycleNode(theNode,mTokenRecycler);
}
return result;
}
@ -1828,7 +1762,7 @@ nsresult CNavDTD::HandleCommentToken(CToken* aToken) {
nsString& theComment=aToken->GetStringValueXXX();
mLineNumber += (theComment).CountChar(kNewLine);
nsCParserNode* theNode=CreateNode();
nsCParserNode* theNode=mNodeRecycler->CreateNode();
if(theNode) {
theNode->Init(aToken,mLineNumber,0);
@ -1841,7 +1775,7 @@ nsresult CNavDTD::HandleCommentToken(CToken* aToken) {
result=(mSink) ? mSink->AddComment(*theNode) : NS_OK;
RecycleNode(theNode);
mNodeRecycler->RecycleNode(theNode,mTokenRecycler);
MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::HandleCommentToken(), this=%p\n", this));
START_TIMER();
@ -1905,7 +1839,7 @@ nsresult CNavDTD::HandleProcessingInstructionToken(CToken* aToken){
nsresult result=NS_OK;
nsCParserNode* theNode=CreateNode();
nsCParserNode* theNode=mNodeRecycler->CreateNode();
if(theNode) {
theNode->Init(aToken,mLineNumber,0);
@ -1918,7 +1852,7 @@ nsresult CNavDTD::HandleProcessingInstructionToken(CToken* aToken){
result=(mSink) ? mSink->AddProcessingInstruction(*theNode) : NS_OK;
RecycleNode(theNode);
mNodeRecycler->RecycleNode(theNode,mTokenRecycler);
MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::HandleProcessingInstructionToken(), this=%p\n", this));
START_TIMER();
@ -1954,7 +1888,7 @@ nsresult CNavDTD::HandleDocTypeDeclToken(CToken* aToken){
}
docTypeStr.Cut(0,2); // Now remove "<!" from the begining
nsCParserNode* theNode=CreateNode();
nsCParserNode* theNode=mNodeRecycler->CreateNode();
if(theNode) {
theNode->Init(aToken,mLineNumber,0);
@ -1962,7 +1896,7 @@ nsresult CNavDTD::HandleDocTypeDeclToken(CToken* aToken){
MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::HandleDocTypeDeclToken(), this=%p\n", this));
result = (mSink)? mSink->AddDocTypeDecl(*theNode,mParseMode):NS_OK;
RecycleNode(theNode);
mNodeRecycler->RecycleNode(theNode,mTokenRecycler);
MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::HandleDocTypeDeclToken(), this=%p\n", this));
START_TIMER();
@ -2459,7 +2393,7 @@ nsresult CNavDTD::OpenTransientStyles(eHTMLTags aChildTag){
//if the node tag can't contain the child tag, then remove the child tag from the style stack
nsCParserNode* theRemovedNode=(nsCParserNode*)theStack->Remove(sindex,theNodeTag);
if(theRemovedNode) {
RecycleNode(theRemovedNode);
mNodeRecycler->RecycleNode(theRemovedNode,mTokenRecycler);
}
theEntry--; //back up by one
}
@ -2529,7 +2463,7 @@ nsresult CNavDTD::PopStyle(eHTMLTags aTag){
if(nsHTMLElement::IsResidualStyleTag(aTag)) {
nsCParserNode* theNode=(nsCParserNode*)mBodyContext->PopStyle(aTag);
if(theNode) {
RecycleNode(theNode);
mNodeRecycler->RecycleNode(theNode,mTokenRecycler);
}
}
#endif
@ -3197,7 +3131,7 @@ nsresult CNavDTD::CloseContainersTo(PRInt32 anIndex,eHTMLTags aTarget, PRBool aC
}
#endif
}//if anode
RecycleNode(theNode);
mNodeRecycler->RecycleNode(theNode,mTokenRecycler);
}

View File

@ -106,6 +106,7 @@ class nsEntryStack;
class nsITokenizer;
class nsCParserNode;
class CTokenRecycler;
class CNodeRecycler;
/***************************************************************
Now the main event: CNavDTD.
@ -483,8 +484,6 @@ protected:
nsresult DidHandleStartTag(nsCParserNode& aNode,eHTMLTags aChildTag);
nsresult HandleOmittedTag(CToken* aToken,eHTMLTags aChildTag,eHTMLTags aParent,nsIParserNode *aNode);
nsresult HandleSavedTokens(PRInt32 anIndex);
nsCParserNode* CreateNode(void);
void RecycleNode(nsCParserNode* aNode);
void RecycleNodes(nsEntryStack *aNodeStack);
nsIHTMLContentSink* mSink;
@ -507,6 +506,7 @@ protected:
nsParser* mParser;
nsITokenizer* mTokenizer;
CTokenRecycler* mTokenRecycler;
CNodeRecycler* mNodeRecycler;
nsDeque mMisplacedContent;
nsDeque mSkippedContent;
PRBool mHasOpenScript;
@ -526,10 +526,6 @@ protected:
PRBool mIsFormContainer;
nsAutoString mMimeType;
#ifdef NS_DEBUG
PRInt32 gNodeCount;
#endif
};
inline nsresult NS_NewNavHTMLDTD(nsIDTD** aInstancePtrResult)

View File

@ -33,8 +33,10 @@
MOZ_DECL_CTOR_COUNTER(nsEntryStack);
MOZ_DECL_CTOR_COUNTER(nsDTDContext);
MOZ_DECL_CTOR_COUNTER(CTokenRecycler);
MOZ_DECL_CTOR_COUNTER(CNodeRecycler);
MOZ_DECL_CTOR_COUNTER(CObserverService);
/**************************************************************************************
A few notes about how residual style handling is performed:
@ -373,7 +375,7 @@ PRInt32 nsEntryStack::GetTopmostIndexOf(eHTMLTags aTag) const {
/***************************************************************
Now define the dtdcontext class
***************************************************************/
CNodeRecycler* nsDTDContext::mNodeRecycler=0;
/**
*
@ -454,6 +456,15 @@ nsIParserNode* nsDTDContext::Pop(nsEntryStack *&aChildStyleStack) {
return result;
}
/**
*
* @update harishd 04/07/00
*/
nsIParserNode* nsDTDContext::Pop() {
nsEntryStack *theTempStyleStack=0; // This has no use here...
return Pop(theTempStyleStack);
}
/**
*
@ -640,6 +651,30 @@ nsIParserNode* nsDTDContext::RemoveStyle(eHTMLTags aTag){
return result;
}
/**
*
* @update harishd 04/10/00
*/
nsresult nsDTDContext::GetNodeRecycler(CNodeRecycler*& aNodeRecycler){
nsresult result=NS_OK;
if(!mNodeRecycler) {
mNodeRecycler=new CNodeRecycler();
if(mNodeRecycler==0) result=NS_ERROR_OUT_OF_MEMORY;
}
aNodeRecycler=mNodeRecycler;
return result;
}
/**
*
* @update hairshd 04/10/00
*/
void nsDTDContext::FreeNodeRecycler(){
if(mNodeRecycler) {
delete mNodeRecycler;
}
}
/**************************************************************
Now define the tokenrecycler class...
**************************************************************/
@ -801,6 +836,75 @@ CToken* CTokenRecycler::CreateTokenOfType(eHTMLTokenTypes aType,eHTMLTags aTag)
return result;
}
CNodeRecycler::CNodeRecycler(): mSharedNodes(0) {
MOZ_COUNT_CTOR(CTokenRecycler);
#ifdef NS_DEBUG
gNodeCount=0;
#endif
}
CNodeRecycler::~CNodeRecycler() {
MOZ_COUNT_DTOR(CTokenRecycler);
nsCParserNode* theNode=0;
#ifdef NS_DEBUG
#if 0
PRInt32 count=gNodeCount-mSharedNodes.GetSize();
if(count) {
printf("%i of %i nodes leaked!\n",count,gNodeCount);
}
#endif
#endif
while((theNode=(nsCParserNode*)mSharedNodes.Pop())){
delete theNode;
}
}
void CNodeRecycler::RecycleNode(nsCParserNode* aNode,nsITokenRecycler* aTokenRecycler) {
if(aNode && (!aNode->mUseCount)) {
// If the node contains tokens there better me a token recycler..
if(aTokenRecycler) {
if(aNode->mToken) {
if(!aNode->mToken->mUseCount) {
aTokenRecycler->RecycleToken(aNode->mToken);
}
}
CToken* theToken=0;
while((theToken=(CToken*)aNode->PopAttributeToken())){
if(!theToken->mUseCount) {
aTokenRecycler->RecycleToken(theToken);
}
}
}
mSharedNodes.Push(aNode);
}
}
nsCParserNode* CNodeRecycler::CreateNode(void) {
nsCParserNode* result=0;
if(0<mSharedNodes.GetSize()) {
result=(nsCParserNode*)mSharedNodes.Pop();
}
else{
result=new nsCParserNode();
#ifdef NS_DEBUG
#if 1
gNodeCount++;
#endif
#endif
}
return result;
}
void DebugDumpContainmentRules(nsIDTD& theDTD,const char* aFilename,const char* aTitle) {
#ifdef RICKG_DEBUG

View File

@ -41,8 +41,11 @@
#include "nsITokenizer.h"
#include "nsString.h"
#include "nsIElementObserver.h"
#include "nsIParserNode.h"
class nsIParserNode;
class nsCParserNode;
class CNodeRecycler;
void DebugDumpContainmentRules(nsIDTD& theDTD,const char* aFilename,const char* aTitle);
@ -138,6 +141,8 @@ public:
void Push(const nsIParserNode* aNode,nsEntryStack* aStyleStack=0);
nsIParserNode* Pop(nsEntryStack*& aChildStack);
nsIParserNode* Pop();
nsIParserNode* PeekNode() { return mStack.NodeAt(mStack.mCount-1); }
eHTMLTags First(void) const;
eHTMLTags Last(void) const;
nsTagEntry* LastEntry(void) const;
@ -157,17 +162,21 @@ public:
nsIParserNode* PopStyle(eHTMLTags aTag);
nsIParserNode* RemoveStyle(eHTMLTags aTag);
nsresult GetNodeRecycler(CNodeRecycler*& aNodeRecycler);
static void FreeNodeRecycler(void);
nsEntryStack mStack; //this will hold a list of tagentries...
PRInt32 mResidualStyleCount;
PRInt32 mContextTopIndex;
static CNodeRecycler* mNodeRecycler;
#ifdef NS_DEBUG
enum { eMaxTags = 100 };
eHTMLTags mXTags[eMaxTags];
#endif
};
/**************************************************************
Now define the token deallocator class...
**************************************************************/
@ -207,6 +216,29 @@ protected:
#endif
};
/************************************************************************
CNodeRecycler class implementation.
This class is used to recycle nodes.
By using this simple class, we cut down on the number of nodes
that get created during the run of the system.
************************************************************************/
class CNodeRecycler {
public:
CNodeRecycler();
virtual ~CNodeRecycler();
virtual nsCParserNode* CreateNode(void);
virtual void RecycleNode(nsCParserNode* aNode,nsITokenRecycler* aTokenRecycler=0);
protected:
nsDeque mSharedNodes;
#ifdef NS_DEBUG
PRInt32 gNodeCount;
#endif
};
/************************************************************************
ITagHandler class offers an API for taking care of specific tokens.
************************************************************************/

View File

@ -195,6 +195,7 @@ nsParserModule::Shutdown()
nsXMLTokenizer::FreeTokenRecycler();
nsExpatTokenizer::FreeTokenRecycler();
// nsTextTokenizer::FreeTokenRecycler();
nsDTDContext::FreeNodeRecycler();
nsParser::FreeSharedObjects();
mInitialized = PR_FALSE;
}

File diff suppressed because it is too large Load Diff

View File

@ -48,6 +48,11 @@ class CTokenHandler;
class nsIDTDDebug;
class nsIHTMLContentSink;
class nsITokenizer;
class nsDTDContext;
class nsEntryStack;
class nsCParserNode;
class CTokenRecycler;
class CNodeRecycler;
//*** This enum is used to define the known universe of XIF tags.
//*** The use of this table doesn't preclude of from using non-standard
@ -244,10 +249,6 @@ class nsXIFDTD : public nsIDTD {
* --------------[ Sets DTD to STOP mode ]----------------
* It's recommended to use this method in accordance with
* the parser's terminate() method.
*
* @update harishd 07/22/99
* @param
* @return
*/
virtual nsresult Terminate(void);
@ -275,9 +276,6 @@ class nsXIFDTD : public nsIDTD {
* This method gets called to determine whether a given
* tag is itself a container
*
* @update gess 12/1/99
* @param aTag -- tag to test for containership
* @return PR_TRUE if given tag can contain other tags
*/
virtual PRBool IsHTMLContainer(eHTMLTags aTag) const;
@ -296,52 +294,37 @@ class nsXIFDTD : public nsIDTD {
/**
* This method gets called when a start token has been consumed and needs
* to be handled (possibly added to content model via sink).
* @update gpk 06/18/98
* @param aToken is the start token to be handled
* @return TRUE if the token was handled.
*/
nsresult HandleStartToken(CToken* aToken);
/**
* This method gets called when an end token has been consumed and needs
* to be handled (possibly added to content model via sink).
* @update gpk 06/18/98
* @param aToken is the end token to be handled
* @return TRUE if the token was handled.
*/
nsresult HandleEndToken(CToken* aToken);
/**
* This method gets called when an entity token has been consumed and needs
* to be handled (possibly added to content model via sink).
* @update gpk 06/18/98
* @param aToken is the entity token to be handled
* @return TRUE if the token was handled.
*/
nsresult HandleEntityToken(CToken* aToken);
/**
* This method gets called when a comment token has been consumed and needs
* to be handled (possibly added to content model via sink).
* @update gpk 06/18/98
* @param aToken is the comment token to be handled
* @return TRUE if the token was handled.
*/
nsresult HandleCommentToken(CToken* aToken);
nsresult HandleCommentToken(CToken* aToken,nsIParserNode& aNode);
/**
* This method gets called when an attribute token has been consumed and needs
* to be handled (possibly added to content model via sink).
* @update gpk 06/18/98
* @param aToken is the attribute token to be handled
* @return TRUE if the token was handled.
*/
nsresult HandleAttributeToken(CToken* aToken);
nsresult HandleAttributeToken(CToken* aToken,nsIParserNode& aNode);
nsresult HandleWhiteSpaceToken(CToken* aToken);
nsresult HandleTextToken(CToken* aToken);
nsresult HandleContainer(nsIParserNode& aNode);
nsresult HandleDefaultToken(CToken* aToken,nsIParserNode& aNode);
PRBool CanHandleDefaultTag(eXIFTags aTag, PRInt32& aIsContainer);
private:
@ -410,78 +393,65 @@ private:
* @return ptr to recycler (or null)
*/
virtual nsITokenRecycler* GetTokenRecycler(void);
eHTMLTags GetStartTag(const nsIParserNode& aNode, nsString& aName);
private:
void ProcessEncodeTag(const nsIParserNode& aNode);
void ProcessEntityTag(const nsIParserNode& aNode);
void ProcessDocumentInfoTag(const nsIParserNode& aNode);
nsresult ProcessEncodeTag(const nsIParserNode& aNode);
nsresult ProcessEntityTag(const nsIParserNode& aNode);
nsresult ProcessDocumentInfoTag(const nsIParserNode& aNode);
void BeginCSSStyleSheet(const nsIParserNode& aNode);
void EndCSSStyleSheet(const nsIParserNode& aNode);
nsresult BeginCSSStyleSheet(const nsIParserNode& aNode);
nsresult EndCSSStyleSheet(const nsIParserNode& aNode);
void BeginCSSStyleRule(const nsIParserNode& aNode);
void EndCSSStyleRule(const nsIParserNode& aNode);
nsresult BeginCSSStyleRule(const nsIParserNode& aNode);
nsresult EndCSSStyleRule(const nsIParserNode& aNode);
void AddCSSSelector(const nsIParserNode& aNode);
void AddCSSDeclaration(const nsIParserNode& aNode);
void BeginCSSDeclarationList(const nsIParserNode& aNode);
void EndCSSDeclarationList(const nsIParserNode& aNode);
void AddAttribute(nsIParserNode& aNode);
void PushHTMLTag(const eHTMLTags aTag, const nsString& aName);
void PopHTMLTag(eHTMLTags& aTag, nsString*& aName);
nsresult AddCSSSelector(const nsIParserNode& aNode);
nsresult AddCSSDeclaration(const nsIParserNode& aNode);
nsresult BeginCSSDeclarationList(const nsIParserNode& aNode);
nsresult EndCSSDeclarationList(const nsIParserNode& aNode);
PRBool GetAttributePair(nsIParserNode& aNode, nsString& aKey, nsString& aValue);
PRBool GetAttribute(const nsIParserNode& aNode, const nsString& aKey, nsString& aValue);
void BeginStartTag(const nsIParserNode& aNode);
void AddEndTag(const nsIParserNode& aNode);
void AddEndCommentTag(const nsIParserNode& aNode);
PRBool StartTopOfStack();
nsIParserNode* PeekNode();
CToken* PeekToken();
void PushNodeAndToken(nsString& aName);
void PopAndDelete();
protected:
nsresult WillHandleToken(CToken* aToken,eHTMLTokenTypes& aType);
nsresult DidHandleToken(CToken* aToken, nsresult aResult=NS_OK);
nsresult WillHandleStartToken(CToken* aToken,eXIFTags aTag, nsIParserNode& aNode);
nsresult DidHandleStartToken(CToken* aToken,eXIFTags aTag, nsIParserNode& aNode);
nsresult PreprocessStack();
PRBool CanContainFormElement(eXIFTags aParent,eXIFTags aChild) const;
nsresult CollectAttributes(nsCParserNode& aNode,PRInt32 aCount);
nsresult CollectSkippedContent(nsCParserNode& aNode,PRInt32& aCount);
nsresult CollectContentComment(CToken* aToken,nsCParserNode& aNode);
nsParser* mParser;
nsIHTMLContentSink* mSink;
PRBool mLeafBits[100];
eXIFTags mContextStack[100];
PRInt32 mContextStackPos;
PRBool mHasOpenForm;
PRBool mHasOpenMap;
nsIDTDDebug* mDTDDebug;
nsVoidArray mNodeStack;
nsVoidArray mTokenStack;
PRInt32 mHTMLStackPos;
eHTMLTags mHTMLTagStack[512];
nsAutoString* mHTMLNameStack[512];
PRBool mInContent;
nsString mBuffer;
PRInt32 mMaxCSSSelectorWidth;
PRInt32 mCSSDeclarationCount;
PRInt32 mCSSSelectorCount;
PRBool mLowerCaseTags;
PRBool mLowerCaseAttributes;
nsITokenizer* mTokenizer;
nsString mCharset;
nsDTDContext* mXIFContext;
CTokenRecycler* mTokenRecycler;
CNodeRecycler* mNodeRecycler;
nsresult mDTDState;
nsString mContainerKey;
nsString mEncodeKey;
nsString mCSSStyleSheetKey;
nsString mCSSSelectorKey;
nsString mCSSDeclarationKey;
nsString mGenericKey;
PRInt32 mLineNumber;
};