Bug 68213. Require users of nsFixedSizeAllocator to specify object size at Free() time to avoid 8 byte overhead per allocation. r=harishd, brendan, shaver, hyatt; sr=scc

git-svn-id: svn://10.0.0.236/trunk@91251 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
waterson%netscape.com 2001-04-04 05:00:08 +00:00
parent 049707d100
commit 1ef6e620b4
67 changed files with 2342 additions and 1539 deletions

View File

@ -98,25 +98,34 @@ public:
nsIContent* mElement;
static nsXBLAttributeEntry*
Create(nsIAtom* aSrcAtom, nsIAtom* aDstAtom, nsIContent* aContent) {
void* place = nsXBLPrototypeBinding::kAttrPool.Alloc(sizeof(nsXBLAttributeEntry));
return place ? ::new (place) nsXBLAttributeEntry(aSrcAtom, aDstAtom, aContent) : nsnull;
}
static void
Destroy(nsXBLAttributeEntry* aSelf) {
aSelf->~nsXBLAttributeEntry();
nsXBLPrototypeBinding::kAttrPool.Free(aSelf, sizeof(*aSelf));
}
nsCOMPtr<nsIAtom> mSrcAttribute;
nsCOMPtr<nsIAtom> mDstAttribute;
nsCOMPtr<nsIXBLAttributeEntry> mNext;
static void* operator new(size_t aSize, nsFixedSizeAllocator& aAllocator) {
return aAllocator.Alloc(aSize);
}
static void operator delete(void* aPtr, size_t aSize) {
nsFixedSizeAllocator::Free(aPtr, aSize);
}
NS_DECL_ISUPPORTS
protected:
nsXBLAttributeEntry(nsIAtom* aSrcAtom, nsIAtom* aDstAtom, nsIContent* aContent) {
NS_INIT_REFCNT(); mSrcAttribute = aSrcAtom; mDstAttribute = aDstAtom; mElement = aContent;
};
}
virtual ~nsXBLAttributeEntry() {};
NS_DECL_ISUPPORTS
private:
// Hide so that only Create() and Destroy() can be used to
// allocate and deallocate from the heap
static void* operator new(size_t) { return 0; }
static void operator delete(void*, size_t) {}
};
NS_IMPL_ISUPPORTS1(nsXBLAttributeEntry, nsIXBLAttributeEntry)
@ -159,27 +168,38 @@ public:
nsCOMPtr<nsIContent> mInsertionParent;
nsCOMPtr<nsIContent> mDefaultContent;
PRUint32 mInsertionIndex;
static nsXBLInsertionPointEntry*
Create(nsIContent* aParent) {
void* place = nsXBLPrototypeBinding::kInsPool.Alloc(sizeof(nsXBLInsertionPointEntry));
return place ? ::new (place) nsXBLInsertionPointEntry(aParent) : nsnull;
}
static void
Destroy(nsXBLInsertionPointEntry* aSelf) {
aSelf->~nsXBLInsertionPointEntry();
nsXBLPrototypeBinding::kInsPool.Free(aSelf, sizeof(*aSelf));
}
static void* operator new(size_t aSize, nsFixedSizeAllocator& aAllocator) {
return aAllocator.Alloc(aSize);
}
static void operator delete(void* aPtr, size_t aSize) {
nsFixedSizeAllocator::Free(aPtr, aSize);
}
NS_DECL_ISUPPORTS
protected:
nsXBLInsertionPointEntry(nsIContent* aParent) {
NS_INIT_REFCNT();
mInsertionIndex = 0;
mInsertionParent = aParent;
};
virtual ~nsXBLInsertionPointEntry() {};
NS_DECL_ISUPPORTS
private:
// Hide so that only Create() and Destroy() can be used to
// allocate and deallocate from the heap
static void* operator new(size_t) { return 0; }
static void operator delete(void*, size_t) {}
};
NS_IMPL_ISUPPORTS1(nsXBLInsertionPointEntry, nsIXBLInsertionPointEntry)
NS_IMPL_ADDREF(nsXBLInsertionPointEntry)
NS_IMPL_RELEASE_WITH_DESTROY(nsXBLInsertionPointEntry, Destroy(this))
NS_IMPL_QUERY_INTERFACE1(nsXBLInsertionPointEntry, nsIXBLInsertionPointEntry)
// =============================================================================
@ -1107,7 +1127,7 @@ nsXBLPrototypeBinding::ConstructAttributeTable(nsIContent* aElement)
}
// Create an XBL attribute entry.
nsXBLAttributeEntry* xblAttr = new (kAttrPool) nsXBLAttributeEntry(atom, attribute, aElement);
nsXBLAttributeEntry* xblAttr = nsXBLAttributeEntry::Create(atom, attribute, aElement);
// Now we should see if some element within our anonymous
// content is already observing this attribute.
@ -1173,7 +1193,7 @@ nsXBLPrototypeBinding::ConstructInsertionTable(nsIContent* aContent)
child->GetParent(*getter_AddRefs(parent));
// Create an XBL insertion point entry.
nsXBLInsertionPointEntry* xblIns = new (kInsPool) nsXBLInsertionPointEntry(parent);
nsXBLInsertionPointEntry* xblIns = nsXBLInsertionPointEntry::Create(parent);
nsAutoString includes;
child->GetAttribute(kNameSpaceID_None, kIncludesAtom, includes);

View File

@ -97,39 +97,22 @@ static PRBool IsResourceURI(nsIURI* aURI)
}
// Individual binding requests.
struct nsXBLBindingRequest
class nsXBLBindingRequest
{
public:
nsCString mBindingURL;
nsCOMPtr<nsIContent> mBoundElement;
nsXBLBindingRequest(const nsCString& aURL, nsIContent* aBoundElement)
{
mBindingURL = aURL;
mBoundElement = aBoundElement;
gRefCnt++;
if (gRefCnt == 1) {
nsServiceManager::GetService("@mozilla.org/xbl;1",
NS_GET_IID(nsIXBLService),
(nsISupports**) &gXBLService);
}
static nsXBLBindingRequest*
Create(nsFixedSizeAllocator& aPool, const nsCString& aURL, nsIContent* aBoundElement) {
void* place = aPool.Alloc(sizeof(nsXBLBindingRequest));
return place ? ::new (place) nsXBLBindingRequest(aURL, aBoundElement) : nsnull;
}
~nsXBLBindingRequest()
{
gRefCnt--;
if (gRefCnt == 0) {
nsServiceManager::ReleaseService("@mozilla.org/xbl;1", gXBLService);
gXBLService = nsnull;
}
}
static void* operator new(size_t aSize, nsFixedSizeAllocator& aAllocator) {
return aAllocator.Alloc(aSize);
}
static void operator delete(void* aPtr, size_t aSize) {
nsFixedSizeAllocator::Free(aPtr, aSize);
static void
Destroy(nsFixedSizeAllocator& aPool, nsXBLBindingRequest* aRequest) {
aRequest->~nsXBLBindingRequest();
aPool.Free(aRequest, sizeof(*aRequest));
}
void DocumentLoaded(nsIDocument* aBindingDoc)
@ -166,6 +149,35 @@ struct nsXBLBindingRequest
static nsIXBLService* gXBLService;
static int gRefCnt;
protected:
nsXBLBindingRequest(const nsCString& aURL, nsIContent* aBoundElement)
{
mBindingURL = aURL;
mBoundElement = aBoundElement;
gRefCnt++;
if (gRefCnt == 1) {
nsServiceManager::GetService("@mozilla.org/xbl;1",
NS_GET_IID(nsIXBLService),
(nsISupports**) &gXBLService);
}
}
~nsXBLBindingRequest()
{
gRefCnt--;
if (gRefCnt == 0) {
nsServiceManager::ReleaseService("@mozilla.org/xbl;1", gXBLService);
gXBLService = nsnull;
}
}
private:
// Hide so that only Create() and Destroy() can be used to
// allocate and deallocate from the heap
static void* operator new(size_t) { return 0; }
static void operator delete(void*, size_t) {}
};
static const size_t kBucketSizes[] = {
@ -198,13 +210,15 @@ public:
static nsIXULPrototypeCache* gXULCache;
static PRInt32 gRefCnt;
nsXBLStreamListener(nsIStreamListener* aInner, nsIDocument* aDocument, nsIDocument* aBindingDocument);
nsXBLStreamListener(nsXBLService* aXBLService, nsIStreamListener* aInner, nsIDocument* aDocument, nsIDocument* aBindingDocument);
virtual ~nsXBLStreamListener();
void AddRequest(nsXBLBindingRequest* aRequest) { mBindingRequests.AppendElement(aRequest); };
PRBool HasRequest(const nsCString& aURI, nsIContent* aBoundElement);
private:
nsXBLService* mXBLService; // [WEAK]
nsCOMPtr<nsIStreamListener> mInner;
nsVoidArray mBindingRequests;
@ -218,11 +232,13 @@ PRInt32 nsXBLStreamListener::gRefCnt = 0;
/* Implementation file */
NS_IMPL_ISUPPORTS4(nsXBLStreamListener, nsIStreamListener, nsIStreamObserver, nsIDOMLoadListener, nsIDOMEventListener)
nsXBLStreamListener::nsXBLStreamListener(nsIStreamListener* aInner, nsIDocument* aDocument,
nsXBLStreamListener::nsXBLStreamListener(nsXBLService* aXBLService,
nsIStreamListener* aInner, nsIDocument* aDocument,
nsIDocument* aBindingDocument)
{
NS_INIT_ISUPPORTS();
/* member initializers and constructor code */
mXBLService = aXBLService;
mInner = aInner;
mDocument = getter_AddRefs(NS_GetWeakReference(aDocument));
mBindingDocument = aBindingDocument;
@ -290,7 +306,7 @@ nsXBLStreamListener::OnStopRequest(nsIRequest* request, nsISupports* aCtxt, nsre
PRUint32 count = mBindingRequests.Count();
for (PRUint32 i = 0; i < count; i++) {
nsXBLBindingRequest* req = (nsXBLBindingRequest*)mBindingRequests.ElementAt(i);
delete req;
nsXBLBindingRequest::Destroy(mXBLService->mPool, req);
}
mDocument = nsnull;
@ -404,7 +420,7 @@ nsXBLStreamListener::Load(nsIDOMEvent* aEvent)
for (i = 0; i < count; i++) {
nsXBLBindingRequest* req = (nsXBLBindingRequest*)mBindingRequests.ElementAt(i);
delete req;
nsXBLBindingRequest::Destroy(mXBLService->mPool, req);
}
nsCOMPtr<nsIDOMEventReceiver> rec(do_QueryInterface(mBindingDocument));
@ -1122,7 +1138,7 @@ nsXBLService::LoadBindingDocumentInfo(nsIContent* aBoundElement, nsIDocument* aB
bindingURI += "#";
bindingURI += aRef;
if (!xblListener->HasRequest(bindingURI, aBoundElement)) {
nsXBLBindingRequest* req = new (mPool) nsXBLBindingRequest(bindingURI, aBoundElement);
nsXBLBindingRequest* req = nsXBLBindingRequest::Create(mPool, bindingURI, aBoundElement);
xblListener->AddRequest(req);
}
return NS_OK;
@ -1225,7 +1241,7 @@ nsXBLService::FetchBindingDocument(nsIContent* aBoundElement, nsIDocument* aBoun
if (!aForceSyncLoad) {
// We can be asynchronous
nsXBLStreamListener* xblListener = new nsXBLStreamListener(listener, aBoundDocument, doc);
nsXBLStreamListener* xblListener = new nsXBLStreamListener(this, listener, aBoundDocument, doc);
nsCOMPtr<nsIDOMEventReceiver> rec(do_QueryInterface(doc));
rec->AddEventListener(NS_ConvertASCIItoUCS2("load"), (nsIDOMLoadListener*)xblListener, PR_FALSE);
@ -1241,7 +1257,7 @@ nsXBLService::FetchBindingDocument(nsIContent* aBoundElement, nsIDocument* aBoun
nsCAutoString bindingURI(uri);
bindingURI += "#";
bindingURI += aRef;
nsXBLBindingRequest* req = new (mPool) nsXBLBindingRequest(bindingURI, aBoundElement);
nsXBLBindingRequest* req = nsXBLBindingRequest::Create(mPool, bindingURI, aBoundElement);
xblListener->AddRequest(req);
// Now kick off the async read.

View File

@ -65,8 +65,9 @@ static PLHashEntry* PR_CALLBACK AllocEntry(void* aPool, const void* aKey)
static void PR_CALLBACK FreeEntry(void* aPool, PLHashEntry* aEntry, PRUintn aFlag)
{
nsFixedSizeAllocator* pool = NS_STATIC_CAST(nsFixedSizeAllocator*, aPool);
if (aFlag == HT_FREE_ENTRY)
nsFixedSizeAllocator::Free(aEntry, sizeof(PLHashEntry));
pool->Free(aEntry, sizeof(PLHashEntry));
}
PLHashAllocOps nsElementMap::gAllocOps = {
@ -115,7 +116,7 @@ nsElementMap::~nsElementMap()
MOZ_COUNT_DTOR(nsElementMap);
if (mMap) {
PL_HashTableEnumerateEntries(mMap, ReleaseContentList, nsnull);
PL_HashTableEnumerateEntries(mMap, ReleaseContentList, this);
PL_HashTableDestroy(mMap);
}
@ -127,6 +128,8 @@ nsElementMap::~nsElementMap()
PRIntn
nsElementMap::ReleaseContentList(PLHashEntry* aHashEntry, PRIntn aIndex, void* aClosure)
{
nsElementMap* self = NS_STATIC_CAST(nsElementMap*, aClosure);
PRUnichar* id =
NS_REINTERPRET_CAST(PRUnichar*, NS_CONST_CAST(void*, aHashEntry->key));
@ -138,7 +141,7 @@ nsElementMap::ReleaseContentList(PLHashEntry* aHashEntry, PRIntn aIndex, void* a
while (head) {
ContentListItem* doomed = head;
head = head->mNext;
delete doomed;
ContentListItem::Destroy(self->mPool, doomed);
}
return HT_ENUMERATE_NEXT;
@ -159,7 +162,7 @@ nsElementMap::Add(const nsAReadableString& aID, nsIContent* aContent)
NS_STATIC_CAST(ContentListItem*, PL_HashTableLookup(mMap, id));
if (! head) {
head = new (mPool) ContentListItem(aContent);
head = ContentListItem::Create(mPool, aContent);
if (! head)
return NS_ERROR_OUT_OF_MEMORY;
@ -211,7 +214,7 @@ nsElementMap::Add(const nsAReadableString& aID, nsIContent* aContent)
head = head->mNext;
}
head->mNext = new (mPool) ContentListItem(aContent);
head->mNext = ContentListItem::Create(mPool, aContent);
if (! head->mNext)
return NS_ERROR_OUT_OF_MEMORY;
}
@ -302,14 +305,14 @@ nsElementMap::Remove(const nsAReadableString& aID, nsIContent* aContent)
PL_HashTableRawRemove(mMap, hep, *hep);
nsMemory::Free(key);
}
delete head;
ContentListItem::Destroy(mPool, head);
}
else {
ContentListItem* item = head->mNext;
while (item) {
if (item->mContent.get() == aContent) {
head->mNext = item->mNext;
delete item;
ContentListItem::Destroy(mPool, item);
break;
}
head = item;
@ -365,7 +368,7 @@ nsElementMap::FindFirst(const nsAReadableString& aID, nsIContent** aResult)
nsresult
nsElementMap::Enumerate(nsElementMapEnumerator aEnumerator, void* aClosure)
{
EnumerateClosure closure = { aEnumerator, aClosure };
EnumerateClosure closure = { this, aEnumerator, aClosure };
PL_HashTableEnumerateEntries(mMap, EnumerateImpl, &closure);
return NS_OK;
}
@ -398,7 +401,7 @@ nsElementMap::EnumerateImpl(PLHashEntry* aHashEntry, PRIntn aIndex, void* aClosu
if (result == HT_ENUMERATE_REMOVE) {
// If the user wants to remove the current, then deal.
*link = item;
delete current;
ContentListItem::Destroy(closure->mSelf->mPool, current);
if ((! *link) && (link == NS_REINTERPRET_CAST(ContentListItem**, &aHashEntry->value))) {
// It's the last content node that was mapped to this

View File

@ -65,22 +65,31 @@ protected:
class ContentListItem {
public:
static void* operator new(size_t aSize, nsFixedSizeAllocator& aAllocator) {
return aAllocator.Alloc(aSize); }
static void operator delete(void* aPtr, size_t aSize) {
nsFixedSizeAllocator::Free(aPtr, aSize); }
ContentListItem(nsIContent* aContent) : mNext(nsnull), mContent(aContent) {
MOZ_COUNT_CTOR(nsElementMap::ContentListItem);
}
~ContentListItem() {
MOZ_COUNT_DTOR(nsElementMap::ContentListItem);
}
ContentListItem* mNext;
nsCOMPtr<nsIContent> mContent;
static ContentListItem*
Create(nsFixedSizeAllocator& aPool, nsIContent* aContent) {
void* bytes = aPool.Alloc(sizeof(ContentListItem));
return bytes ? new (bytes) ContentListItem(aContent) : nsnull; }
static void
Destroy(nsFixedSizeAllocator& aPool, ContentListItem* aItem) {
delete aItem;
aPool.Free(aItem, sizeof(*aItem)); }
protected:
static void* operator new(size_t aSize, void* aPtr) {
return aPtr; }
static void operator delete(void* aPtr, size_t aSize) {
/* do nothing; memory free()'d in Destroy() */ }
ContentListItem(nsIContent* aContent) : mNext(nsnull), mContent(aContent) {
MOZ_COUNT_CTOR(nsElementMap::ContentListItem); }
~ContentListItem() {
MOZ_COUNT_DTOR(nsElementMap::ContentListItem); }
};
static PLHashNumber PR_CALLBACK
@ -117,6 +126,7 @@ public:
private:
struct EnumerateClosure {
nsElementMap* mSelf;
nsElementMapEnumerator mEnumerator;
void* mClosure;
};

View File

@ -41,7 +41,9 @@ nsClusterKeySet::nsClusterKeySet()
mPool.Init("nsClusterKeySet", kBucketSizes, kNumBuckets, kInitialPoolSize);
mTable = PL_NewHashTable(kInitialEntries, nsClusterKey::HashClusterKey, nsClusterKey::CompareClusterKeys,
mTable = PL_NewHashTable(kInitialEntries,
nsClusterKey::HashClusterKey,
nsClusterKey::CompareClusterKeys,
PL_CompareValues, &gAllocOps, &mPool);
MOZ_COUNT_CTOR(nsClusterKeySet);

View File

@ -37,13 +37,13 @@ public:
protected:
class Entry {
private:
// Hide so that only Create() and Destroy() can be used to
// allocate and deallocate from the heap
static void* operator new(size_t) { return 0; }
static void operator delete(void*, size_t) {}
public:
static void* operator new(size_t aSize, nsFixedSizeAllocator& aAllocator) {
return aAllocator.Alloc(aSize); }
static void operator delete(void* aPtr, size_t aSize) {
nsFixedSizeAllocator::Free(aPtr, aSize); }
Entry() { MOZ_COUNT_CTOR(nsClusterKeySet::Entry); }
Entry(const nsClusterKey& aKey) : mKey(aKey) {
@ -51,10 +51,20 @@ protected:
~Entry() { MOZ_COUNT_DTOR(nsClusterKeySet::Entry); }
PLHashEntry mHashEntry;
nsClusterKey mKey;
Entry* mPrev;
Entry* mNext;
static Entry*
Create(nsFixedSizeAllocator& aPool, const nsClusterKey& aKey) {
void* place = aPool.Alloc(sizeof(Entry));
return place ? ::new (place) Entry(aKey) : nsnull; }
static void
Destroy(nsFixedSizeAllocator& aPool, Entry* aEntry) {
aEntry->~Entry();
aPool.Free(aEntry, sizeof(*aEntry)); }
PLHashEntry mHashEntry;
nsClusterKey mKey;
Entry* mPrev;
Entry* mNext;
};
PLHashTable* mTable;
@ -120,12 +130,13 @@ protected:
static PLHashEntry* PR_CALLBACK AllocEntry(void* aPool, const void* aKey) {
nsFixedSizeAllocator* pool = NS_STATIC_CAST(nsFixedSizeAllocator*, aPool);
const nsClusterKey* key = NS_STATIC_CAST(const nsClusterKey*, aKey);
Entry* entry = new (*pool) Entry(*key);
Entry* entry = Entry::Create(*pool, *key);
return NS_REINTERPRET_CAST(PLHashEntry*, entry); }
static void PR_CALLBACK FreeEntry(void* aPool, PLHashEntry* aEntry, PRUintn aFlag) {
nsFixedSizeAllocator* pool = NS_STATIC_CAST(nsFixedSizeAllocator*, aPool);
if (aFlag == HT_FREE_ENTRY)
delete NS_REINTERPRET_CAST(Entry*, aEntry); }
Entry::Destroy(*pool, NS_REINTERPRET_CAST(Entry*, aEntry)); }
};
#endif // nsClusterKeySet_h__

View File

@ -22,6 +22,7 @@
*/
#include "nsConflictSet.h"
#include "nsTemplateRule.h"
#ifdef PR_LOGGING
PRLogModule* nsConflictSet::gLog;
@ -52,8 +53,6 @@ nsConflictSet::Init()
sizeof(ClusterEntry),
sizeof(SupportEntry),
sizeof(BindingEntry),
nsTemplateMatchSet::kEntrySize,
nsTemplateMatchSet::kIndexSize
};
static const PRInt32 kNumBuckets = sizeof(kBucketSizes) / sizeof(size_t);
@ -115,10 +114,10 @@ nsConflictSet::Add(nsTemplateMatch* aMatch)
PLHashNumber hash = key.Hash();
PLHashEntry** hep = PL_HashTableRawLookup(mClusters, hash, &key);
nsTemplateMatchSet* set;
MatchCluster* cluster;
if (hep && *hep) {
set = NS_STATIC_CAST(nsTemplateMatchSet*, (*hep)->value);
cluster = NS_REINTERPRET_CAST(MatchCluster*, (*hep)->value);
}
else {
PLHashEntry* he = PL_HashTableRawAdd(mClusters, hep, hash, &key, nsnull);
@ -132,14 +131,12 @@ nsConflictSet::Add(nsTemplateMatch* aMatch)
// than the value on the stack). Do the same for its
// value.
entry->mHashEntry.key = &entry->mKey;
entry->mHashEntry.value = &entry->mMatchSet;
set = &entry->mMatchSet;
entry->mHashEntry.value = cluster = &entry->mCluster;
}
if (! set->Contains(*aMatch)) {
set->Add(mPool, aMatch);
}
nsTemplateMatchRefSet& set = cluster->mMatches;
if (! set.Contains(aMatch))
set.Add(aMatch);
}
@ -150,10 +147,10 @@ nsConflictSet::Add(nsTemplateMatch* aMatch)
PLHashNumber hash = element->Hash();
PLHashEntry** hep = PL_HashTableRawLookup(mSupport, hash, element.operator->());
nsTemplateMatchSet* set;
nsTemplateMatchRefSet* set;
if (hep && *hep) {
set = NS_STATIC_CAST(nsTemplateMatchSet*, (*hep)->value);
set = NS_STATIC_CAST(nsTemplateMatchRefSet*, (*hep)->value);
}
else {
PLHashEntry* he = PL_HashTableRawAdd(mSupport, hep, hash, element.operator->(), nsnull);
@ -169,8 +166,9 @@ nsConflictSet::Add(nsTemplateMatch* aMatch)
set = &entry->mMatchSet;
}
if (! set->Contains(*aMatch)) {
set->Add(mPool, aMatch);
if (! set->Contains(aMatch)) {
set->Add(aMatch);
aMatch->AddRef();
}
}
}
@ -184,26 +182,52 @@ nsConflictSet::Add(nsTemplateMatch* aMatch)
}
void
nsConflictSet::GetMatchesForClusterKey(const nsClusterKey& aKey, const nsTemplateMatchSet** aMatchSet)
nsConflictSet::MatchCluster*
nsConflictSet::GetMatchesForClusterKey(const nsClusterKey& aKey)
{
// Retrieve all the matches in a cluster
*aMatchSet = NS_STATIC_CAST(nsTemplateMatchSet*, PL_HashTableLookup(mClusters, &aKey));
return NS_STATIC_CAST(MatchCluster*, PL_HashTableLookup(mClusters, &aKey));
}
void
nsConflictSet::GetMatchesWithBindingDependency(nsIRDFResource* aResource, const nsTemplateMatchSet** aMatchSet)
nsTemplateMatch*
nsConflictSet::GetMatchWithHighestPriority(const MatchCluster* aMatchCluster) const
{
// Find the rule with the "highest priority"; i.e., the rule with
// the lowest value for GetPriority().
//
// XXX if people start writing more than a few matches, we should
// rewrite this to maintain the matches in sorted order, and then
// just pluck the match off the top of the list.
nsTemplateMatch* result = nsnull;
PRInt32 max = PRInt32(PR_BIT(31) - 1);
const nsTemplateMatchRefSet& set = aMatchCluster->mMatches;
nsTemplateMatchRefSet::ConstIterator last = set.Last();
for (nsTemplateMatchRefSet::ConstIterator match = set.First(); match != last; ++match) {
PRInt32 priority = match->mRule->GetPriority();
if (priority < max) {
result = NS_CONST_CAST(nsTemplateMatch*, match.operator->());
max = priority;
}
}
return result;
}
const nsTemplateMatchRefSet*
nsConflictSet::GetMatchesWithBindingDependency(nsIRDFResource* aResource)
{
// Retrieve all the matches whose bindings depend on the specified resource
*aMatchSet = NS_STATIC_CAST(nsTemplateMatchSet*, PL_HashTableLookup(mBindingDependencies, aResource));
return NS_STATIC_CAST(nsTemplateMatchRefSet*, PL_HashTableLookup(mBindingDependencies, aResource));
}
void
nsConflictSet::Remove(const MemoryElement& aMemoryElement,
nsTemplateMatchSet& aNewMatches,
nsTemplateMatchSet& aRetractedMatches)
nsTemplateMatchSet& aNewMatches,
nsTemplateMatchSet& aRetractedMatches)
{
// Use the memory-element-to-match map to figure out what matches
// will be affected.
@ -213,14 +237,16 @@ nsConflictSet::Remove(const MemoryElement& aMemoryElement,
return;
// 'set' gets the set of all matches containing the first binding.
nsTemplateMatchSet* set = NS_STATIC_CAST(nsTemplateMatchSet*, (*hep)->value);
nsTemplateMatchRefSet* set =
NS_STATIC_CAST(nsTemplateMatchRefSet*, (*hep)->value);
// We'll iterate through these matches, only paying attention to
// matches that strictly contain the MemoryElement we're about to
// remove.
for (nsTemplateMatchSet::Iterator match = set->First(); match != set->Last(); ++match) {
nsTemplateMatchRefSet::ConstIterator last = set->Last();
for (nsTemplateMatchRefSet::ConstIterator match = set->First(); match != last; ++match) {
// Note the retraction, so we can compute new matches, later.
aRetractedMatches.Add(mPool, match.operator->());
aRetractedMatches.Add(match.operator->());
// Keep the bindings table in sync, as well. Since this match
// is getting nuked, we need to nuke its bindings as well.
@ -244,10 +270,10 @@ nsConflictSet::AddBindingDependency(nsTemplateMatch* aMatch, nsIRDFResource* aRe
PLHashNumber hash = HashBindingElement(aResource);
PLHashEntry** hep = PL_HashTableRawLookup(mBindingDependencies, hash, aResource);
nsTemplateMatchSet* set;
nsTemplateMatchRefSet* set;
if (hep && *hep) {
set = NS_STATIC_CAST(nsTemplateMatchSet*, (*hep)->value);
set = NS_STATIC_CAST(nsTemplateMatchRefSet*, (*hep)->value);
}
else {
PLHashEntry* he = PL_HashTableRawAdd(mBindingDependencies, hep, hash, aResource, nsnull);
@ -261,9 +287,8 @@ nsConflictSet::AddBindingDependency(nsTemplateMatch* aMatch, nsIRDFResource* aRe
}
if (! set->Contains(*aMatch)) {
set->Add(mPool, aMatch);
}
if (! set->Contains(aMatch))
set->Add(aMatch);
return NS_OK;
}
@ -276,26 +301,28 @@ nsConflictSet::RemoveBindingDependency(nsTemplateMatch* aMatch, nsIRDFResource*
PLHashEntry** hep = PL_HashTableRawLookup(mBindingDependencies, hash, aResource);
if (hep && *hep) {
nsTemplateMatchSet* set = NS_STATIC_CAST(nsTemplateMatchSet*, (*hep)->value);
nsTemplateMatchRefSet* set = NS_STATIC_CAST(nsTemplateMatchRefSet*, (*hep)->value);
set->Remove(aMatch);
if (set->Empty()) {
if (set->Empty())
PL_HashTableRawRemove(mBindingDependencies, hep, *hep);
}
}
return NS_OK;
}
nsresult
nsConflictSet::ComputeNewMatches(nsTemplateMatchSet& aNewMatches, nsTemplateMatchSet& aRetractedMatches)
nsConflictSet::ComputeNewMatches(nsTemplateMatchSet& aNewMatches,
nsTemplateMatchSet& aRetractedMatches)
{
// Given a set of just-retracted matches, compute the set of new
// matches that have been revealed, updating the key-to-match map
// as we go.
nsTemplateMatchSet::ConstIterator last = aRetractedMatches.Last();
for (nsTemplateMatchSet::ConstIterator retraction = aRetractedMatches.First(); retraction != last; ++retraction) {
for (nsTemplateMatchSet::ConstIterator retraction = aRetractedMatches.First();
retraction != last;
++retraction) {
nsClusterKey key(retraction->mInstantiation, retraction->mRule);
PLHashEntry** hep = PL_HashTableRawLookup(mClusters, key.Hash(), &key);
@ -305,26 +332,27 @@ nsConflictSet::ComputeNewMatches(nsTemplateMatchSet& aNewMatches, nsTemplateMatc
if (!hep || !*hep)
continue;
nsTemplateMatchSet* set = NS_STATIC_CAST(nsTemplateMatchSet*, (*hep)->value);
MatchCluster* cluster = NS_REINTERPRET_CAST(MatchCluster*, (*hep)->value);
nsTemplateMatchRefSet& set = cluster->mMatches;
for (nsTemplateMatchSet::Iterator match = set->First(); match != set->Last(); ++match) {
nsTemplateMatchRefSet::ConstIterator last = set.Last();
for (nsTemplateMatchRefSet::ConstIterator match = set.First(); match != last; ++match) {
if (match->mRule == retraction->mRule) {
set->Erase(match--);
set.Remove(match.operator->()); // N.B., iterator no longer valid!
// See if we've revealed another rule that's applicable
nsTemplateMatch* newmatch =
set->FindMatchWithHighestPriority();
GetMatchWithHighestPriority(cluster);
if (newmatch)
aNewMatches.Add(mPool, newmatch);
aNewMatches.Add(newmatch);
break;
}
}
if (set->Empty()) {
if (set.Empty())
PL_HashTableRawRemove(mClusters, hep, *hep);
}
}
return NS_OK;
@ -358,3 +386,23 @@ nsConflictSet::CompareMemoryElements(const void* aLeft, const void* aRight)
return *left == *right;
}
//----------------------------------------------------------------------
//
void
nsConflictSet::SupportEntry::Destroy(nsFixedSizeAllocator& aPool, SupportEntry* aEntry)
{
// We need to Release() the matches here, because this is where
// we've got access to the pool from which they were
// allocated. Since SupportEntry's dtor is protected, nobody else
// can be creating SupportEntry objects (e.g., on the stack).
nsTemplateMatchRefSet::ConstIterator last = aEntry->mMatchSet.Last();
for (nsTemplateMatchRefSet::ConstIterator iter = aEntry->mMatchSet.First();
iter != last;
++iter)
iter->Release(aPool);
aEntry->~SupportEntry();
aPool.Free(aEntry, sizeof(*aEntry));
}

View File

@ -31,25 +31,100 @@
#include "nsIRDFResource.h"
/**
* Maintains the set of active matches, and the stuff that the
* matches depend on.
* Maintains the set of active matches, and the stuff that the matches
* depend on. An entity-relationship diagram of the situation might
* look something like this:
*
* nsIRDFResource objects
* (mBindingDependencies)
* |
* | [1]
* |
* [2] ^ [3]
* Match ``clusters'' ---< nsTemplateMatch >--- MemoryElement objects
* (mClusters) objects (mSupport)
*
* [1] Each match object may ``depend'' on one or more RDF resources;
* that is, if an assertion about a resource changes, will the
* match's bindings need to be updated? By maintaing a map from
* nsIRDFResource objects to match objects, we can quickly
* determine which matches will be affected when the datasource
* notifies us of new assertions about a resource.
*
* The AddBindingDependency() and RemoveBindingDependency()
* methods are used to add and remove dependencies from an
* nsIRDFResource object to a match. The
* GetMatchesWithBindingDependency() method is used to retrieve
* the matches that depend upon a particular nsIRDFResource
* object.
*
* [2] Each match is a ``grouped' by into a cluster for conflict
* resolution. If the template has more than one rule, then it's
* possible that more than one of the rules may match. If that's
* the case, we need to choose amongst the matched rules to select
* which one gets ``activated''. By maintaining a map from cluster
* ``key'' (really just a <container, member> tuple) to the set of
* matches that are active for that key, we can quickly select
* amongst the matches to determine which one should be activated.
*
* When a match is first added to the conflict set using the Add()
* method, it is automatically placed in the appropriate
* group. The GetMatchesForClusterKey() method is used to retrieve
* all the active matches in a match cluster; the
* GetMatchWithHighestPriority() method is used to select among
* these to determine which match should be activated.
*
* [3] Each match is ``supported'' by one or more MemoryElement
* objects. These objects represent the values that were bound to
* variables in the match's rule's conditions. If one of these
* MemoryElements is removed, then the match is no longer
* valid. We maintain a mapping from memory elements to the
* matches that they support so that we can quickly determine
* which matches will be affected by the removal of a memory
* element object.
*
* When a match is first added to the conflict set using the Add()
* method, the memory element dependencies are automatically
* computed. The Remove() method is used to notify the conflict
* set that a memory element has been removed; the method computes
* the matches that have been ``retracted'' because the memory
* element is gone, as well as any new matches that may have
* ``fired'' because they were blocked by the presence of the
* memory element.
*/
class nsConflictSet
{
public:
/**
* A ``cluster'' of matches, all with the same nsClusterKey (that
* is, matches with the same <container, member> tuple).
*/
class MatchCluster {
public:
MatchCluster() : mLastMatch(nsnull) {}
nsTemplateMatchRefSet mMatches;
nsTemplateMatch* mLastMatch;
};
nsConflictSet()
: mClusters(nsnull),
mSupport(nsnull),
mBindingDependencies(nsnull) { Init(); }
mBindingDependencies(nsnull) {
MOZ_COUNT_CTOR(nsConflictSet);
Init(); }
~nsConflictSet() { Destroy(); }
~nsConflictSet() {
MOZ_COUNT_DTOR(nsConflictSet);
Destroy(); }
/**
* Add a match to the conflict set.
* @param aMatch the match to add to the conflict set
* @return NS_OK if no errors occurred
*/
nsresult Add(nsTemplateMatch* aMatch);
nsresult
Add(nsTemplateMatch* aMatch);
/**
* Given a cluster key, which is a container-member pair, return the
@ -60,7 +135,16 @@ public:
* @param aMatchSet the set of matches that are currently active
* for the key.
*/
void GetMatchesForClusterKey(const nsClusterKey& aKey, const nsTemplateMatchSet** aMatchSet);
MatchCluster*
GetMatchesForClusterKey(const nsClusterKey& aKey);
/**
* Retrieve the match from the set with the ``highest priority''
* (that is, the lowest value returned by
* nsTemplateMatch::GetPriority()).
*/
nsTemplateMatch*
GetMatchWithHighestPriority(const MatchCluster* aMatchCluster) const;
/**
* Given a "source" in the RDF graph, return the set of matches
@ -68,7 +152,8 @@ public:
* @param aSource an RDF resource that is a "source" in the graph.
* @param aMatchSet the set of matches that depend on aSource.
*/
void GetMatchesWithBindingDependency(nsIRDFResource* aSource, const nsTemplateMatchSet** aMatchSet);
const nsTemplateMatchRefSet*
GetMatchesWithBindingDependency(nsIRDFResource* aSource);
/**
* Remove a memory element from the conflict set. This may
@ -80,13 +165,22 @@ public:
* @param aRetractedMatches matches whose validity depended
* on aMemoryElement and have been retracted.
*/
void Remove(const MemoryElement& aMemoryElement,
nsTemplateMatchSet& aNewMatches,
nsTemplateMatchSet& aRetractedMatches);
void
Remove(const MemoryElement& aMemoryElement,
nsTemplateMatchSet& aNewMatches,
nsTemplateMatchSet& aRetractedMatches);
nsresult AddBindingDependency(nsTemplateMatch* aMatch, nsIRDFResource* aResource);
/**
* Add a binding dependency for aMatch on aResource.
*/
nsresult
AddBindingDependency(nsTemplateMatch* aMatch, nsIRDFResource* aResource);
nsresult RemoveBindingDependency(nsTemplateMatch* aMatch, nsIRDFResource* aResource);
/**
* Remove the binding dependency on aResource from aMatch.
*/
nsresult
RemoveBindingDependency(nsTemplateMatch* aMatch, nsIRDFResource* aResource);
/**
* Remove all match support information currently stored in the conflict
@ -104,7 +198,9 @@ protected:
nsresult Init();
nsresult Destroy();
nsresult ComputeNewMatches(nsTemplateMatchSet& aNewMatches, nsTemplateMatchSet& aRetractedMatches);
nsresult
ComputeNewMatches(nsTemplateMatchSet& aNewMatches,
nsTemplateMatchSet& aRetractedMatches);
/**
* "Clusters" of matched rules for the same <content, member>
@ -115,19 +211,29 @@ protected:
PLHashTable* mClusters;
class ClusterEntry {
private:
// Hide so that only Create() and Destroy() can be used to
// allocate and deallocate from the heap
static void* operator new(size_t) { return 0; }
static void operator delete(void*, size_t) {}
public:
static void* operator new(size_t aSize, nsFixedSizeAllocator& aAllocator) {
return aAllocator.Alloc(aSize); }
static void operator delete(void* aPtr, size_t aSize) {
nsFixedSizeAllocator::Free(aPtr, aSize); }
ClusterEntry() { MOZ_COUNT_CTOR(nsConflictSet::ClusterEntry); }
~ClusterEntry() { MOZ_COUNT_DTOR(nsConflictSet::ClusterEntry); }
PLHashEntry mHashEntry;
nsClusterKey mKey;
nsTemplateMatchSet mMatchSet;
static ClusterEntry*
Create(nsFixedSizeAllocator& aPool) {
void* place = aPool.Alloc(sizeof(ClusterEntry));
return place ? ::new (place) ClusterEntry() : nsnull; }
static void
Destroy(nsFixedSizeAllocator& aPool, ClusterEntry* aEntry) {
aEntry->~ClusterEntry();
aPool.Free(aEntry, sizeof(*aEntry)); }
PLHashEntry mHashEntry;
nsClusterKey mKey;
MatchCluster mCluster;
};
static PLHashAllocOps gClusterAllocOps;
@ -141,7 +247,7 @@ protected:
static PLHashEntry* PR_CALLBACK AllocClusterEntry(void* aPool, const void* aKey) {
nsFixedSizeAllocator* pool = NS_STATIC_CAST(nsFixedSizeAllocator*, aPool);
ClusterEntry* entry = new (*pool) ClusterEntry();
ClusterEntry* entry = ClusterEntry::Create(*pool);
if (! entry)
return nsnull;
@ -149,24 +255,26 @@ protected:
return NS_REINTERPRET_CAST(PLHashEntry*, entry); }
static void PR_CALLBACK FreeClusterEntry(void* aPool, PLHashEntry* aHashEntry, PRUintn aFlag) {
nsFixedSizeAllocator* pool = NS_STATIC_CAST(nsFixedSizeAllocator*, aPool);
if (aFlag == HT_FREE_ENTRY)
delete NS_REINTERPRET_CAST(ClusterEntry*, aHashEntry); }
ClusterEntry::Destroy(*pool, NS_REINTERPRET_CAST(ClusterEntry*, aHashEntry)); }
/**
* Maps a MemoryElement to the nsTemplateMatch objects that it
* supports. This map allows us to efficiently remove rules from
* the conflict set when a MemoryElement is removed.
* supports. This map allows us to efficiently remove matches from
* the conflict set when a MemoryElement is removed. Conceptually,
* a support element is what ``owns'' the match.
*/
PLHashTable* mSupport;
class SupportEntry {
public:
static void* operator new(size_t aSize, nsFixedSizeAllocator& aAllocator) {
return aAllocator.Alloc(aSize); }
static void operator delete(void* aPtr, size_t aSize) {
nsFixedSizeAllocator::Free(aPtr, aSize); }
private:
// Hide so that only Create() and Destroy() can be used to
// allocate and deallocate from the heap
static void* operator new(size_t) { return 0; }
static void operator delete(void*, size_t) {}
protected:
SupportEntry() : mElement(nsnull)
{ MOZ_COUNT_CTOR(nsConflictSet::SupportEntry); }
@ -174,9 +282,18 @@ protected:
delete mElement;
MOZ_COUNT_DTOR(nsConflictSet::SupportEntry); }
PLHashEntry mHashEntry;
MemoryElement* mElement;
nsTemplateMatchSet mMatchSet;
public:
static SupportEntry*
Create(nsFixedSizeAllocator& aPool) {
void* place = aPool.Alloc(sizeof(SupportEntry));
return place ? ::new (place) SupportEntry() : nsnull; }
static void
Destroy(nsFixedSizeAllocator& aPool, SupportEntry* aEntry);
PLHashEntry mHashEntry;
MemoryElement* mElement;
nsTemplateMatchRefSet mMatchSet;
};
static PLHashAllocOps gSupportAllocOps;
@ -190,7 +307,7 @@ protected:
static PLHashEntry* PR_CALLBACK AllocSupportEntry(void* aPool, const void* aKey) {
nsFixedSizeAllocator* pool = NS_STATIC_CAST(nsFixedSizeAllocator*, aPool);
SupportEntry* entry = new (*pool) SupportEntry();
SupportEntry* entry = SupportEntry::Create(*pool);
if (! entry)
return nsnull;
@ -200,8 +317,9 @@ protected:
return NS_REINTERPRET_CAST(PLHashEntry*, entry); }
static void PR_CALLBACK FreeSupportEntry(void* aPool, PLHashEntry* aHashEntry, PRUintn aFlag) {
nsFixedSizeAllocator* pool = NS_STATIC_CAST(nsFixedSizeAllocator*, aPool);
if (aFlag == HT_FREE_ENTRY)
delete NS_REINTERPRET_CAST(SupportEntry*, aHashEntry); }
SupportEntry::Destroy(*pool, NS_REINTERPRET_CAST(SupportEntry*, aHashEntry)); }
static PLHashNumber PR_CALLBACK HashMemoryElement(const void* aBinding);
static PRIntn PR_CALLBACK CompareMemoryElements(const void* aLeft, const void* aRight);
@ -215,21 +333,31 @@ protected:
PLHashTable* mBindingDependencies;
class BindingEntry {
protected:
// Hide so that only Create() and Destroy() can be used to
// allocate and deallocate from the heap
static void* operator new(size_t) { return 0; }
static void operator delete(void*, size_t) {}
public:
static void* operator new(size_t aSize, nsFixedSizeAllocator& aAllocator) {
return aAllocator.Alloc(aSize); }
static void operator delete(void* aPtr, size_t aSize) {
nsFixedSizeAllocator::Free(aPtr, aSize); }
BindingEntry()
{ MOZ_COUNT_CTOR(nsConflictSet::BindingEntry); }
~BindingEntry()
{ MOZ_COUNT_DTOR(nsConflictSet::BindingEntry); }
PLHashEntry mHashEntry;
nsTemplateMatchSet mMatchSet;
static BindingEntry*
Create(nsFixedSizeAllocator& aPool) {
void* place = aPool.Alloc(sizeof(BindingEntry));
return place ? ::new (place) BindingEntry() : nsnull; }
static void
Destroy(nsFixedSizeAllocator& aPool, BindingEntry* aEntry) {
aEntry->~BindingEntry();
aPool.Free(aEntry, sizeof(*aEntry)); }
PLHashEntry mHashEntry;
nsTemplateMatchRefSet mMatchSet;
};
static PLHashAllocOps gBindingAllocOps;
@ -243,7 +371,7 @@ protected:
static PLHashEntry* PR_CALLBACK AllocBindingEntry(void* aPool, const void* aKey) {
nsFixedSizeAllocator* pool = NS_STATIC_CAST(nsFixedSizeAllocator*, aPool);
BindingEntry* entry = new (*pool) BindingEntry();
BindingEntry* entry = BindingEntry::Create(*pool);
if (! entry)
return nsnull;
@ -256,7 +384,8 @@ protected:
if (aFlag == HT_FREE_ENTRY) {
nsIRDFResource* key = NS_STATIC_CAST(nsIRDFResource*, NS_CONST_CAST(void*, aHashEntry->key));
NS_RELEASE(key);
delete NS_REINTERPRET_CAST(BindingEntry*, aHashEntry);
nsFixedSizeAllocator* pool = NS_STATIC_CAST(nsFixedSizeAllocator*, aPool);
BindingEntry::Destroy(*pool, NS_REINTERPRET_CAST(BindingEntry*, aHashEntry));
} }
static PLHashNumber PR_CALLBACK HashBindingElement(const void* aSupport) {

View File

@ -24,58 +24,39 @@
#include "nsContentSupportMap.h"
#include "nsIXULContent.h"
PLHashAllocOps nsContentSupportMap::gAllocOps = {
AllocTable, FreeTable, AllocEntry, FreeEntry };
PLDHashTableOps nsContentSupportMap::gOps = {
PL_DHashAllocTable,
PL_DHashFreeTable,
PL_DHashGetKeyStub,
PL_DHashVoidPtrKeyStub,
PL_DHashMatchEntryStub,
PL_DHashMoveEntryStub,
ClearEntry,
PL_DHashFinalizeStub
};
void PR_CALLBACK
nsContentSupportMap::ClearEntry(PLDHashTable* aTable, PLDHashEntryHdr* aHdr)
{
PL_DHashClearEntryStub(aTable, aHdr);
}
void
nsContentSupportMap::Init()
{
static const size_t kBucketSizes[] = { sizeof(Entry) };
static const PRInt32 kNumBuckets = sizeof(kBucketSizes) / sizeof(size_t);
// Per news://news.mozilla.org/39BEC105.5090206%40netscape.com
static const PRInt32 kInitialSize = 256;
mPool.Init("nsContentSupportMap", kBucketSizes, kNumBuckets, kInitialSize);
static const PRInt32 kInitialEntries = 8; // XXX arbitrary
mMap = PL_NewHashTable(kInitialEntries,
HashPointer,
PL_CompareValues,
PL_CompareValues,
&gAllocOps,
&mPool);
PL_DHashTableInit(&mMap, &gOps, nsnull, sizeof(Entry), PL_DHASH_MIN_SIZE);
}
void
nsContentSupportMap::Finish()
{
PL_HashTableDestroy(mMap);
PL_DHashTableFinish(&mMap);
}
nsresult
nsContentSupportMap::Put(nsIContent* aElement, nsTemplateMatch* aMatch)
{
PLHashEntry* he = PL_HashTableAdd(mMap, aElement, nsnull);
if (! he)
return NS_ERROR_OUT_OF_MEMORY;
// "Fix up" the entry's value to refer to the mMatch that's built
// in to the Entry object.
Entry* entry = NS_REINTERPRET_CAST(Entry*, he);
entry->mHashEntry.value = &entry->mMatch;
entry->mMatch = aMatch;
aMatch->AddRef();
return NS_OK;
}
nsresult
nsContentSupportMap::Remove(nsIContent* aElement)
{
PL_HashTableRemove(mMap, aElement);
PL_DHashTableOperate(&mMap, aElement, PL_DHASH_REMOVE);
PRInt32 count;
@ -101,13 +82,3 @@ nsContentSupportMap::Remove(nsIContent* aElement)
}
PRBool
nsContentSupportMap::Get(nsIContent* aElement, nsTemplateMatch** aMatch)
{
nsTemplateMatch** match = NS_STATIC_CAST(nsTemplateMatch**, PL_HashTableLookup(mMap, aElement));
if (! match)
return PR_FALSE;
*aMatch = *match;
return PR_TRUE;
}

View File

@ -24,7 +24,7 @@
#ifndef nsContentSupportMap_h__
#define nsContentSupportMap_h__
#include "plhash.h"
#include "pldhash.h"
#include "nsFixedSizeAllocator.h"
#include "nsTemplateMatch.h"
@ -43,57 +43,46 @@ public:
nsContentSupportMap() { Init(); }
~nsContentSupportMap() { Finish(); }
nsresult Put(nsIContent* aElement, nsTemplateMatch* aMatch);
PRBool Get(nsIContent* aElement, nsTemplateMatch** aMatch);
nsresult Put(nsIContent* aElement, nsTemplateMatch* aMatch) {
PLDHashEntryHdr* hdr = PL_DHashTableOperate(&mMap, aElement, PL_DHASH_ADD);
if (!hdr)
return NS_ERROR_OUT_OF_MEMORY;
Entry* entry = NS_REINTERPRET_CAST(Entry*, hdr);
NS_ASSERTION(entry->mMatch == nsnull, "over-writing entry");
entry->mContent = aElement;
entry->mMatch = aMatch;
return NS_OK; }
PRBool Get(nsIContent* aElement, nsTemplateMatch** aMatch) {
PLDHashEntryHdr* hdr = PL_DHashTableOperate(&mMap, aElement, PL_DHASH_LOOKUP);
if (PL_DHASH_ENTRY_IS_FREE(hdr))
return PR_FALSE;
Entry* entry = NS_REINTERPRET_CAST(Entry*, hdr);
*aMatch = entry->mMatch;
return PR_TRUE; }
nsresult Remove(nsIContent* aElement);
void Clear() { Finish(); Init(); }
protected:
PLHashTable* mMap;
nsFixedSizeAllocator mPool;
PLDHashTable mMap;
void Init();
void Finish();
struct Entry {
PLHashEntry mHashEntry;
PLDHashEntryHdr mHdr;
nsIContent* mContent;
nsTemplateMatch* mMatch;
};
static PLHashAllocOps gAllocOps;
static void* PR_CALLBACK
AllocTable(void* aPool, PRSize aSize) {
return new char[aSize]; };
static PLDHashTableOps gOps;
static void PR_CALLBACK
FreeTable(void* aPool, void* aItem) {
delete[] NS_STATIC_CAST(char*, aItem); }
static PLHashEntry* PR_CALLBACK
AllocEntry(void* aPool, const void* aKey) {
nsFixedSizeAllocator* pool = NS_STATIC_CAST(nsFixedSizeAllocator*, aPool);
Entry* entry = NS_STATIC_CAST(Entry*, pool->Alloc(sizeof(Entry)));
if (! entry)
return nsnull;
return NS_REINTERPRET_CAST(PLHashEntry*, entry); }
static void PR_CALLBACK
FreeEntry(void* aPool, PLHashEntry* aEntry, PRUintn aFlag) {
if (aFlag == HT_FREE_ENTRY) {
Entry* entry = NS_REINTERPRET_CAST(Entry*, aEntry);
if (entry->mMatch)
entry->mMatch->Release();
nsFixedSizeAllocator::Free(entry, sizeof(Entry));
} }
static PLHashNumber PR_CALLBACK
HashPointer(const void* aKey) {
return PLHashNumber(aKey) >> 3; }
ClearEntry(PLDHashTable* aTable, PLDHashEntryHdr* aHdr);
};
#endif

View File

@ -131,8 +131,9 @@ nsContentTestNode::FilterInstantiations(InstantiationSet& aInstantiations, void*
}
if (consistent) {
Element* element = new (mConflictSet.GetPool())
Element(VALUE_TO_ICONTENT(contentValue));
Element* element =
Element::Create(mConflictSet.GetPool(),
VALUE_TO_ICONTENT(contentValue));
if (! element)
return NS_ERROR_OUT_OF_MEMORY;
@ -166,8 +167,8 @@ nsContentTestNode::FilterInstantiations(InstantiationSet& aInstantiations, void*
Instantiation newinst = *inst;
newinst.AddAssignment(mIdVariable, Value(resource.get()));
Element* element = new (mConflictSet.GetPool())
Element(content);
Element* element =
Element::Create(mConflictSet.GetPool(), content);
if (! element)
return NS_ERROR_OUT_OF_MEMORY;
@ -211,7 +212,8 @@ nsContentTestNode::FilterInstantiations(InstantiationSet& aInstantiations, void*
Instantiation newinst = *inst;
newinst.AddAssignment(mContentVariable, Value(content.get()));
Element* element = new (mConflictSet.GetPool()) Element(content);
Element* element =
Element::Create(mConflictSet.GetPool(), content);
if (! element)
return NS_ERROR_OUT_OF_MEMORY;

View File

@ -47,19 +47,29 @@ public:
GetAncestorVariables(VariableSet& aVariables) const;
class Element : public MemoryElement {
private:
// Hide so that only Create() and Destroy() can be used to
// allocate and deallocate from the heap
static void* operator new(size_t) { return 0; }
static void operator delete(void*, size_t) {}
public:
static void* operator new(size_t aSize, nsFixedSizeAllocator& aAllocator) {
return aAllocator.Alloc(aSize); }
static void operator delete(void* aPtr, size_t aSize) {
nsFixedSizeAllocator::Free(aPtr, aSize); }
Element(nsIContent* aContent)
: mContent(aContent) {
MOZ_COUNT_CTOR(nsContentTestNode::Element); }
virtual ~Element() { MOZ_COUNT_DTOR(nsContentTestNode::Element); }
static Element*
Create(nsFixedSizeAllocator& aPool, nsIContent* aContent) {
void* place = aPool.Alloc(sizeof(Element));
return place ? ::new (place) Element(aContent) : nsnull; }
static void
Destroy(nsFixedSizeAllocator& aPool, Element* aElement) {
aElement->~Element();
aPool.Free(aElement, sizeof(*aElement)); }
virtual const char* Type() const {
return "nsContentTestNode::Element"; }
@ -74,8 +84,7 @@ public:
return PR_FALSE; }
virtual MemoryElement* Clone(void* aPool) const {
return new (*NS_STATIC_CAST(nsFixedSizeAllocator*, aPool))
Element(mContent); }
return Create(*NS_STATIC_CAST(nsFixedSizeAllocator*, aPool), mContent); }
protected:
nsCOMPtr<nsIContent> mContent;

View File

@ -62,17 +62,22 @@ nsInstantiationNode::Propogate(const InstantiationSet& aInstantiations, void* aC
for (InstantiationSet::ConstIterator inst = aInstantiations.First(); inst != last; ++inst) {
nsAssignmentSet assignments = inst->mAssignments;
nsTemplateMatch* match = new (mConflictSet.GetPool()) nsTemplateMatch(mRule, *inst, assignments);
nsTemplateMatch* match =
nsTemplateMatch::Create(mConflictSet.GetPool(), mRule, *inst, assignments);
if (! match)
return NS_ERROR_OUT_OF_MEMORY;
// Temporarily AddRef() to keep the match alive.
match->AddRef();
mRule->InitBindings(mConflictSet, match);
mConflictSet.Add(match);
// Give back our "local" reference. The conflict set will have
// taken what it needs.
match->Release();
match->Release(mConflictSet.GetPool());
newkeys->Add(nsClusterKey(*inst, mRule));
}

View File

@ -75,8 +75,8 @@ nsOutlinerRowTestNode::FilterInstantiations(InstantiationSet& aInstantiations, v
(mRows.Find(mConflictSet, container) != mRows.Last())) {
PR_LOG(gXULTemplateLog, PR_LOG_DEBUG, (" => passed"));
Element* element = new (mConflictSet.GetPool())
Element(container);
Element* element =
Element::Create(mConflictSet.GetPool(), container);
if (! element)
return NS_ERROR_OUT_OF_MEMORY;

View File

@ -47,19 +47,29 @@ public:
GetAncestorVariables(VariableSet& aVariables) const;
class Element : public MemoryElement {
protected:
// Hide so that only Create() and Destroy() can be used to
// allocate and deallocate from the heap
static void* operator new(size_t) { return 0; }
static void operator delete(void*, size_t) { }
public:
static void* operator new(size_t aSize, nsFixedSizeAllocator& aAllocator) {
return aAllocator.Alloc(aSize); }
static void operator delete(void* aPtr, size_t aSize) {
nsFixedSizeAllocator::Free(aPtr, aSize); }
Element(nsIRDFResource* aResource)
: mResource(aResource) {
MOZ_COUNT_CTOR(nsOutlinerRowTestNode::Element); }
virtual ~Element() { MOZ_COUNT_DTOR(nsOutlinerRowTestNode::Element); }
static Element*
Create(nsFixedSizeAllocator& aPool, nsIRDFResource* aResource) {
void* place = aPool.Alloc(sizeof(Element));
return place ? ::new (place) Element(aResource) : nsnull; }
static void
Destroy(nsFixedSizeAllocator& aPool, Element* aElement) {
aElement->~Element();
aPool.Free(aElement, sizeof(*aElement)); }
virtual const char* Type() const {
return "nsOutlinerRowTestNode::Element"; }
@ -74,8 +84,7 @@ public:
return PR_FALSE; }
virtual MemoryElement* Clone(void* aPool) const {
return new (*NS_STATIC_CAST(nsFixedSizeAllocator*, aPool))
Element(mResource); }
return Create(*NS_STATIC_CAST(nsFixedSizeAllocator*, aPool), mResource); }
protected:
nsCOMPtr<nsIRDFResource> mResource;

View File

@ -172,9 +172,10 @@ nsRDFConInstanceTestNode::FilterInstantiations(InstantiationSet& aInstantiations
(empty == mEmpty) ? "consistent" : "inconsistent"));
if (empty == mEmpty) {
Element* element = new (mConflictSet.GetPool())
Element(VALUE_TO_IRDFRESOURCE(value),
mContainer, mEmpty);
Element* element =
Element::Create(mConflictSet.GetPool(),
VALUE_TO_IRDFRESOURCE(value),
mContainer, mEmpty);
if (! element)
return NS_ERROR_OUT_OF_MEMORY;
@ -233,8 +234,10 @@ nsRDFConInstanceTestNode::FilterInstantiations(InstantiationSet& aInstantiations
(container == mContainer) ? "consistent" : "inconsistent"));
if (container == mContainer) {
Element* element = new (mConflictSet.GetPool())
Element(VALUE_TO_IRDFRESOURCE(value), mContainer, mEmpty);
Element* element =
Element::Create(mConflictSet.GetPool(),
VALUE_TO_IRDFRESOURCE(value),
mContainer, mEmpty);
if (! element)

View File

@ -67,13 +67,13 @@ public:
class Element : public MemoryElement {
protected:
// Hide so that only Create() and Destroy() can be used to
// allocate and deallocate from the heap
static void* operator new(size_t) { return 0; }
static void operator delete(void*, size_t) {}
public:
static void* operator new(size_t aSize, nsFixedSizeAllocator& aAllocator) {
return aAllocator.Alloc(aSize); }
static void operator delete(void* aPtr, size_t aSize) {
nsFixedSizeAllocator::Free(aPtr, aSize); }
Element(nsIRDFResource* aContainer,
Test aContainerTest,
Test aEmptyTest)
@ -84,6 +84,17 @@ public:
virtual ~Element() { MOZ_COUNT_DTOR(nsRDFConInstanceTestNode::Element); }
static Element*
Create(nsFixedSizeAllocator& aPool, nsIRDFResource* aContainer,
Test aContainerTest, Test aEmptyTest) {
void* place = aPool.Alloc(sizeof(Element));
return place ? ::new (place) Element(aContainer, aContainerTest, aEmptyTest) : nsnull; }
static void
Destroy(nsFixedSizeAllocator& aPool, Element* aElement) {
aElement->~Element();
aPool.Free(aElement, sizeof(*aElement)); }
virtual const char* Type() const {
return "nsRDFConInstanceTestNode::Element"; }
@ -102,8 +113,8 @@ public:
return PR_FALSE; }
virtual MemoryElement* Clone(void* aPool) const {
return new (*NS_STATIC_CAST(nsFixedSizeAllocator*, aPool))
Element(mContainer, mContainerTest, mEmptyTest); }
return Create(*NS_STATIC_CAST(nsFixedSizeAllocator*, aPool),
mContainer, mContainerTest, mEmptyTest); }
protected:
nsCOMPtr<nsIRDFResource> mContainer;

View File

@ -183,9 +183,10 @@ nsRDFConMemberTestNode::FilterInstantiations(InstantiationSet& aInstantiations,
if (isconsistent) {
// Add a memory element to our set-of-support.
Element* element = new (mConflictSet.GetPool())
Element(VALUE_TO_IRDFRESOURCE(containerValue),
VALUE_TO_IRDFNODE(memberValue));
Element* element =
Element::Create(mConflictSet.GetPool(),
VALUE_TO_IRDFRESOURCE(containerValue),
VALUE_TO_IRDFNODE(memberValue));
if (! element)
return NS_ERROR_OUT_OF_MEMORY;
@ -238,8 +239,10 @@ nsRDFConMemberTestNode::FilterInstantiations(InstantiationSet& aInstantiations,
Instantiation newinst = *inst;
newinst.AddAssignment(mMemberVariable, Value(node.get()));
Element* element = new (mConflictSet.GetPool())
Element(VALUE_TO_IRDFRESOURCE(containerValue), node);
Element* element =
Element::Create(mConflictSet.GetPool(),
VALUE_TO_IRDFRESOURCE(containerValue),
node);
if (! element)
return NS_ERROR_OUT_OF_MEMORY;
@ -329,8 +332,10 @@ nsRDFConMemberTestNode::FilterInstantiations(InstantiationSet& aInstantiations,
Instantiation newinst = *inst;
newinst.AddAssignment(mContainerVariable, Value(source.get()));
Element* element = new (mConflictSet.GetPool())
Element(source, VALUE_TO_IRDFNODE(memberValue));
Element* element =
Element::Create(mConflictSet.GetPool(),
source,
VALUE_TO_IRDFNODE(memberValue));
if (! element)
return NS_ERROR_OUT_OF_MEMORY;
@ -424,14 +429,14 @@ nsRDFConMemberTestNode::FilterInstantiations(InstantiationSet& aInstantiations,
Element* element;
if (hasContainerBinding) {
element = new (mConflictSet.GetPool())
Element(VALUE_TO_IRDFRESOURCE(containerValue),
VALUE_TO_IRDFNODE(value));
element = Element::Create(mConflictSet.GetPool(),
VALUE_TO_IRDFRESOURCE(containerValue),
VALUE_TO_IRDFNODE(value));
}
else {
element = new (mConflictSet.GetPool())
Element(VALUE_TO_IRDFRESOURCE(value),
VALUE_TO_IRDFNODE(memberValue));
element = Element::Create(mConflictSet.GetPool(),
VALUE_TO_IRDFRESOURCE(value),
VALUE_TO_IRDFNODE(memberValue));
}
if (! element)

View File

@ -63,13 +63,13 @@ public:
nsTemplateMatchSet& aRetractions) const;
class Element : public MemoryElement {
protected:
// Hide so that only Create() and Destroy() can be used to
// allocate and deallocate from the heap
static void* operator new(size_t) { return 0; }
static void operator delete(void*, size_t) {}
public:
static void* operator new(size_t aSize, nsFixedSizeAllocator& aAllocator) {
return aAllocator.Alloc(aSize); }
static void operator delete(void* aPtr, size_t aSize) {
nsFixedSizeAllocator::Free(aPtr, aSize); }
Element(nsIRDFResource* aContainer,
nsIRDFNode* aMember)
: mContainer(aContainer),
@ -78,6 +78,18 @@ public:
virtual ~Element() { MOZ_COUNT_DTOR(nsRDFConMemberTestNode::Element); }
static Element*
Create(nsFixedSizeAllocator& aPool,
nsIRDFResource* aContainer,
nsIRDFNode* aMember) {
void* place = aPool.Alloc(sizeof(Element));
return place ? ::new (place) Element(aContainer, aMember) : nsnull; }
static void
Destroy(nsFixedSizeAllocator& aPool, Element* aElement) {
aElement->~Element();
aPool.Free(aElement, sizeof(*aElement)); }
virtual const char* Type() const {
return "nsRDFConMemberTestNode::Element"; }
@ -93,8 +105,8 @@ public:
return PR_FALSE; }
virtual MemoryElement* Clone(void* aPool) const {
return new (*NS_STATIC_CAST(nsFixedSizeAllocator*, aPool))
Element(mContainer, mMember); }
return Create(*NS_STATIC_CAST(nsFixedSizeAllocator*, aPool),
mContainer, mMember); }
protected:
nsCOMPtr<nsIRDFResource> mContainer;

View File

@ -187,10 +187,11 @@ nsRDFPropertyTestNode::FilterInstantiations(InstantiationSet& aInstantiations, v
if (hasAssertion) {
// it's consistent.
Element* element = new (mConflictSet.GetPool())
Element(VALUE_TO_IRDFRESOURCE(sourceValue),
mProperty,
VALUE_TO_IRDFNODE(targetValue));
Element* element =
Element::Create(mConflictSet.GetPool(),
VALUE_TO_IRDFRESOURCE(sourceValue),
mProperty,
VALUE_TO_IRDFNODE(targetValue));
if (! element)
return NS_ERROR_OUT_OF_MEMORY;
@ -286,10 +287,11 @@ nsRDFPropertyTestNode::FilterInstantiations(InstantiationSet& aInstantiations, v
Instantiation newinst = *inst;
newinst.AddAssignment(variable, value);
Element* element = new (mConflictSet.GetPool())
Element(VALUE_TO_IRDFRESOURCE(sourceValue),
mProperty,
VALUE_TO_IRDFNODE(targetValue));
Element* element =
Element::Create(mConflictSet.GetPool(),
VALUE_TO_IRDFRESOURCE(sourceValue),
mProperty,
VALUE_TO_IRDFNODE(targetValue));
if (! element)
return NS_ERROR_OUT_OF_MEMORY;

View File

@ -82,13 +82,13 @@ public:
class Element : public MemoryElement {
protected:
// Hide so that only Create() and Destroy() can be used to
// allocate and deallocate from the heap
static void* operator new(size_t) { return 0; }
static void operator delete(void*, size_t) {}
public:
static void* operator new(size_t aSize, nsFixedSizeAllocator& aAllocator) {
return aAllocator.Alloc(aSize); }
static void operator delete(void* aPtr, size_t aSize) {
nsFixedSizeAllocator::Free(aPtr, aSize); }
Element(nsIRDFResource* aSource,
nsIRDFResource* aProperty,
nsIRDFNode* aTarget)
@ -99,6 +99,19 @@ public:
virtual ~Element() { MOZ_COUNT_DTOR(nsRDFPropertyTestNode::Element); }
static Element*
Create(nsFixedSizeAllocator& aPool,
nsIRDFResource* aSource,
nsIRDFResource* aProperty,
nsIRDFNode* aTarget) {
void* place = aPool.Alloc(sizeof(Element));
return place ? ::new (place) Element(aSource, aProperty, aTarget) : nsnull; }
static void
Destroy(nsFixedSizeAllocator& aPool, Element* aElement) {
aElement->~Element();
aPool.Free(aElement, sizeof(*aElement)); }
virtual const char* Type() const {
return "nsRDFPropertyTestNode::Element"; }
@ -117,8 +130,8 @@ public:
return PR_FALSE; }
virtual MemoryElement* Clone(void* aPool) const {
return new (*NS_STATIC_CAST(nsFixedSizeAllocator*, aPool))
Element(mSource, mProperty, mTarget); }
return Create(*NS_STATIC_CAST(nsFixedSizeAllocator*, aPool),
mSource, mProperty, mTarget); }
protected:
nsCOMPtr<nsIRDFResource> mSource;

View File

@ -79,20 +79,6 @@ ClearEntry(PLDHashTable* aTable, PLDHashEntryHdr* aEntry)
PL_DHashClearEntryStub(aTable, aEntry);
}
static PLDHashOperator PR_CALLBACK
RemoveEach(PLDHashTable* aTable, PLDHashEntryHdr* aEntry, PRUint32 aNumber, void* aArg)
{
return PL_DHASH_REMOVE;
}
static void PR_CALLBACK
FinalizeTable(PLDHashTable* aTable)
{
PL_DHashTableEnumerate(aTable, RemoveEach, nsnull);
PL_DHashFinalizeStub(aTable);
}
PLDHashTableOps nsRuleNetwork::gOps = {
PL_DHashAllocTable,
PL_DHashFreeTable,
@ -101,7 +87,7 @@ PLDHashTableOps nsRuleNetwork::gOps = {
MatchEntry,
PL_DHashMoveEntryStub,
ClearEntry,
FinalizeTable
PL_DHashFinalizeStub
};
void

View File

@ -27,6 +27,7 @@
#include "nsFixedSizeAllocator.h"
#include "nsResourceSet.h"
#include "nsRuleNetwork.h"
#include <new>
/**
* A "match" is a fully instantiated rule; that is, a complete and
@ -42,24 +43,36 @@ class nsConflictSet;
class nsTemplateRule;
class nsTemplateMatch {
private:
// Hide so that only Create() and Destroy() can be used to
// allocate and deallocate from the heap
void* operator new(size_t) { return 0; }
void operator delete(void*, size_t) {}
protected:
PRInt32 mRefCnt;
public:
static void* operator new(size_t aSize, nsFixedSizeAllocator& aAllocator) {
return aAllocator.Alloc(aSize); }
static void operator delete(void* aPtr, size_t aSize) {
nsFixedSizeAllocator::Free(aPtr, aSize); }
nsTemplateMatch(const nsTemplateRule* aRule,
const Instantiation& aInstantiation,
const nsAssignmentSet& aAssignments)
: mRefCnt(1),
const Instantiation& aInstantiation,
const nsAssignmentSet& aAssignments)
: mRefCnt(0),
mRule(aRule),
mInstantiation(aInstantiation),
mAssignments(aAssignments)
{ MOZ_COUNT_CTOR(nsTemplateMatch); }
mAssignments(aAssignments) {}
public:
static nsTemplateMatch*
Create(nsFixedSizeAllocator& aPool,
const nsTemplateRule* aRule,
const Instantiation& aInstantiation,
const nsAssignmentSet& aAssignments) {
void* place = aPool.Alloc(sizeof(nsTemplateMatch));
return place ? ::new (place) nsTemplateMatch(aRule, aInstantiation, aAssignments) : nsnull; }
static void
Destroy(nsFixedSizeAllocator& aPool, nsTemplateMatch* aMatch) {
aMatch->~nsTemplateMatch();
aPool.Free(aMatch, sizeof(*aMatch)); }
PRBool operator==(const nsTemplateMatch& aMatch) const {
return mRule == aMatch.mRule && mInstantiation == aMatch.mInstantiation; }
@ -104,17 +117,19 @@ public:
*/
nsResourceSet mBindingDependencies;
PRInt32 AddRef() { return ++mRefCnt; }
PRInt32 AddRef() {
++mRefCnt;
NS_LOG_ADDREF(this, mRefCnt, "nsTemplateMatch", sizeof(*this));
return mRefCnt; }
PRInt32 Release() {
PRInt32 Release(nsFixedSizeAllocator& aPool) {
NS_PRECONDITION(mRefCnt > 0, "bad refcnt");
PRInt32 refcnt = --mRefCnt;
if (refcnt == 0) delete this;
NS_LOG_RELEASE(this, mRefCnt, "nsTemplateMatch");
if (refcnt == 0)
Destroy(aPool, this);
return refcnt; }
protected:
~nsTemplateMatch() { MOZ_COUNT_DTOR(nsTemplateMatch); }
private:
nsTemplateMatch(const nsTemplateMatch& aMatch); // not to be implemented
void operator=(const nsTemplateMatch& aMatch); // not to be implemented

View File

@ -24,174 +24,326 @@
#include "nsTemplateMatchSet.h"
#include "nsTemplateRule.h"
PLHashAllocOps nsTemplateMatchSet::gAllocOps = {
AllocTable, FreeTable, AllocEntry, FreeEntry };
nsTemplateMatchSet::nsTemplateMatchSet()
: mMatches(nsnull), mCount(0), mLastMatch(nsnull)
{
MOZ_COUNT_CTOR(nsTemplateMatchSet);
mHead.mNext = mHead.mPrev = &mHead;
}
#ifdef NEED_CPP_UNUSED_IMPLEMENTATIONS
nsTemplateMatchSet::nsTemplateMatchSet(const nsTemplateMatchSet& aMatchSet) {}
void nsTemplateMatchSet::operator=(const nsTemplateMatchSet& aMatchSet) {}
#ifdef DEBUG_waterson
#define NSTEMPLATEMATCHREFSET_METER // collect stats about match set sizes
#endif
//----------------------------------------------------------------------
//
// nsTemplateMatchSet
//
nsTemplateMatchSet::~nsTemplateMatchSet()
{
if (mMatches) {
PL_HashTableDestroy(mMatches);
mMatches = nsnull;
while (mHead) {
Element* doomed = mHead;
mHead = mHead->mNext;
doomed->mMatch->Release(mPool);
delete doomed;
}
Clear();
MOZ_COUNT_DTOR(nsTemplateMatchSet);
}
//----------------------------------------------------------------------
//
// nsTemplateMatchRefSet
//
nsTemplateMatchSet::Iterator
nsTemplateMatchSet::Insert(nsFixedSizeAllocator& aPool, Iterator aIterator, nsTemplateMatch* aMatch)
PLDHashTableOps nsTemplateMatchRefSet::gOps = {
PL_DHashAllocTable,
PL_DHashFreeTable,
PL_DHashGetKeyStub,
HashEntry,
MatchEntry,
PL_DHashMoveEntryStub,
PL_DHashClearEntryStub,
PL_DHashFinalizeStub
};
PLDHashNumber PR_CALLBACK
nsTemplateMatchRefSet::HashEntry(PLDHashTable* aTable, const void* aKey)
{
if (++mCount > kHashTableThreshold && !mMatches) {
// If we've exceeded a high-water mark, then hash everything.
mMatches = PL_NewHashTable(2 * kHashTableThreshold,
HashMatch,
CompareMatches,
PL_CompareValues,
&gAllocOps,
&aPool);
Iterator last = Last();
for (Iterator match = First(); match != last; ++match) {
// The sole purpose of the hashtable is to make
// determining nsTemplateMatchSet membership an O(1)
// operation. Since the linked list is maintaining
// storage, we can use a pointer to the nsTemplateMatch object
// (obtained from the iterator) as the key. We'll just
// stuff something non-zero into the table as a value.
PL_HashTableAdd(mMatches, match.operator->(), match.mCurrent);
}
}
List* newelement = new (aPool) List();
if (newelement) {
newelement->mMatch = aMatch;
aMatch->AddRef();
aIterator.mCurrent->mPrev->mNext = newelement;
newelement->mNext = aIterator.mCurrent;
newelement->mPrev = aIterator.mCurrent->mPrev;
aIterator.mCurrent->mPrev = newelement;
if (mMatches)
PL_HashTableAdd(mMatches, newelement->mMatch, newelement);
}
return aIterator;
const nsTemplateMatch* match = NS_STATIC_CAST(const nsTemplateMatch*, aKey);
return PLDHashNumber(Instantiation::Hash(&(match->mInstantiation)))
^ (PLDHashNumber(match->mRule) >> 2);
}
nsresult
nsTemplateMatchSet::CopyInto(nsTemplateMatchSet& aMatchSet, nsFixedSizeAllocator& aPool) const
PRBool PR_CALLBACK
nsTemplateMatchRefSet::MatchEntry(PLDHashTable* aTable, const PLDHashEntryHdr* aHdr, const void* aKey)
{
aMatchSet.Clear();
for (nsTemplateMatchSet::ConstIterator match = First(); match != Last(); ++match)
aMatchSet.Add(aPool, NS_CONST_CAST(nsTemplateMatch*, match.operator->()));
const Entry* entry = NS_REINTERPRET_CAST(const Entry*, aHdr);
const nsTemplateMatch* left = entry->mMatch;
const nsTemplateMatch* right = NS_STATIC_CAST(const nsTemplateMatch*, aKey);
return *left == *right;
}
return NS_OK;
#ifdef NSTEMPLATEMATCHREFSET_METER
#include "nsVoidArray.h"
static PRInt32 gCount;
static nsVoidArray gCountDistribution;
#endif
void
nsTemplateMatchRefSet::Init()
{
#ifdef NSTEMPLATEMATCHREFSET_METER
++gCount;
#endif
mInlineMatches.mCount = 0;
}
void
nsTemplateMatchSet::Clear()
nsTemplateMatchRefSet::Finish()
{
Iterator match = First();
while (match != Last())
Erase(match++);
}
#ifdef NSTEMPLATEMATCHREFSET_METER
{
PRInt32 entries = mInlineMatches.mCount <= kMaxInlineMatches
? PRInt32(mInlineMatches.mCount)
: mTable.entryCount;
nsTemplateMatchSet::ConstIterator
nsTemplateMatchSet::Find(const nsTemplateMatch& aMatch) const
{
if (mMatches) {
List* list = NS_STATIC_CAST(List*, PL_HashTableLookup(mMatches, &aMatch));
if (list)
return ConstIterator(list);
}
else {
ConstIterator last = Last();
for (ConstIterator i = First(); i != last; ++i) {
if (*i == aMatch)
return i;
PRInt32 count = PRInt32(gCountDistribution[entries]);
gCountDistribution.ReplaceElementAt((void*) ++count, entries);
--gCount;
if (gCount == 0) {
printf("nsTemplateMatchRefSet distribution\n");
for (PRInt32 i = gCountDistribution.Count() - 1; i >= 0; --i)
printf("%d: %d\n", i, gCountDistribution[i]);
}
}
#endif
return Last();
}
if (mInlineMatches.mCount > kMaxInlineMatches)
// It's a hashtable, so finish the table properly
PL_DHashTableFinish(&mTable);
nsTemplateMatchSet::Iterator
nsTemplateMatchSet::Find(const nsTemplateMatch& aMatch)
{
if (mMatches) {
List* list = NS_STATIC_CAST(List*, PL_HashTableLookup(mMatches, &aMatch));
if (list)
return Iterator(list);
}
else {
Iterator last = Last();
for (Iterator i = First(); i != last; ++i) {
if (*i == aMatch)
return i;
}
}
return Last();
}
nsTemplateMatch*
nsTemplateMatchSet::FindMatchWithHighestPriority() const
{
// Find the rule with the "highest priority"; i.e., the rule with
// the lowest value for GetPriority().
nsTemplateMatch* result = nsnull;
PRInt32 max = ~(1 << 31); // XXXwaterson portable?
for (ConstIterator match = First(); match != Last(); ++match) {
PRInt32 priority = match->mRule->GetPriority();
if (priority < max) {
result = NS_CONST_CAST(nsTemplateMatch*, match.operator->());
max = priority;
}
}
return result;
}
nsTemplateMatchSet::Iterator
nsTemplateMatchSet::Erase(Iterator aIterator)
{
Iterator result = aIterator;
--mCount;
if (mMatches)
PL_HashTableRemove(mMatches, aIterator.operator->());
++result;
aIterator.mCurrent->mNext->mPrev = aIterator.mCurrent->mPrev;
aIterator.mCurrent->mPrev->mNext = aIterator.mCurrent->mNext;
aIterator->Release();
delete aIterator.mCurrent;
return result;
mInlineMatches.mCount = 0;
}
void
nsTemplateMatchSet::Remove(nsTemplateMatch* aMatch)
nsTemplateMatchRefSet::CopyFrom(const nsTemplateMatchRefSet& aSet)
{
Iterator doomed = Find(*aMatch);
if (doomed != Last())
Erase(doomed);
ConstIterator last = aSet.Last();
for (ConstIterator iter = aSet.First(); iter != last; ++iter)
Add(iter.operator->());
}
PRBool
nsTemplateMatchRefSet::Empty() const
{
PRUint32 count = mInlineMatches.mCount;
if (count <= kMaxInlineMatches)
return count == 0;
return mTable.entryCount == 0;
}
PRBool
nsTemplateMatchRefSet::Contains(const nsTemplateMatch* aMatch) const
{
PRUint32 count = mInlineMatches.mCount;
if (count <= kMaxInlineMatches) {
while (PRInt32(--count) >= 0) {
if (*(mInlineMatches.mEntries[count]) == *aMatch)
return PR_TRUE;
}
return PR_FALSE;
}
PLDHashEntryHdr* hdr =
PL_DHashTableOperate(NS_CONST_CAST(PLDHashTable*, &mTable), aMatch,
PL_DHASH_LOOKUP);
return PL_DHASH_ENTRY_IS_BUSY(hdr);
}
PRBool
nsTemplateMatchRefSet::Add(const nsTemplateMatch* aMatch)
{
// Cast away const, we assume shared ownership.
nsTemplateMatch* match = NS_CONST_CAST(nsTemplateMatch*, aMatch);
PRUint32 count = mInlineMatches.mCount;
if (count < kMaxInlineMatches) {
// There's still room in the inline matches.
// Check for duplicates
for (PRInt32 i = PRInt32(count) - 1; i >= 0; --i) {
if (*(mInlineMatches.mEntries[i]) == *aMatch)
return PR_FALSE;
}
// Nope. Add it!
mInlineMatches.mEntries[count] = match;
++mInlineMatches.mCount;
return PR_TRUE;
}
if (count == kMaxInlineMatches) {
// No room left in inline matches. Fault, and convert to
// hashtable.
nsTemplateMatch* temp[kMaxInlineMatches];
PRInt32 i;
// Copy pointers to a safe place
for (i = count - 1; i >= 0; --i)
temp[i] = mInlineMatches.mEntries[i];
// Clobber the union; we'll treat it as a hashtable now.
PL_DHashTableInit(&mTable, &gOps, nsnull, sizeof(Entry), PL_DHASH_MIN_SIZE);
// Now that we've table-ized this thing, mCount better be a
// big freaking number, since it's sharing space with a
// pointer to the PLDHashTable's ops.
NS_ASSERTION(mInlineMatches.mCount > kMaxInlineMatches,
"wow, I thought it'd be bigger than _that_");
// Copy the pointers into the hashtable.
for (i = count - 1; i >= 0; --i)
AddToTable(temp[i]);
}
return AddToTable(match);
}
PRBool
nsTemplateMatchRefSet::AddToTable(nsTemplateMatch* aMatch)
{
PLDHashEntryHdr* hdr =
PL_DHashTableOperate(&mTable, aMatch, PL_DHASH_ADD);
if (hdr) {
Entry* entry = NS_REINTERPRET_CAST(Entry*, hdr);
if (! entry->mMatch) {
entry->mMatch = aMatch;
return PR_TRUE;
}
}
return PR_FALSE;
}
PRBool
nsTemplateMatchRefSet::Remove(const nsTemplateMatch* aMatch)
{
PRBool found = PR_FALSE;
PRUint32 count = mInlineMatches.mCount;
if (count <= kMaxInlineMatches) {
nsTemplateMatch** last;
for (PRUint32 i = 0; i < count; ++i) {
nsTemplateMatch** entry = &mInlineMatches.mEntries[i];
nsTemplateMatch* match = *entry;
if (*match == *aMatch) {
found = PR_TRUE;
}
else if (found)
*last = match;
last = entry;
}
if (found)
--mInlineMatches.mCount;
}
else {
PLDHashEntryHdr* hdr =
PL_DHashTableOperate(&mTable, aMatch, PL_DHASH_LOOKUP);
found = PL_DHASH_ENTRY_IS_BUSY(hdr);
if (found)
// Remove the match. N.B., we never demote back to a list.
PL_DHashTableOperate(&mTable, aMatch, PL_DHASH_REMOVE);
}
return found;
}
//----------------------------------------------------------------------
//
// ConstIterator
//
#define ENTRY_IS_LIVE(entry) (PL_DHASH_ENTRY_IS_BUSY(&((entry)->mHdr)) && (entry)->mMatch)
nsTemplateMatchRefSet::ConstIterator
nsTemplateMatchRefSet::First() const
{
if (mInlineMatches.mCount <= kMaxInlineMatches)
return ConstIterator(this, NS_CONST_CAST(nsTemplateMatch**, mInlineMatches.mEntries));
Entry* entry = NS_REINTERPRET_CAST(Entry*, mTable.entryStore);
Entry* limit = entry + PR_BIT(mTable.sizeLog2);
for ( ; entry < limit; ++entry) {
if (ENTRY_IS_LIVE(entry))
break;
}
return ConstIterator(this, entry);
}
nsTemplateMatchRefSet::ConstIterator
nsTemplateMatchRefSet::Last() const
{
PRUint32 count = mInlineMatches.mCount;
if (count <= kMaxInlineMatches) {
nsTemplateMatch** first = NS_CONST_CAST(nsTemplateMatch**, mInlineMatches.mEntries);
nsTemplateMatch** limit = first + count;
return ConstIterator(this, limit);
}
Entry* limit = NS_REINTERPRET_CAST(Entry*, mTable.entryStore);
limit += PR_BIT(mTable.sizeLog2);
return ConstIterator(this, limit);
}
void
nsTemplateMatchRefSet::ConstIterator::Next()
{
if (mSet->mInlineMatches.mCount <= kMaxInlineMatches)
++mInlineEntry;
else {
const PLDHashTable& table = mSet->mTable;
Entry* limit = NS_REINTERPRET_CAST(Entry*, table.entryStore);
limit += PR_BIT(table.sizeLog2);
while (++mTableEntry < limit) {
if (ENTRY_IS_LIVE(mTableEntry))
break;
}
}
}
void
nsTemplateMatchRefSet::ConstIterator::Prev()
{
if (mSet->mInlineMatches.mCount <= kMaxInlineMatches)
--mInlineEntry;
else {
const PLDHashTable& table = mSet->mTable;
Entry* limit = NS_REINTERPRET_CAST(Entry*, table.entryStore);
while (--mTableEntry > limit) {
if (ENTRY_IS_LIVE(mTableEntry))
break;
}
}
}
PRBool
nsTemplateMatchRefSet::ConstIterator::operator==(const ConstIterator& aConstIterator) const
{
if (mSet != aConstIterator.mSet)
return PR_FALSE;
PRUint32 count = mSet->mInlineMatches.mCount;
if (count <= kMaxInlineMatches)
return mInlineEntry == aConstIterator.mInlineEntry;
return mTableEntry == aConstIterator.mTableEntry;
}

View File

@ -27,204 +27,306 @@
#include "nsRuleNetwork.h"
#include "nsFixedSizeAllocator.h"
#include "nsTemplateMatch.h"
#include "plhash.h"
#include "pldhash.h"
/**
* A collection of unique nsTemplateMatch objects.
*/
class nsTemplateMatchSet
{
class nsTemplateMatchSet {
public:
class ConstIterator;
friend class ConstIterator;
class Iterator;
friend class Iterator;
nsTemplateMatchSet();
~nsTemplateMatchSet();
private:
nsTemplateMatchSet(const nsTemplateMatchSet& aMatchSet); // XXX not to be implemented
void operator=(const nsTemplateMatchSet& aMatchSet); // XXX not to be implemented
friend class ConstIterator; // so it can see Element
protected:
struct List {
static void* operator new(size_t aSize, nsFixedSizeAllocator& aPool) {
return aPool.Alloc(aSize); }
static void operator delete(void* aPtr, size_t aSize) {
nsFixedSizeAllocator::Free(aPtr, aSize); }
class Element {
public:
Element(nsTemplateMatch* aMatch)
: mMatch(aMatch), mNext(nsnull) {}
nsTemplateMatch* mMatch;
List* mNext;
List* mPrev;
Element* mNext;
};
List mHead;
// Lazily created when we pass a size threshold.
PLHashTable* mMatches;
PRInt32 mCount;
const nsTemplateMatch* mLastMatch;
static PLHashNumber PR_CALLBACK HashMatch(const void* aMatch) {
const nsTemplateMatch* match = NS_STATIC_CAST(const nsTemplateMatch*, aMatch);
return Instantiation::Hash(&match->mInstantiation) ^ (PLHashNumber(match->mRule) >> 2); }
static PRIntn PR_CALLBACK CompareMatches(const void* aLeft, const void* aRight) {
const nsTemplateMatch* left = NS_STATIC_CAST(const nsTemplateMatch*, aLeft);
const nsTemplateMatch* right = NS_STATIC_CAST(const nsTemplateMatch*, aRight);
return *left == *right; }
enum { kHashTableThreshold = 8 };
static PLHashAllocOps gAllocOps;
static void* PR_CALLBACK AllocTable(void* aPool, PRSize aSize) {
return new char[aSize]; }
static void PR_CALLBACK FreeTable(void* aPool, void* aItem) {
delete[] NS_STATIC_CAST(char*, aItem); }
static PLHashEntry* PR_CALLBACK AllocEntry(void* aPool, const void* aKey) {
nsFixedSizeAllocator* pool = NS_STATIC_CAST(nsFixedSizeAllocator*, aPool);
PLHashEntry* entry = NS_STATIC_CAST(PLHashEntry*, pool->Alloc(sizeof(PLHashEntry)));
return entry; }
static void PR_CALLBACK FreeEntry(void* aPool, PLHashEntry* aEntry, PRUintn aFlag) {
if (aFlag == HT_FREE_ENTRY)
nsFixedSizeAllocator::Free(aEntry, sizeof(PLHashEntry)); }
nsFixedSizeAllocator& mPool;
Element* mHead;
public:
// Used to initialize the nsFixedSizeAllocator that's used to pool
// entries.
enum {
kEntrySize = sizeof(List),
kIndexSize = sizeof(PLHashEntry)
};
nsTemplateMatchSet(nsFixedSizeAllocator& aPool)
: mPool(aPool), mHead(nsnull) { MOZ_COUNT_CTOR(nsTemplateMatchSet); }
~nsTemplateMatchSet();
class ConstIterator {
protected:
friend class Iterator; // XXXwaterson so broken.
List* mCurrent;
friend class nsTemplateMatchSet;
Element* mCurrent;
ConstIterator(Element* aElement)
: mCurrent(aElement) {}
public:
ConstIterator() : mCurrent(nsnull) {}
ConstIterator(List* aCurrent) : mCurrent(aCurrent) {}
ConstIterator(const ConstIterator& aIterator)
: mCurrent(aIterator.mCurrent) {}
ConstIterator(const ConstIterator& aConstIterator)
: mCurrent(aConstIterator.mCurrent) {}
ConstIterator& operator=(const ConstIterator& aConstIterator) {
mCurrent = aConstIterator.mCurrent;
ConstIterator&
operator=(const ConstIterator& aIterator) {
mCurrent = aIterator.mCurrent;
return *this; }
ConstIterator& operator++() {
ConstIterator&
operator++() {
mCurrent = mCurrent->mNext;
return *this; }
return *this; };
ConstIterator operator++(int) {
ConstIterator result(*this);
ConstIterator
operator++(int) {
ConstIterator tmp(*this);
mCurrent = mCurrent->mNext;
return result; }
ConstIterator& operator--() {
mCurrent = mCurrent->mPrev;
return *this; }
ConstIterator operator--(int) {
ConstIterator result(*this);
mCurrent = mCurrent->mPrev;
return result; }
const nsTemplateMatch& operator*() const {
return *mCurrent->mMatch; }
const nsTemplateMatch* operator->() const {
return mCurrent->mMatch; }
PRBool operator==(const ConstIterator& aConstIterator) const {
return mCurrent == aConstIterator.mCurrent; }
PRBool operator!=(const ConstIterator& aConstIterator) const {
return mCurrent != aConstIterator.mCurrent; }
};
ConstIterator First() const { return ConstIterator(mHead.mNext); }
ConstIterator Last() const { return ConstIterator(NS_CONST_CAST(List*, &mHead)); }
class Iterator : public ConstIterator {
public:
Iterator() {}
Iterator(List* aCurrent) : ConstIterator(aCurrent) {}
Iterator& operator++() {
mCurrent = mCurrent->mNext;
return *this; }
Iterator operator++(int) {
Iterator result(*this);
mCurrent = mCurrent->mNext;
return result; }
Iterator& operator--() {
mCurrent = mCurrent->mPrev;
return *this; }
Iterator operator--(int) {
Iterator result(*this);
mCurrent = mCurrent->mPrev;
return result; }
return tmp; }
nsTemplateMatch& operator*() const {
return *mCurrent->mMatch; }
return *(mCurrent->mMatch); }
nsTemplateMatch* operator->() const {
return mCurrent->mMatch; }
PRBool operator==(const ConstIterator& aConstIterator) const {
return mCurrent == aConstIterator.mCurrent; }
PRBool
operator==(const ConstIterator& aIterator) const {
return mCurrent == aIterator.mCurrent; }
PRBool operator!=(const ConstIterator& aConstIterator) const {
return mCurrent != aConstIterator.mCurrent; }
friend class nsTemplateMatchSet;
PRBool
operator!=(const ConstIterator& aIterator) const {
return !aIterator.operator==(*this); }
};
Iterator First() { return Iterator(mHead.mNext); }
Iterator Last() { return Iterator(&mHead); }
ConstIterator First() const { return ConstIterator(mHead); }
PRBool Empty() const { return First() == Last(); }
ConstIterator Last() const { return ConstIterator(nsnull); }
PRInt32 Count() const { return mCount; }
void
Add(nsTemplateMatch* aMatch) {
Element* element = new Element(aMatch);
if (element) {
aMatch->AddRef();
element->mMatch = aMatch;
element->mNext = mHead;
mHead = element;
} }
};
ConstIterator Find(const nsTemplateMatch& aMatch) const;
Iterator Find(const nsTemplateMatch& aMatch);
/**
* A set of references nsTemplateMatch objects.
*/
class nsTemplateMatchRefSet
{
public:
nsTemplateMatchRefSet() {
MOZ_COUNT_CTOR(nsTemplateMatchRefSet);
Init(); }
PRBool Contains(const nsTemplateMatch& aMatch) const {
return Find(aMatch) != Last(); }
nsTemplateMatchRefSet(const nsTemplateMatchRefSet& aMatchSet) {
MOZ_COUNT_CTOR(nsTemplateMatchRefSet);
Init();
CopyFrom(aMatchSet); }
nsTemplateMatch* FindMatchWithHighestPriority() const;
nsTemplateMatchRefSet&
operator=(const nsTemplateMatchRefSet& aMatchSet) {
Finish();
Init();
CopyFrom(aMatchSet);
return *this; }
const nsTemplateMatch* GetLastMatch() const { return mLastMatch; }
void SetLastMatch(const nsTemplateMatch* aMatch) { mLastMatch = aMatch; }
~nsTemplateMatchRefSet() {
Finish();
MOZ_COUNT_DTOR(nsTemplateMatchRefSet); }
Iterator Insert(nsFixedSizeAllocator& aPool, Iterator aIterator, nsTemplateMatch* aMatch);
protected:
/**
* Initialize the set. Must be called before the set is used, or
* after Finish().
*/
void Init();
Iterator Add(nsFixedSizeAllocator& aPool, nsTemplateMatch* aMatch) {
return Insert(aPool, Last(), aMatch); }
/**
* Finish the set, releasing all matches. This must be called to
* properly release matches in the set. Yeah, yeah, this sucks.
*/
void Finish();
nsresult CopyInto(nsTemplateMatchSet& aMatchSet, nsFixedSizeAllocator& aPool) const;
/**
* Copy the set's contents from another match set
*/
void CopyFrom(const nsTemplateMatchRefSet& aMatchSet);
void Clear();
/**
* Helper routine that adds the match to the hashtable
*/
PRBool AddToTable(nsTemplateMatch* aMatch);
Iterator Erase(Iterator aIterator);
/**
* Hashtable entry; holds weak reference to a match object.
*/
struct Entry {
PLDHashEntryHdr mHdr;
nsTemplateMatch* mMatch;
};
void Remove(nsTemplateMatch* aMatch);
enum { kMaxInlineMatches = (sizeof(PLDHashTable) / sizeof(void*)) - 1 };
struct InlineMatches;
friend struct InlineMatches;
/**
* If the set is currently
*/
struct InlineMatches {
PRUint32 mCount;
nsTemplateMatch* mEntries[kMaxInlineMatches];
};
/**
* The set is implemented as a dual datastructure. It is initially
* a simple array that holds storage for kMaxInlineMatches
* elements. Once that capacity is exceeded, the storage is
* re-used for a PLDHashTable header. The hashtable allocates its
* entries from the normal malloc() heap.
*
* the InlineMatches structure is implemented such that its mCount
* variable overlaps with the PLDHashTable's `ops' member (which
* is a pointer to the hashtable's callback table). On a 32-bit
* architecture, we're safe assuming that the value for `ops' will
* be larger than kMaxInlineMatches when treated as an unsigned
* integer. And we'd have to get pretty unlucky on a 64-bit
* system for us to get screwed, I think.
*
* Instrumentation (#define NSTEMPLATEMATCHSET_METER) shows that
* almost all of the match sets contain fewer than seven elements.
*/
union {
PLDHashTable mTable;
InlineMatches mInlineMatches;
};
static PLDHashTableOps gOps;
static PLDHashNumber PR_CALLBACK
HashEntry(PLDHashTable* aTable, const void* aKey);
static PRBool PR_CALLBACK
MatchEntry(PLDHashTable* aTable, const PLDHashEntryHdr* aHdr, const void* aKey);
public:
class ConstIterator;
friend class ConstIterator;
/**
* An iterator that can be used to enumerate the contents of the
* set
*/
class ConstIterator {
protected:
friend class nsTemplateMatchRefSet;
void Next();
void Prev();
ConstIterator(const nsTemplateMatchRefSet* aSet, Entry* aTableEntry)
: mSet(aSet), mTableEntry(aTableEntry) {}
ConstIterator(const nsTemplateMatchRefSet* aSet, nsTemplateMatch** aInlineEntry)
: mSet(aSet), mInlineEntry(aInlineEntry) {}
const nsTemplateMatchRefSet* mSet;
union {
Entry* mTableEntry;
nsTemplateMatch** mInlineEntry;
};
nsTemplateMatch* get() const {
return mSet->mInlineMatches.mCount > PRUint32(kMaxInlineMatches)
? mTableEntry->mMatch
: *mInlineEntry; }
public:
ConstIterator() : mSet(nsnull), mTableEntry(nsnull) {}
ConstIterator(const ConstIterator& aConstIterator)
: mSet(aConstIterator.mSet),
mTableEntry(aConstIterator.mTableEntry) {}
ConstIterator& operator=(const ConstIterator& aConstIterator) {
mSet = aConstIterator.mSet;
mTableEntry = aConstIterator.mTableEntry;
return *this; }
ConstIterator& operator++() {
Next();
return *this; }
ConstIterator operator++(int) {
ConstIterator result(*this);
Next();
return result; }
ConstIterator& operator--() {
Prev();
return *this; }
ConstIterator operator--(int) {
ConstIterator result(*this);
Prev();
return result; }
/*const*/ nsTemplateMatch& operator*() const {
return *get(); }
/*const*/ nsTemplateMatch* operator->() const {
return get(); }
PRBool operator==(const ConstIterator& aConstIterator) const;
PRBool operator!=(const ConstIterator& aConstIterator) const {
return ! aConstIterator.operator==(*this); }
};
/**
* Retrieve an iterator that refers to the first element of the
* set
*/
ConstIterator First() const;
/**
* Retrieve an iterator that refers to ``one past'' the last
* element of the set
*/
ConstIterator Last() const;
/**
* Return PR_TRUE if the set is empty
*/
PRBool Empty() const;
/**
* Return PR_TRUE if the set contains aMatch
*/
PRBool Contains(const nsTemplateMatch* aMatch) const;
/**
* Add a match to the set. The set does *not* assume ownership of
* the match object: it only holds a weak reference. Duplicate
* matches are not added.
*
* @return PR_TRUE if the match was added to the set; PR_FALSE if it
* already existed (or could not be added for some other reason)
*/
PRBool Add(const nsTemplateMatch* aMatch);
/**
* Remove a match from the set.
* @return PR_TRUE if the match was removed from the set; PR_FALSE
* if the match was not present in the set.
*/
PRBool Remove(const nsTemplateMatch* aMatch);
};
#endif // nsTemplateMatchSet_h__

View File

@ -75,8 +75,8 @@ nsOutlinerRowTestNode::FilterInstantiations(InstantiationSet& aInstantiations, v
(mRows.Find(mConflictSet, container) != mRows.Last())) {
PR_LOG(gXULTemplateLog, PR_LOG_DEBUG, (" => passed"));
Element* element = new (mConflictSet.GetPool())
Element(container);
Element* element =
Element::Create(mConflictSet.GetPool(), container);
if (! element)
return NS_ERROR_OUT_OF_MEMORY;

View File

@ -47,19 +47,29 @@ public:
GetAncestorVariables(VariableSet& aVariables) const;
class Element : public MemoryElement {
protected:
// Hide so that only Create() and Destroy() can be used to
// allocate and deallocate from the heap
static void* operator new(size_t) { return 0; }
static void operator delete(void*, size_t) { }
public:
static void* operator new(size_t aSize, nsFixedSizeAllocator& aAllocator) {
return aAllocator.Alloc(aSize); }
static void operator delete(void* aPtr, size_t aSize) {
nsFixedSizeAllocator::Free(aPtr, aSize); }
Element(nsIRDFResource* aResource)
: mResource(aResource) {
MOZ_COUNT_CTOR(nsOutlinerRowTestNode::Element); }
virtual ~Element() { MOZ_COUNT_DTOR(nsOutlinerRowTestNode::Element); }
static Element*
Create(nsFixedSizeAllocator& aPool, nsIRDFResource* aResource) {
void* place = aPool.Alloc(sizeof(Element));
return place ? ::new (place) Element(aResource) : nsnull; }
static void
Destroy(nsFixedSizeAllocator& aPool, Element* aElement) {
aElement->~Element();
aPool.Free(aElement, sizeof(*aElement)); }
virtual const char* Type() const {
return "nsOutlinerRowTestNode::Element"; }
@ -74,8 +84,7 @@ public:
return PR_FALSE; }
virtual MemoryElement* Clone(void* aPool) const {
return new (*NS_STATIC_CAST(nsFixedSizeAllocator*, aPool))
Element(mResource); }
return Create(*NS_STATIC_CAST(nsFixedSizeAllocator*, aPool), mResource); }
protected:
nsCOMPtr<nsIRDFResource> mResource;

View File

@ -1263,14 +1263,14 @@ nsXULContentBuilder::CreateContainerContents(nsIContent* aElement,
// Iterate through newly added keys to determine which rules fired
nsClusterKeySet::ConstIterator last = newkeys.Last();
for (nsClusterKeySet::ConstIterator key = newkeys.First(); key != last; ++key) {
const nsTemplateMatchSet* matches;
mConflictSet.GetMatchesForClusterKey(*key, &matches);
nsConflictSet::MatchCluster* matches =
mConflictSet.GetMatchesForClusterKey(*key);
if (! matches)
continue;
nsTemplateMatch* match =
matches->FindMatchWithHighestPriority();
mConflictSet.GetMatchWithHighestPriority(matches);
NS_ASSERTION(match != nsnull, "no best match in match set");
if (! match)
@ -1286,7 +1286,7 @@ nsXULContentBuilder::CreateContainerContents(nsIContent* aElement,
aContainer, aNewIndexInContainer);
// Remember this as the "last" match
NS_CONST_CAST(nsTemplateMatchSet*, matches)->SetLastMatch(match);
matches->mLastMatch = match;
}
return NS_OK;
@ -1470,7 +1470,8 @@ nsXULContentBuilder::RemoveGeneratedContent(nsIContent* aElement)
// Remove element from the conflict set.
// XXXwaterson should this be moved into NoteGeneratedSubtreeRemoved?
nsTemplateMatchSet firings, retractions;
nsTemplateMatchSet firings(mConflictSet.GetPool());
nsTemplateMatchSet retractions(mConflictSet.GetPool());
mConflictSet.Remove(nsContentTestNode::Element(child), firings, retractions);
// Remove this and any children from the content support map.
@ -2087,7 +2088,8 @@ nsXULContentBuilder::CloseContainer(nsIContent* aElement)
// Remove any instantiations involving this element from the
// conflict set.
nsTemplateMatchSet firings, retractions;
nsTemplateMatchSet firings(mConflictSet.GetPool());
nsTemplateMatchSet retractions(mConflictSet.GetPool());
mConflictSet.Remove(nsContentTestNode::Element(aElement), firings, retractions);
}

View File

@ -1106,14 +1106,7 @@ nsXULOutlinerBuilder::TokenizeProperties(const nsAReadableString& aString,
if (iter == first)
break;
#if 1 // XXX until bug 55143 is fixed, we need to copy so the string
// is zero-terminated
nsAutoString s(Substring(first, iter));
nsCOMPtr<nsIAtom> atom = dont_AddRef(NS_NewAtom(s));
#else
nsCOMPtr<nsIAtom> atom = dont_AddRef(NS_NewAtom(Substring(first, iter)));
#endif
aProperties->AppendElement(atom);
} while (iter != end);
@ -1188,14 +1181,14 @@ nsXULOutlinerBuilder::OpenSubtreeOf(nsOutlinerRows::Subtree* aSubtree,
// Iterate through newly added keys to determine which rules fired
nsClusterKeySet::ConstIterator last = newkeys.Last();
for (nsClusterKeySet::ConstIterator key = newkeys.First(); key != last; ++key) {
const nsTemplateMatchSet* matches;
mConflictSet.GetMatchesForClusterKey(*key, &matches);
nsConflictSet::MatchCluster* matches =
mConflictSet.GetMatchesForClusterKey(*key);
if (! matches)
continue;
nsTemplateMatch* match =
matches->FindMatchWithHighestPriority();
mConflictSet.GetMatchWithHighestPriority(matches);
NS_ASSERTION(match != nsnull, "no best match in match set");
if (! match)
@ -1205,7 +1198,7 @@ nsXULOutlinerBuilder::OpenSubtreeOf(nsOutlinerRows::Subtree* aSubtree,
mRows.InsertRowAt(match, aSubtree, count);
// Remember this as the "last" match
NS_CONST_CAST(nsTemplateMatchSet*, matches)->SetLastMatch(match);
matches->mLastMatch = match;
// If this is open, then remember it so we can recursively add
// *its* rows to the tree.
@ -1260,13 +1253,14 @@ nsXULOutlinerBuilder::CloseContainer(PRInt32 aIndex, nsIRDFResource* aContainer)
if (aIndex < 0 || aIndex >= mRows.Count())
return NS_ERROR_INVALID_ARG;
nsTemplateMatchSet firings, retractions;
nsTemplateMatchSet firings(mConflictSet.GetPool());
nsTemplateMatchSet retractions(mConflictSet.GetPool());
mConflictSet.Remove(nsOutlinerRowTestNode::Element(aContainer), firings, retractions);
{
// Clean up the conflict set
nsTemplateMatchSet::Iterator last = retractions.Last();
nsTemplateMatchSet::Iterator iter;
nsTemplateMatchSet::ConstIterator last = retractions.Last();
nsTemplateMatchSet::ConstIterator iter;
for (iter = retractions.First(); iter != last; ++iter) {
Value val;
@ -1301,11 +1295,12 @@ nsXULOutlinerBuilder::RemoveMatchesFor(nsIRDFResource* aContainer)
if (! aContainer)
return NS_ERROR_FAILURE;
nsTemplateMatchSet firings, retractions;
nsTemplateMatchSet firings(mConflictSet.GetPool());
nsTemplateMatchSet retractions(mConflictSet.GetPool());
mConflictSet.Remove(nsOutlinerRowTestNode::Element(aContainer), firings, retractions);
nsTemplateMatchSet::Iterator last = retractions.Last();
nsTemplateMatchSet::Iterator iter;
nsTemplateMatchSet::ConstIterator last = retractions.Last();
nsTemplateMatchSet::ConstIterator iter;
for (iter = retractions.First(); iter != last; ++iter) {
Value val;

View File

@ -514,15 +514,15 @@ nsXULTemplateBuilder::FireNewlyMatchedRules(const nsClusterKeySet& aNewKeys)
// to track those?
nsClusterKeySet::ConstIterator last = aNewKeys.Last();
for (nsClusterKeySet::ConstIterator key = aNewKeys.First(); key != last; ++key) {
const nsTemplateMatchSet* matches;
mConflictSet.GetMatchesForClusterKey(*key, &matches);
nsConflictSet::MatchCluster* matches =
mConflictSet.GetMatchesForClusterKey(*key);
NS_ASSERTION(matches != nsnull, "no matched rules for new key");
if (! matches)
continue;
nsTemplateMatch* bestmatch =
matches->FindMatchWithHighestPriority();
mConflictSet.GetMatchWithHighestPriority(matches);
NS_ASSERTION(bestmatch != nsnull, "no matches in match set");
if (! bestmatch)
@ -530,12 +530,12 @@ nsXULTemplateBuilder::FireNewlyMatchedRules(const nsClusterKeySet& aNewKeys)
// If the new "bestmatch" is different from the last match,
// then we need to yank some content out and rebuild it.
const nsTemplateMatch* lastmatch = matches->GetLastMatch();
const nsTemplateMatch* lastmatch = matches->mLastMatch;
if (bestmatch != lastmatch) {
ReplaceMatch(VALUE_TO_IRDFRESOURCE(key->mMemberValue), lastmatch, bestmatch);
// Remember the best match as the new "last" match
NS_CONST_CAST(nsTemplateMatchSet*, matches)->SetLastMatch(bestmatch);
matches->mLastMatch = bestmatch;
}
}
@ -587,13 +587,13 @@ nsXULTemplateBuilder::Retract(nsIRDFResource* aSource,
for (NodeSet::ConstIterator node = mRDFTests.First(); node != lastnode; ++node) {
const nsRDFTestNode* rdftestnode = NS_STATIC_CAST(const nsRDFTestNode*, *node);
nsTemplateMatchSet firings;
nsTemplateMatchSet retractions;
nsTemplateMatchSet firings(mConflictSet.GetPool());
nsTemplateMatchSet retractions(mConflictSet.GetPool());
rdftestnode->Retract(aSource, aProperty, aTarget, firings, retractions);
{
nsTemplateMatchSet::Iterator last = retractions.Last();
for (nsTemplateMatchSet::Iterator match = retractions.First(); match != last; ++match) {
nsTemplateMatchSet::ConstIterator last = retractions.Last();
for (nsTemplateMatchSet::ConstIterator match = retractions.First(); match != last; ++match) {
Value memberval;
match->mAssignments.GetAssignmentFor(match->mRule->GetMemberVariable(), &memberval);
@ -1243,27 +1243,19 @@ nsXULTemplateBuilder::SynchronizeAll(nsIRDFResource* aSource,
// Get all the matches whose assignments are currently supported
// by aSource and aProperty: we'll need to recompute them.
const nsTemplateMatchSet* matches;
mConflictSet.GetMatchesWithBindingDependency(aSource, &matches);
const nsTemplateMatchRefSet* matches =
mConflictSet.GetMatchesWithBindingDependency(aSource);
if (! matches || matches->Empty())
return NS_OK;
// Since we'll actually be manipulating the match set as we
// iterate through it, we need to copy it into our own private
// area before performing the iteration.
static const size_t kBucketSizes[] = { nsTemplateMatchSet::kEntrySize, nsTemplateMatchSet::kIndexSize };
static const PRInt32 kNumBuckets = sizeof(kBucketSizes) / sizeof(size_t);
nsTemplateMatchRefSet copy = *matches;
// Per news://news.mozilla.org/39BEC105.5090206%40netscape.com
static const PRInt32 kPoolSize = 256;
nsFixedSizeAllocator pool;
pool.Init("nsXULTemplateBuilder::SynchronizeAll", kBucketSizes, kNumBuckets, kPoolSize);
nsTemplateMatchSet copy;
matches->CopyInto(copy, pool);
for (nsTemplateMatchSet::Iterator match = copy.First(); match != copy.Last(); ++match) {
nsTemplateMatchRefSet::ConstIterator last = copy.Last();
for (nsTemplateMatchRefSet::ConstIterator match = copy.First(); match != last; ++match) {
const nsTemplateRule* rule = match->mRule;
// Recompute the assignments. This will replace aOldTarget with

View File

@ -1106,14 +1106,7 @@ nsXULOutlinerBuilder::TokenizeProperties(const nsAReadableString& aString,
if (iter == first)
break;
#if 1 // XXX until bug 55143 is fixed, we need to copy so the string
// is zero-terminated
nsAutoString s(Substring(first, iter));
nsCOMPtr<nsIAtom> atom = dont_AddRef(NS_NewAtom(s));
#else
nsCOMPtr<nsIAtom> atom = dont_AddRef(NS_NewAtom(Substring(first, iter)));
#endif
aProperties->AppendElement(atom);
} while (iter != end);
@ -1188,14 +1181,14 @@ nsXULOutlinerBuilder::OpenSubtreeOf(nsOutlinerRows::Subtree* aSubtree,
// Iterate through newly added keys to determine which rules fired
nsClusterKeySet::ConstIterator last = newkeys.Last();
for (nsClusterKeySet::ConstIterator key = newkeys.First(); key != last; ++key) {
const nsTemplateMatchSet* matches;
mConflictSet.GetMatchesForClusterKey(*key, &matches);
nsConflictSet::MatchCluster* matches =
mConflictSet.GetMatchesForClusterKey(*key);
if (! matches)
continue;
nsTemplateMatch* match =
matches->FindMatchWithHighestPriority();
mConflictSet.GetMatchWithHighestPriority(matches);
NS_ASSERTION(match != nsnull, "no best match in match set");
if (! match)
@ -1205,7 +1198,7 @@ nsXULOutlinerBuilder::OpenSubtreeOf(nsOutlinerRows::Subtree* aSubtree,
mRows.InsertRowAt(match, aSubtree, count);
// Remember this as the "last" match
NS_CONST_CAST(nsTemplateMatchSet*, matches)->SetLastMatch(match);
matches->mLastMatch = match;
// If this is open, then remember it so we can recursively add
// *its* rows to the tree.
@ -1260,13 +1253,14 @@ nsXULOutlinerBuilder::CloseContainer(PRInt32 aIndex, nsIRDFResource* aContainer)
if (aIndex < 0 || aIndex >= mRows.Count())
return NS_ERROR_INVALID_ARG;
nsTemplateMatchSet firings, retractions;
nsTemplateMatchSet firings(mConflictSet.GetPool());
nsTemplateMatchSet retractions(mConflictSet.GetPool());
mConflictSet.Remove(nsOutlinerRowTestNode::Element(aContainer), firings, retractions);
{
// Clean up the conflict set
nsTemplateMatchSet::Iterator last = retractions.Last();
nsTemplateMatchSet::Iterator iter;
nsTemplateMatchSet::ConstIterator last = retractions.Last();
nsTemplateMatchSet::ConstIterator iter;
for (iter = retractions.First(); iter != last; ++iter) {
Value val;
@ -1301,11 +1295,12 @@ nsXULOutlinerBuilder::RemoveMatchesFor(nsIRDFResource* aContainer)
if (! aContainer)
return NS_ERROR_FAILURE;
nsTemplateMatchSet firings, retractions;
nsTemplateMatchSet firings(mConflictSet.GetPool());
nsTemplateMatchSet retractions(mConflictSet.GetPool());
mConflictSet.Remove(nsOutlinerRowTestNode::Element(aContainer), firings, retractions);
nsTemplateMatchSet::Iterator last = retractions.Last();
nsTemplateMatchSet::Iterator iter;
nsTemplateMatchSet::ConstIterator last = retractions.Last();
nsTemplateMatchSet::ConstIterator iter;
for (iter = retractions.First(); iter != last; ++iter) {
Value val;

View File

@ -196,8 +196,8 @@ void CNavDTD::RecycleNodes(nsEntryStack *aNodeStack) {
PRInt32 theIndex=0;
for(theIndex=0;theIndex<theCount;theIndex++) {
nsIParserNode* node=aNodeStack->NodeAt(theIndex);
NS_IF_RELEASE(node);
nsCParserNode* node=aNodeStack->NodeAt(theIndex);
IF_FREE(node, &mNodeAllocator);
}
}
}
@ -587,12 +587,12 @@ nsresult CNavDTD::DidBuildModel(nsresult anErrorCode,PRBool aNotifySink,nsIParse
while(mBodyContext->GetCount() > 0) {
nsEntryStack *theChildStyles=0;
nsIParserNode* theNode=mBodyContext->Pop(theChildStyles);
nsCParserNode* theNode=mBodyContext->Pop(theChildStyles);
if(theNode) {
if(theChildStyles) {
delete theChildStyles;
}
NS_IF_RELEASE(theNode);
IF_FREE(theNode, &mNodeAllocator);
}
}
}
@ -637,7 +637,7 @@ nsresult CNavDTD::DidBuildModel(nsresult anErrorCode,PRBool aNotifySink,nsIParse
CToken* theToken=0;
while((theToken=(CToken*)mMisplacedContent.Pop())) {
IF_FREE(theToken);
IF_FREE(theToken, mTokenAllocator);
}
if(mDTDDebug) {
@ -726,7 +726,7 @@ nsresult CNavDTD::HandleToken(CToken* aToken,nsIParser* aParser){
mSkipTarget=eHTMLTag_unknown; //stop skipping.
//mTokenizer->PushTokenFront(aToken); //push the end token...
execSkipContent=PR_TRUE;
IF_FREE(aToken);
IF_FREE(aToken, mTokenAllocator);
theToken=(CHTMLToken*)mSkippedContent.PopFront();
theType=eToken_start;
}
@ -741,7 +741,7 @@ nsresult CNavDTD::HandleToken(CToken* aToken,nsIParser* aParser){
if(theType!=eToken_attribute) {
aToken->AppendSource(mScratch);
}
IF_FREE(aToken);
IF_FREE(aToken, mTokenAllocator);
return result;
}
else {
@ -889,7 +889,7 @@ nsresult CNavDTD::HandleToken(CToken* aToken,nsIParser* aParser){
if(NS_SUCCEEDED(result) || (NS_ERROR_HTMLPARSER_BLOCK==result)) {
IF_FREE(theToken);
IF_FREE(theToken, mTokenAllocator);
}
else if(result==NS_ERROR_HTMLPARSER_STOPPARSING) {
mDTDState=result;
@ -937,7 +937,7 @@ nsresult CNavDTD::DidHandleStartTag(nsIParserNode& aNode,eHTMLTags aChildTag){
if(eToken_newline==theType){
mLineNumber++;
theNextToken=mTokenizer->PopToken(); //skip 1st newline inside PRE and LISTING
IF_FREE(theNextToken); // fix for Bug 29379
IF_FREE(theNextToken, mTokenAllocator); // fix for Bug 29379
}//if
}//if
}
@ -1019,7 +1019,7 @@ nsresult CNavDTD::DidHandleStartTag(nsIParserNode& aNode,eHTMLTags aChildTag){
CToken *theEndToken=mTokenAllocator->CreateTokenOfType(eToken_end,aChildTag);
if(theEndToken) {
result=HandleEndToken(theEndToken);
IF_FREE(theEndToken);
IF_FREE(theEndToken, mTokenAllocator);
}
}
}
@ -1172,7 +1172,7 @@ enum eProcessRule {eNormalOp,eLetInlineContainBlock};
* @param aNode -- CParserNode representing this start token
* @return PR_TRUE if all went well; PR_FALSE if error occured
*/
nsresult CNavDTD::HandleDefaultStartToken(CToken* aToken,eHTMLTags aChildTag,nsIParserNode *aNode) {
nsresult CNavDTD::HandleDefaultStartToken(CToken* aToken,eHTMLTags aChildTag,nsCParserNode *aNode) {
NS_PRECONDITION(0!=aToken,kNullToken);
nsresult result=NS_OK;
@ -1607,7 +1607,7 @@ nsresult CNavDTD::HandleStartToken(CToken* aToken) {
//Begin by gathering up attributes...
nsIParserNode* theNode=mNodeAllocator.CreateNode(aToken,mLineNumber,mTokenAllocator);
nsCParserNode* theNode=mNodeAllocator.CreateNode(aToken,mLineNumber,mTokenAllocator);
eHTMLTags theChildTag=(eHTMLTags)aToken->GetTypeID();
PRInt16 attrCount=aToken->GetAttributeCount();
@ -1724,7 +1724,7 @@ nsresult CNavDTD::HandleStartToken(CToken* aToken) {
result=NS_OK;
}
NS_IF_RELEASE(theNode);
IF_FREE(theNode, &mNodeAllocator);
return result;
}
@ -1850,7 +1850,7 @@ static void StripWSFollowingTag(eHTMLTags aChildTag,nsITokenizer* aTokenizer,nsT
case eToken_newline: aNewlineCount++;
case eToken_whitespace:
theToken=aTokenizer->PopToken();
IF_FREE(theToken);
IF_FREE(theToken, aTokenAllocator);
theToken=aTokenizer->PeekToken();
break;
default:
@ -2039,9 +2039,9 @@ nsresult CNavDTD::HandleSavedTokens(PRInt32 anIndex) {
nsEntryStack* theChildStyleStack=0;
for(i=0; i<(theTagCount - theTopIndex); i++) {
nsIParserNode* node=mBodyContext->Pop(theChildStyleStack);
nsCParserNode* node=mBodyContext->Pop(theChildStyleStack);
mTempContext->Push(node);
NS_IF_RELEASE(node); //release the popped node since push will addref for us.
IF_FREE(node, &mNodeAllocator); //release the popped node since push will addref for us.
}
// Now flush out all the bad contents.
@ -2068,7 +2068,7 @@ nsresult CNavDTD::HandleSavedTokens(PRInt32 anIndex) {
PRInt32 theIndex=mBodyContext->LastOf(theTag);
if(theIndex!=kNotFound && theIndex<=mBodyContext->mContextTopIndex) {
IF_FREE(theToken);
IF_FREE(theToken, mTokenAllocator);
continue;
}
}
@ -2082,9 +2082,9 @@ nsresult CNavDTD::HandleSavedTokens(PRInt32 anIndex) {
// Bad-contents were successfully processed. Now, itz time to get
// back to the original body context state.
for(PRInt32 k=0; k<(theTagCount - theTopIndex); k++) {
nsIParserNode* node=mTempContext->Pop(theChildStyleStack);
nsCParserNode* node=mTempContext->Pop(theChildStyleStack);
mBodyContext->Push(node);
NS_IF_RELEASE(node);
IF_FREE(node, &mNodeAllocator);
}
STOP_TIMER()
@ -2135,7 +2135,7 @@ nsresult CNavDTD::HandleEntityToken(CToken* aToken) {
eHTMLTags theParentTag=mBodyContext->Last();
nsIParserNode* theNode=mNodeAllocator.CreateNode(aToken,mLineNumber,0);
nsCParserNode* theNode=mNodeAllocator.CreateNode(aToken,mLineNumber,0);
if(theNode) {
PRBool theParentContains=-1; //set to -1 to force CanOmit to recompute...
if(CanOmit(theParentTag,eHTMLTag_entity,theParentContains)) {
@ -2148,7 +2148,7 @@ nsresult CNavDTD::HandleEntityToken(CToken* aToken) {
#endif
result=AddLeaf(theNode);
}
NS_IF_RELEASE(theNode);
IF_FREE(theNode, &mNodeAllocator);
}
return result;
}
@ -2172,7 +2172,7 @@ nsresult CNavDTD::HandleCommentToken(CToken* aToken) {
const nsAReadableString& theComment = theToken->GetStringValue();
mLineNumber += CountCharInReadable(theComment, PRUnichar(kNewLine));
nsIParserNode* theNode=mNodeAllocator.CreateNode(aToken,mLineNumber,0);
nsCParserNode* theNode=mNodeAllocator.CreateNode(aToken,mLineNumber,0);
if(theNode) {
#ifdef RICKG_DEBUG
@ -2184,7 +2184,7 @@ nsresult CNavDTD::HandleCommentToken(CToken* aToken) {
result=(mSink) ? mSink->AddComment(*theNode) : NS_OK;
NS_IF_RELEASE(theNode);
IF_FREE(theNode, &mNodeAllocator);
MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::HandleCommentToken(), this=%p\n", this));
START_TIMER();
@ -2248,7 +2248,7 @@ nsresult CNavDTD::HandleProcessingInstructionToken(CToken* aToken){
nsresult result=NS_OK;
nsIParserNode* theNode=mNodeAllocator.CreateNode(aToken,mLineNumber,0);
nsCParserNode* theNode=mNodeAllocator.CreateNode(aToken,mLineNumber,0);
if(theNode) {
#ifdef RICKG_DEBUG
@ -2260,7 +2260,7 @@ nsresult CNavDTD::HandleProcessingInstructionToken(CToken* aToken){
result=(mSink) ? mSink->AddProcessingInstruction(*theNode) : NS_OK;
NS_IF_RELEASE(theNode);
IF_FREE(theNode, &mNodeAllocator);
MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::HandleProcessingInstructionToken(), this=%p\n", this));
START_TIMER();
@ -2298,7 +2298,7 @@ nsresult CNavDTD::HandleDocTypeDeclToken(CToken* aToken){
docTypeStr.Cut(0,2); // Now remove "<!" from the begining
theToken->SetStringValue(docTypeStr);
nsIParserNode* theNode=mNodeAllocator.CreateNode(aToken,mLineNumber,0);
nsCParserNode* theNode=mNodeAllocator.CreateNode(aToken,mLineNumber,0);
if(theNode) {
STOP_TIMER();
@ -2321,7 +2321,7 @@ nsresult CNavDTD::HandleDocTypeDeclToken(CToken* aToken){
result = (mSink)? mSink->AddDocTypeDecl(*theNode,theMode):NS_OK;
NS_IF_RELEASE(theNode);
IF_FREE(theNode, &mNodeAllocator);
MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::HandleDocTypeDeclToken(), this=%p\n", this));
START_TIMER();
@ -2431,7 +2431,7 @@ nsresult CNavDTD::CollectSkippedContent(nsIParserNode& aNode,PRInt32 &aCount) {
}
else theNextToken->AppendSource(*theNode->mSkippedContent);
}
IF_FREE(theNextToken);
IF_FREE(theNextToken, mTokenAllocator);
}
// if the string contained CRs (hence is either CR, or CRLF terminated)
@ -2899,8 +2899,8 @@ nsresult CNavDTD::OpenTransientStyles(eHTMLTags aChildTag){
}
else {
//if the node tag can't contain the child tag, then remove the child tag from the style stack
nsIParserNode* node=theStack->Remove(sindex,theNodeTag);
NS_IF_RELEASE(node);
nsCParserNode* node=theStack->Remove(sindex,theNodeTag);
IF_FREE(node, &mNodeAllocator);
theEntry--; //back up by one
}
} //if
@ -2967,8 +2967,8 @@ nsresult CNavDTD::PopStyle(eHTMLTags aTag){
if(mFlags & NS_PARSER_FLAG_ENABLE_RESIDUAL_STYLE) {
#ifdef ENABLE_RESIDUALSTYLE
if(nsHTMLElement::IsResidualStyleTag(aTag)) {
nsIParserNode* node=mBodyContext->PopStyle(aTag);
NS_IF_RELEASE(node);
nsCParserNode* node=mBodyContext->PopStyle(aTag);
IF_FREE(node, &mNodeAllocator);
}
#endif
} //if
@ -2984,7 +2984,7 @@ nsresult CNavDTD::PopStyle(eHTMLTags aTag){
* @update gess4/22/98
* @param aNode -- next node to be added to model
*/
nsresult CNavDTD::OpenHTML(const nsIParserNode *aNode){
nsresult CNavDTD::OpenHTML(const nsCParserNode *aNode){
NS_PRECONDITION(mBodyContext->GetCount() >= 0, kInvalidTagStackPos);
STOP_TIMER();
@ -3084,7 +3084,7 @@ nsresult CNavDTD::CloseHead(const nsIParserNode *aNode){
* @param aNode -- next node to be added to model
* @return TRUE if ok, FALSE if error
*/
nsresult CNavDTD::OpenBody(const nsIParserNode *aNode){
nsresult CNavDTD::OpenBody(const nsCParserNode *aNode){
NS_PRECONDITION(mBodyContext->GetCount() >= 0, kInvalidTagStackPos);
nsresult result=NS_OK;
@ -3209,7 +3209,7 @@ nsresult CNavDTD::CloseForm(const nsIParserNode *aNode){
* @param aNode -- next node to be added to model
* @return TRUE if ok, FALSE if error
*/
nsresult CNavDTD::OpenMap(const nsIParserNode *aNode){
nsresult CNavDTD::OpenMap(const nsCParserNode *aNode){
STOP_TIMER();
MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::OpenMap(), this=%p\n", this));
@ -3260,7 +3260,7 @@ nsresult CNavDTD::CloseMap(const nsIParserNode *aNode){
* @param aNode -- next node to be added to model
* @return TRUE if ok, FALSE if error
*/
nsresult CNavDTD::OpenFrameset(const nsIParserNode *aNode){
nsresult CNavDTD::OpenFrameset(const nsCParserNode *aNode){
NS_PRECONDITION(mBodyContext->GetCount() >= 0, kInvalidTagStackPos);
mFlags |= NS_PARSER_FLAG_HAD_FRAMESET;
@ -3308,7 +3308,7 @@ nsresult CNavDTD::CloseFrameset(const nsIParserNode *aNode){
* @param aNode - The noscript node
* return NS_OK if succeeded else ERROR
*/
nsresult CNavDTD::OpenNoscript(const nsIParserNode *aNode,nsEntryStack* aStyleStack) {
nsresult CNavDTD::OpenNoscript(const nsCParserNode *aNode,nsEntryStack* aStyleStack) {
nsresult result=NS_OK;
if(mSink) {
@ -3381,7 +3381,7 @@ nsresult CNavDTD::CloseNoscript(const nsIParserNode *aNode) {
* @return TRUE if ok, FALSE if error
*/
nsresult
CNavDTD::OpenContainer(const nsIParserNode *aNode,eHTMLTags aTag,PRBool aClosedByStartTag,nsEntryStack* aStyleStack){
CNavDTD::OpenContainer(const nsCParserNode *aNode,eHTMLTags aTag,PRBool aClosedByStartTag,nsEntryStack* aStyleStack){
NS_PRECONDITION(mBodyContext->GetCount() >= 0, kInvalidTagStackPos);
nsresult result=NS_OK;
@ -3505,7 +3505,7 @@ CNavDTD::OpenContainer(const nsIParserNode *aNode,eHTMLTags aTag,PRBool aClosedB
* @return TRUE if ok, FALSE if error
*/
nsresult
CNavDTD::CloseContainer(const nsIParserNode *aNode,eHTMLTags aTarget,PRBool aClosedByStartTag){
CNavDTD::CloseContainer(const nsCParserNode *aNode,eHTMLTags aTarget,PRBool aClosedByStartTag){
nsresult result=NS_OK;
eHTMLTags nodeType=(eHTMLTags)aNode->GetNodeType();
@ -3587,7 +3587,7 @@ nsresult CNavDTD::CloseContainersTo(PRInt32 anIndex,eHTMLTags aTarget, PRBool aC
nsEntryStack *theChildStyleStack=0;
eHTMLTags theTag=mBodyContext->Last();
nsCParserNode *theNode=NS_STATIC_CAST(nsCParserNode*,mBodyContext->Pop(theChildStyleStack));
nsCParserNode *theNode=mBodyContext->Pop(theChildStyleStack);
if(theNode) {
result=CloseContainer(theNode,aTarget,aClosedByStartTag);
@ -3634,8 +3634,8 @@ nsresult CNavDTD::CloseContainersTo(PRInt32 anIndex,eHTMLTags aTarget, PRBool aC
//here's a case we missed: <a><div>text<a>text</a></div>
//The <div> pushes the 1st <a> onto the rs-stack, then the 2nd <a>
//pops the 1st <a> from the rs-stack altogether.
nsIParserNode* node=mBodyContext->PopStyle(theTag);
NS_IF_RELEASE(node);
nsCParserNode* node=mBodyContext->PopStyle(theTag);
IF_FREE(node, &mNodeAllocator);
}
@ -3680,8 +3680,8 @@ nsresult CNavDTD::CloseContainersTo(PRInt32 anIndex,eHTMLTags aTarget, PRBool aC
// This fixes bug 30885 and 29626
// Make sure that the node, which is about to
// get released does not stay on the style stack...
nsIParserNode* node=mBodyContext->PopStyle(theTag);
NS_IF_RELEASE(node);
nsCParserNode* node=mBodyContext->PopStyle(theTag);
IF_FREE(node, &mNodeAllocator);
}
mBodyContext->PushStyles(theChildStyleStack);
}
@ -3705,8 +3705,8 @@ nsresult CNavDTD::CloseContainersTo(PRInt32 anIndex,eHTMLTags aTarget, PRBool aC
//style tag that got onto that tag stack from a stylestack somewhere.
//Pop it from the stylestack if the target is also a style tag.
if(theTargetTagIsStyle) {
nsIParserNode* node=mBodyContext->PopStyle(theTag);
NS_IF_RELEASE(node);
nsCParserNode* node=mBodyContext->PopStyle(theTag);
IF_FREE(node, &mNodeAllocator);
}
}
}
@ -3723,7 +3723,7 @@ nsresult CNavDTD::CloseContainersTo(PRInt32 anIndex,eHTMLTags aTarget, PRBool aC
}
}
#endif
NS_IF_RELEASE(theNode);
IF_FREE(theNode, &mNodeAllocator);
}//if theNode
}

View File

@ -401,7 +401,7 @@ CLASS_EXPORT_HTMLPARS CNavDTD : public nsIDTD {
* @return error code representing construction state; usually 0.
*/
nsresult HandleStartToken(CToken* aToken);
nsresult HandleDefaultStartToken(CToken* aToken,eHTMLTags aChildTag,nsIParserNode *aNode);
nsresult HandleDefaultStartToken(CToken* aToken,eHTMLTags aChildTag,nsCParserNode *aNode);
nsresult HandleEndToken(CToken* aToken);
nsresult HandleEntityToken(CToken* aToken);
nsresult HandleCommentToken(CToken* aToken);
@ -424,14 +424,14 @@ CLASS_EXPORT_HTMLPARS CNavDTD : public nsIDTD {
* @param node to be opened in content sink.
* @return error code representing error condition-- usually 0.
*/
nsresult OpenHTML(const nsIParserNode *aNode);
nsresult OpenHTML(const nsCParserNode *aNode);
nsresult OpenHead(const nsIParserNode *aNode);
nsresult OpenBody(const nsIParserNode *aNode);
nsresult OpenBody(const nsCParserNode *aNode);
nsresult OpenForm(const nsIParserNode *aNode);
nsresult OpenMap(const nsIParserNode *aNode);
nsresult OpenFrameset(const nsIParserNode *aNode);
nsresult OpenNoscript(const nsIParserNode *aNode,nsEntryStack* aStyleStack=0);
nsresult OpenContainer(const nsIParserNode *aNode,eHTMLTags aTag,PRBool aClosedByStartTag,nsEntryStack* aStyleStack=0);
nsresult OpenMap(const nsCParserNode *aNode);
nsresult OpenFrameset(const nsCParserNode *aNode);
nsresult OpenNoscript(const nsCParserNode *aNode,nsEntryStack* aStyleStack=0);
nsresult OpenContainer(const nsCParserNode *aNode,eHTMLTags aTag,PRBool aClosedByStartTag,nsEntryStack* aStyleStack=0);
/**
* The next set of methods close the given HTML element.
@ -454,7 +454,7 @@ CLASS_EXPORT_HTMLPARS CNavDTD : public nsIDTD {
* @update gess5/11/98
* @return error code - 0 if all went well.
*/
nsresult CloseContainer(const nsIParserNode *aNode,eHTMLTags aTarget,PRBool aClosedByStartTag);
nsresult CloseContainer(const nsCParserNode *aNode,eHTMLTags aTarget,PRBool aClosedByStartTag);
nsresult CloseContainersTo(eHTMLTags aTag,PRBool aClosedByStartTag);
nsresult CloseContainersTo(PRInt32 anIndex,eHTMLTags aTag,PRBool aClosedByStartTag);

View File

@ -463,7 +463,7 @@ nsresult COtherDTD::DidBuildModel(nsresult anErrorCode,PRBool aNotifySink,nsIPar
while(theIndex>0) {
eHTMLTags theParent= mBodyContext->TagAt(--theIndex);
CElement *theElement=gElementTable->mElements[theParent];
nsIParserNode *theNode=mBodyContext->PeekNode();
nsCParserNode *theNode=mBodyContext->PeekNode();
theElement->HandleEndToken(theNode,theChild,mBodyContext,mSink);
theChild=theParent;
}
@ -489,7 +489,7 @@ nsresult COtherDTD::DidBuildModel(nsresult anErrorCode,PRBool aNotifySink,nsIPar
if(theChildStyles) {
delete theChildStyles;
}
NS_IF_RELEASE(theNode);
IF_FREE(theNode, mNodeAllocator);
}
}
}
@ -546,7 +546,7 @@ nsresult COtherDTD::HandleToken(CToken* aToken,nsIParser* aParser){
if(NS_SUCCEEDED(result) || (NS_ERROR_HTMLPARSER_BLOCK==result)) {
IF_FREE(theToken);
IF_FREE(theToken, mTokenAllocator);
}
else if(result==NS_ERROR_HTMLPARSER_STOPPARSING)
mDTDState=result;
@ -701,7 +701,7 @@ nsresult COtherDTD::HandleStartToken(CToken* aToken) {
//Begin by gathering up attributes...
nsresult result=NS_OK;
nsIParserNode* theNode=mNodeAllocator->CreateNode(aToken,mLineNumber,mTokenAllocator);
nsCParserNode* theNode=mNodeAllocator->CreateNode(aToken,mLineNumber,mTokenAllocator);
if(theNode) {
eHTMLTags theChildTag=(eHTMLTags)aToken->GetTypeID();
@ -743,7 +743,7 @@ nsresult COtherDTD::HandleStartToken(CToken* aToken) {
} //if
}//if
NS_IF_RELEASE(theNode);
IF_FREE(theNode, mNodeAllocator);
}
else result=NS_ERROR_OUT_OF_MEMORY;
@ -788,10 +788,10 @@ nsresult COtherDTD::HandleEndToken(CToken* aToken) {
}
CElement* theElement=gElementTable->mElements[theParent];
if(theElement) {
nsIParserNode* theNode=mNodeAllocator->CreateNode(aToken,mLineNumber,mTokenAllocator);
nsCParserNode* theNode=mNodeAllocator->CreateNode(aToken,mLineNumber,mTokenAllocator);
if(theNode) {
result=theElement->HandleEndToken(theNode,theChildTag,mBodyContext,mSink);
NS_IF_RELEASE(theNode);
IF_FREE(theNode, mNodeAllocator);
}
}
break;

View File

@ -211,19 +211,19 @@ public:
nsDTDContext* aContext,
nsIHTMLContentSink* aSink);
virtual nsresult HandleStartToken( nsIParserNode* aNode,
virtual nsresult HandleStartToken( nsCParserNode* aNode,
eHTMLTags aTag,
nsDTDContext* aContext,
nsIHTMLContentSink* aSink);
virtual nsresult HandleEndToken(nsIParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink);
virtual nsresult HandleEndToken(nsCParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink);
virtual nsresult HandleMisplacedStartToken(nsIParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
virtual nsresult HandleMisplacedStartToken(nsCParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
nsresult result=NS_OK;
return result;
}
virtual PRInt32 FindAutoCloseTargetForEndTag(nsIParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink, PRInt32& anIndex) {
virtual PRInt32 FindAutoCloseTargetForEndTag(nsCParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink, PRInt32& anIndex) {
PRInt32 result=-1;
if(mTag!=aTag) {
@ -288,7 +288,7 @@ public:
/**********************************************************
this gets called after each tag is opened in the given context
**********************************************************/
virtual nsresult OpenContext(nsIParserNode *aNode,eHTMLTags aTag,nsDTDContext *aContext,nsIHTMLContentSink *aSink) {
virtual nsresult OpenContext(nsCParserNode *aNode,eHTMLTags aTag,nsDTDContext *aContext,nsIHTMLContentSink *aSink) {
aContext->Push(aNode);
@ -300,7 +300,7 @@ public:
/**********************************************************
this gets called after each tag is opened in the given context
**********************************************************/
virtual nsresult OpenContainerInContext(nsIParserNode *aNode,eHTMLTags aTag,nsDTDContext *aContext,nsIHTMLContentSink *aSink) {
virtual nsresult OpenContainerInContext(nsCParserNode *aNode,eHTMLTags aTag,nsDTDContext *aContext,nsIHTMLContentSink *aSink) {
OpenContext(aNode,aTag,aContext,aSink);
return OpenContainer(aNode,aTag,aContext,aSink);
}
@ -315,22 +315,22 @@ public:
/**********************************************************
this gets called to close a tag in the given context
**********************************************************/
virtual nsresult CloseContext(nsIParserNode *aNode,eHTMLTags aTag,nsDTDContext *aContext,nsIHTMLContentSink *aSink) {
virtual nsresult CloseContext(nsCParserNode *aNode,eHTMLTags aTag,nsDTDContext *aContext,nsIHTMLContentSink *aSink) {
nsresult result=NS_OK;
nsEntryStack *theStack=0;
nsIParserNode *theNode=aContext->Pop(theStack);
nsCParserNode *theNode=aContext->Pop(theStack);
CElement *theElement=(aTag==mTag) ? this : GetElement(aTag);
result=theElement->NotifyClose(theNode,aTag,aContext,aSink);
NS_IF_RELEASE(aNode);
IF_FREE(aNode, aContext->mNodeAllocator);
return result;
}
/**********************************************************
this gets called to close a tag in the sink and in the context
**********************************************************/
virtual nsresult CloseContainerInContext(nsIParserNode *aNode,eHTMLTags aTag,nsDTDContext *aContext,nsIHTMLContentSink *aSink) {
virtual nsresult CloseContainerInContext(nsCParserNode *aNode,eHTMLTags aTag,nsDTDContext *aContext,nsIHTMLContentSink *aSink) {
nsresult result=NS_OK;
if(mTag!=aTag) {
CElement *theElement=GetElement(aTag);
@ -762,7 +762,7 @@ public:
/**********************************************************
Table handles the opening of it's own children
**********************************************************/
virtual nsresult HandleStartToken(nsIParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
virtual nsresult HandleStartToken(nsCParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
nsresult result=NS_OK;
switch(aTag) {
@ -808,7 +808,7 @@ public:
if(aContext->mTableStates) {
if(aContext->mTableStates->CanOpenTBody()) {
CToken* theToken=(CStartToken*)aContext->mTokenAllocator->CreateTokenOfType(eToken_start,eHTMLTag_tbody);
nsIParserNode* theNode=aContext->mNodeAllocator->CreateNode(theToken,0,0);
nsCParserNode* theNode=aContext->mNodeAllocator->CreateNode(theToken,0,0);
result=HandleStartToken(theNode,eHTMLTag_tbody,aContext,aSink);
}
@ -831,7 +831,7 @@ public:
/**********************************************************
Table handles the closing of it's own children
**********************************************************/
virtual nsresult HandleEndToken(nsIParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
virtual nsresult HandleEndToken(nsCParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
nsresult result=NS_OK;
if(aContext->HasOpenContainer(aTag)) {
@ -981,7 +981,7 @@ public:
/**********************************************************
handles the opening of it's own children
**********************************************************/
virtual nsresult HandleStartToken( nsIParserNode* aNode,
virtual nsresult HandleStartToken( nsCParserNode* aNode,
eHTMLTags aTag,
nsDTDContext* aContext,
nsIHTMLContentSink* aSink) {
@ -992,7 +992,7 @@ public:
/**********************************************************
this gets called after each tag is opened in the given context
**********************************************************/
virtual nsresult OpenContext(nsIParserNode *aNode,eHTMLTags aTag,nsDTDContext *aContext,nsIHTMLContentSink *aSink) {
virtual nsresult OpenContext(nsCParserNode *aNode,eHTMLTags aTag,nsDTDContext *aContext,nsIHTMLContentSink *aSink) {
CElement::OpenContext(aNode,aTag,aContext,aSink);
nsresult result=NS_OK;
@ -1013,7 +1013,7 @@ public:
/**********************************************************
handles the opening of it's own children
**********************************************************/
virtual nsresult HandleEndToken(nsIParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
virtual nsresult HandleEndToken(nsCParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
return CElement::HandleEndToken(aNode,aTag,aContext,aSink);
}
@ -1262,7 +1262,7 @@ public:
/**********************************************************
Call this for each element as it get's closed
**********************************************************/
virtual nsresult NotifyClose(nsIParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
virtual nsresult NotifyClose(nsCParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
nsresult result=NS_OK;
CElement* theHead=GetElement(eHTMLTag_head);
if(theHead) {
@ -1358,7 +1358,7 @@ public:
/**********************************************************
Call this for each element as it get's closed
**********************************************************/
virtual nsresult NotifyClose(nsIParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
virtual nsresult NotifyClose(nsCParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
nsresult result=NS_OK;
CElement* theHead=GetElement(eHTMLTag_head);
if(theHead) {
@ -1397,7 +1397,7 @@ public:
/**********************************************************
this gets called after each tag is opened in the given context
**********************************************************/
virtual nsresult OpenContainerInContext(nsIParserNode *aNode,eHTMLTags aTag,nsDTDContext *aContext,nsIHTMLContentSink *aSink) {
virtual nsresult OpenContainerInContext(nsCParserNode *aNode,eHTMLTags aTag,nsDTDContext *aContext,nsIHTMLContentSink *aSink) {
OpenContext(aNode,aTag,aContext,aSink);
return NS_OK;
}
@ -1418,7 +1418,7 @@ public:
/**********************************************************
Call this for each element as it get's closed
**********************************************************/
virtual nsresult NotifyClose(nsIParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
virtual nsresult NotifyClose(nsCParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
nsresult result=NS_OK;
if(aContext->HasOpenContainer(eHTMLTag_body)) {
@ -1464,7 +1464,7 @@ public:
/**********************************************************
Pre handles the opening of it's own children
**********************************************************/
virtual nsresult HandleStartToken(nsIParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
virtual nsresult HandleStartToken(nsCParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
nsresult result=CElement::HandleStartToken(aNode,aTag,aContext,aSink);
return result;
}
@ -1473,7 +1473,7 @@ public:
/**********************************************************
Pre handles the closing of it's own children
**********************************************************/
virtual nsresult HandleEndToken(nsIParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
virtual nsresult HandleEndToken(nsCParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
nsresult result=CElement::HandleEndToken(aNode,aTag,aContext,aSink);
return result;
}
@ -1512,7 +1512,7 @@ public:
/**********************************************************
handles the opening of it's own children
**********************************************************/
virtual nsresult HandleStartToken(nsIParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
virtual nsresult HandleStartToken(nsCParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
nsresult result=NS_OK;
nsIParserNode *theNode=aContext->PeekNode();
if(theNode) {
@ -1569,7 +1569,7 @@ public:
/**********************************************************
fieldset handles the opening of it's own children
**********************************************************/
virtual nsresult HandleStartToken(nsIParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
virtual nsresult HandleStartToken(nsCParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
nsresult result=NS_OK;
nsIParserNode *theNode=aContext->PeekNode();
if(theNode) {
@ -1624,7 +1624,7 @@ public:
/**********************************************************
Toplevel handles the opening of it's own children
**********************************************************/
virtual nsresult HandleStartToken( nsIParserNode* aNode,
virtual nsresult HandleStartToken( nsCParserNode* aNode,
eHTMLTags aTag,
nsDTDContext* aContext,
nsIHTMLContentSink* aSink) {
@ -1643,7 +1643,7 @@ public:
/**********************************************************
TopLevel handles the opening of it's own children
**********************************************************/
virtual nsresult HandleEndToken(nsIParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
virtual nsresult HandleEndToken(nsCParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
nsresult result=NS_OK;
@ -1728,7 +1728,7 @@ public:
/**********************************************************
HTML handles the opening of it's own children
**********************************************************/
virtual nsresult HandleStartToken( nsIParserNode* aNode,
virtual nsresult HandleStartToken( nsCParserNode* aNode,
eHTMLTags aTag,
nsDTDContext* aContext,
nsIHTMLContentSink* aSink) {
@ -1795,7 +1795,7 @@ public:
//let's auto open the body
CToken* theToken=(CStartToken*)aContext->mTokenAllocator->CreateTokenOfType(eToken_start,eHTMLTag_body);
nsIParserNode* theNode=aContext->mNodeAllocator->CreateNode(theToken,0,0);
nsCParserNode* theNode=aContext->mNodeAllocator->CreateNode(theToken,0,0);
result=theBody->HandleStartToken(theNode,eHTMLTag_body,aContext,aSink);
@ -1816,7 +1816,7 @@ public:
/**********************************************************
HTML handles the closing of it's own children
**********************************************************/
virtual nsresult HandleEndToken(nsIParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
virtual nsresult HandleEndToken(nsCParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
nsresult result=NS_OK;
switch(aTag) {
@ -1886,7 +1886,7 @@ public:
}
//this gets called after each tag is opened in the given context
virtual nsresult OpenContainer(nsIParserNode *aNode,eHTMLTags aTag,nsDTDContext *aContext,nsIHTMLContentSink *aSink) {
virtual nsresult OpenContainer(nsCParserNode *aNode,eHTMLTags aTag,nsDTDContext *aContext,nsIHTMLContentSink *aSink) {
nsresult result=NS_OK;
if(mTag==aTag) {
// Close the head before opening a body.
@ -1903,7 +1903,7 @@ public:
/**********************************************************
this gets called after each tag is opened in the given context
**********************************************************/
virtual nsresult OpenContainerInContext(nsIParserNode *aNode,eHTMLTags aTag,nsDTDContext *aContext,nsIHTMLContentSink *aSink) {
virtual nsresult OpenContainerInContext(nsCParserNode *aNode,eHTMLTags aTag,nsDTDContext *aContext,nsIHTMLContentSink *aSink) {
NS_ASSERTION(aContext!=nsnull,"need a valid context");
nsresult result=NS_OK;
// Since BODY is optional, we might come across more than one BODY!.
@ -1922,7 +1922,7 @@ public:
/**********************************************************
Body handles the opening of it's own children
**********************************************************/
virtual nsresult HandleStartToken( nsIParserNode* aNode,
virtual nsresult HandleStartToken( nsCParserNode* aNode,
eHTMLTags aTag,
nsDTDContext* aContext,
nsIHTMLContentSink* aSink) {
@ -1951,7 +1951,7 @@ public:
Body doesnt really need to handle it's own kids, but it's
a really convenient break point for debugging purposes.
**********************************************************/
virtual nsresult HandleEndToken(nsIParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
virtual nsresult HandleEndToken(nsCParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
nsresult result=NS_OK;
switch(aTag) {
case eHTMLTag_script:
@ -2645,7 +2645,7 @@ nsresult CElement::WillHandleStartToken( CElement *anElement,
return result;
}
nsresult CElement::HandleStartToken( nsIParserNode* aNode,
nsresult CElement::HandleStartToken( nsCParserNode* aNode,
eHTMLTags aTag,
nsDTDContext* aContext,
nsIHTMLContentSink* aSink) {
@ -2700,7 +2700,7 @@ nsresult CElement::HandleStartToken( nsIParserNode* aNode,
theParentTag=aContext->Last();
theParent=gElementTable->mElements[theParentTag];
nsIParserNode *theNode=aContext->PeekNode(); //this will get popped later...
nsCParserNode *theNode=aContext->PeekNode(); //this will get popped later...
if(theParent->IsSinkContainer()) {
CloseContainerInContext(theNode,theParentTag,aContext,aSink);
}
@ -2755,7 +2755,7 @@ nsresult CElement::HandleStartToken( nsIParserNode* aNode,
}
nsresult CElement::HandleEndToken(nsIParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
nsresult CElement::HandleEndToken(nsCParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
nsresult result=NS_OK;
if(aContext->Last()==aTag) {

View File

@ -123,7 +123,7 @@ void nsEntryStack::EnsureCapacityFor(PRInt32 aNewMax,PRInt32 aShiftOffset) {
*
* @update gess 04/22/99
*/
void nsEntryStack::Push(const nsIParserNode* aNode,nsEntryStack* aStyleStack) {
void nsEntryStack::Push(const nsCParserNode* aNode,nsEntryStack* aStyleStack) {
if(aNode) {
EnsureCapacityFor(mCount+1);
@ -131,9 +131,9 @@ void nsEntryStack::Push(const nsIParserNode* aNode,nsEntryStack* aStyleStack) {
((nsCParserNode*)aNode)->mUseCount++;
mEntries[mCount].mTag=(eHTMLTags)aNode->GetNodeType();
mEntries[mCount].mNode=(nsIParserNode*)aNode;
mEntries[mCount].mNode=NS_CONST_CAST(nsCParserNode*,aNode);
NS_ADDREF(mEntries[mCount].mNode);
IF_HOLD(mEntries[mCount].mNode);
mEntries[mCount].mParent=aStyleStack;
mEntries[mCount++].mStyles=0;
@ -146,7 +146,7 @@ void nsEntryStack::Push(const nsIParserNode* aNode,nsEntryStack* aStyleStack) {
*
* @update gess 11/10/99
*/
void nsEntryStack::PushFront(const nsIParserNode* aNode,nsEntryStack* aStyleStack) {
void nsEntryStack::PushFront(const nsCParserNode* aNode,nsEntryStack* aStyleStack) {
if(aNode) {
if(mCount<mCapacity) {
@ -161,9 +161,9 @@ void nsEntryStack::PushFront(const nsIParserNode* aNode,nsEntryStack* aStyleStac
((nsCParserNode*)aNode)->mUseCount++;
mEntries[0].mTag=(eHTMLTags)aNode->GetNodeType();
mEntries[0].mNode=(nsIParserNode*)aNode;
mEntries[0].mNode=NS_CONST_CAST(nsCParserNode*,aNode);
NS_ADDREF(mEntries[0].mNode);
IF_HOLD(mEntries[0].mNode);
mEntries[0].mParent=aStyleStack;
mEntries[0].mStyles=0;
@ -203,8 +203,8 @@ void nsEntryStack::Append(nsEntryStack *aStack) {
* aTag: the id of the tag to be removed
* @update gess 02/25/00
*/
nsIParserNode* nsEntryStack::Remove(PRInt32 anIndex,eHTMLTags aTag) {
nsIParserNode* result=0;
nsCParserNode* nsEntryStack::Remove(PRInt32 anIndex,eHTMLTags aTag) {
nsCParserNode* result=0;
if((0<mCount) && (anIndex<mCount)){
result=mEntries[anIndex].mNode;
@ -246,9 +246,9 @@ nsIParserNode* nsEntryStack::Remove(PRInt32 anIndex,eHTMLTags aTag) {
* @update harishd 04/04/99
* @update gess 04/21/99
*/
nsIParserNode* nsEntryStack::Pop(void) {
nsCParserNode* nsEntryStack::Pop(void) {
nsIParserNode* result=0;
nsCParserNode* result=0;
if(0<mCount) {
result=mEntries[--mCount].mNode;
@ -297,8 +297,8 @@ eHTMLTags nsEntryStack::First() const {
* @update harishd 04/04/99
* @update gess 04/21/99
*/
nsIParserNode* nsEntryStack::NodeAt(PRInt32 anIndex) const {
nsIParserNode* result=0;
nsCParserNode* nsEntryStack::NodeAt(PRInt32 anIndex) const {
nsCParserNode* result=0;
if((0<mCount) && (anIndex<mCount)) {
result=mEntries[anIndex].mNode;
}
@ -885,7 +885,7 @@ PRBool nsDTDContext::HasOpenContainer(eHTMLTags aTag) const {
*
* @update gess7/9/98
*/
void nsDTDContext::Push(const nsIParserNode* aNode,nsEntryStack* aStyleStack) {
void nsDTDContext::Push(const nsCParserNode* aNode,nsEntryStack* aStyleStack) {
if(aNode) {
#ifdef NS_DEBUG
@ -894,7 +894,7 @@ void nsDTDContext::Push(const nsIParserNode* aNode,nsEntryStack* aStyleStack) {
if(size< eMaxTags)
mXTags[size]=theTag;
#endif
mStack.Push((nsIParserNode*)aNode,aStyleStack);
mStack.Push(aNode,aStyleStack);
}
}
@ -902,10 +902,10 @@ void nsDTDContext::Push(const nsIParserNode* aNode,nsEntryStack* aStyleStack) {
* @update gess 11/11/99,
* harishd 04/04/99
*/
nsIParserNode* nsDTDContext::Pop(nsEntryStack *&aChildStyleStack) {
nsCParserNode* nsDTDContext::Pop(nsEntryStack *&aChildStyleStack) {
PRInt32 theSize=mStack.mCount;
nsIParserNode* result=0;
nsCParserNode* result=0;
if(0<theSize) {
@ -932,7 +932,7 @@ nsIParserNode* nsDTDContext::Pop(nsEntryStack *&aChildStyleStack) {
* @update harishd 04/07/00
*/
nsIParserNode* nsDTDContext::Pop() {
nsCParserNode* nsDTDContext::Pop() {
nsEntryStack *theTempStyleStack=0; // This has no use here...
return Pop(theTempStyleStack);
}
@ -992,7 +992,7 @@ nsEntryStack* nsDTDContext::GetStylesAt(PRInt32 anIndex) const {
*
* @update gess 04/28/99
*/
void nsDTDContext::PushStyle(const nsIParserNode* aNode){
void nsDTDContext::PushStyle(const nsCParserNode* aNode){
nsTagEntry* theEntry=mStack.EntryAt(mStack.mCount-1);
if(theEntry ) {
@ -1045,8 +1045,8 @@ void nsDTDContext::PushStyles(nsEntryStack *aStyles){
// If you're here it means that we have hit the rock bottom
// ,of the stack, and there's no need to handle anymore styles.
// Fix for bug 29048
nsIParserNode* theNode=aStyles->Pop();
NS_IF_RELEASE(theNode);
nsCParserNode* theNode=aStyles->Pop();
IF_HOLD(theNode);
delete aStyles;
aStyles=0;
}
@ -1058,8 +1058,8 @@ void nsDTDContext::PushStyles(nsEntryStack *aStyles){
*
* @update gess 04/28/99
*/
nsIParserNode* nsDTDContext::PopStyle(void){
nsIParserNode *result=0;
nsCParserNode* nsDTDContext::PopStyle(void){
nsCParserNode *result=0;
nsTagEntry *theEntry=mStack.EntryAt(mStack.mCount-1);
if(theEntry && (theEntry->mNode)) {
@ -1076,10 +1076,10 @@ nsIParserNode* nsDTDContext::PopStyle(void){
*
* @update gess 04/28/99
*/
nsIParserNode* nsDTDContext::PopStyle(eHTMLTags aTag){
nsCParserNode* nsDTDContext::PopStyle(eHTMLTags aTag){
PRInt32 theLevel=0;
nsIParserNode* result=0;
nsCParserNode* result=0;
for(theLevel=mStack.mCount-1;theLevel>0;theLevel--) {
nsEntryStack *theStack=mStack.mEntries[theLevel].mStyles;
@ -1105,10 +1105,10 @@ nsIParserNode* nsDTDContext::PopStyle(eHTMLTags aTag){
*
* @update gess 01/26/00
*/
nsIParserNode* nsDTDContext::RemoveStyle(eHTMLTags aTag){
nsCParserNode* nsDTDContext::RemoveStyle(eHTMLTags aTag){
PRInt32 theLevel=0;
nsIParserNode* result=0;
nsCParserNode* result=0;
for(theLevel=mStack.mCount-1;theLevel>0;theLevel--) {
nsEntryStack *theStack=mStack.mEntries[theLevel].mStyles;
@ -1337,7 +1337,7 @@ nsNodeAllocator::~nsNodeAllocator() {
#endif
}
nsIParserNode* nsNodeAllocator::CreateNode(CToken* aToken,PRInt32 aLineNumber,nsTokenAllocator* aTokenAllocator) {
nsCParserNode* nsNodeAllocator::CreateNode(CToken* aToken,PRInt32 aLineNumber,nsTokenAllocator* aTokenAllocator) {
nsCParserNode* result=0;
#ifdef HEAP_ALLOCATED_NODES
@ -1352,18 +1352,18 @@ nsIParserNode* nsNodeAllocator::CreateNode(CToken* aToken,PRInt32 aLineNumber,ns
result->Init(aToken,aLineNumber,aTokenAllocator,this);
}
else{
result=new nsCParserNode(aToken,aLineNumber,aTokenAllocator,this);
result=nsCParserNode::Create(aToken,aLineNumber,aTokenAllocator,this);
#ifdef DEBUG_TRACK_NODES
mCount++;
AddNode(NS_STATIC_CAST(nsCParserNode*,result));
#endif
NS_IF_ADDREF(result);
IF_HOLD(result);
}
#else
result=new(mNodePool) nsCParserNode(aToken,aLineNumber,aTokenAllocator);
NS_IF_ADDREF(result);
result=nsCParserNode::Create(aToken,aLineNumber,aTokenAllocator,this);
IF_HOLD(result);
#endif
return NS_STATIC_CAST(nsIParserNode*,result);
return result;
}
void DebugDumpContainmentRules(nsIDTD& theDTD,const char* aFilename,const char* aTitle) {

View File

@ -46,7 +46,7 @@
#include "nsVoidArray.h"
#define IF_HOLD(_ptr) if(_ptr) { _ptr->AddRef(); }
#define IF_FREE(_ptr) if(_ptr) { _ptr->Release(); _ptr=0; } // recycles _ptr
#define IF_FREE(_ptr, _allocator) if(_ptr) { _ptr->Release((_allocator)->GetArenaPool()); _ptr=0; } // recycles _ptr
class nsIParserNode;
class nsCParserNode;
@ -67,7 +67,7 @@ class nsEntryStack; //forware declare to make compilers happy.
struct nsTagEntry {
eHTMLTags mTag; //for speedier access to tag id
nsIParserNode* mNode;
nsCParserNode* mNode;
nsEntryStack* mParent;
nsEntryStack* mStyles;
};
@ -78,12 +78,12 @@ public:
~nsEntryStack();
void EnsureCapacityFor(PRInt32 aNewMax, PRInt32 aShiftOffset=0);
void Push(const nsIParserNode* aNode,nsEntryStack* aStyleStack=0);
void PushFront(const nsIParserNode* aNode,nsEntryStack* aStyleStack=0);
void Push(const nsCParserNode* aNode,nsEntryStack* aStyleStack=0);
void PushFront(const nsCParserNode* aNode,nsEntryStack* aStyleStack=0);
void Append(nsEntryStack *theStack);
nsIParserNode* Pop(void);
nsIParserNode* Remove(PRInt32 anIndex,eHTMLTags aTag);
nsIParserNode* NodeAt(PRInt32 anIndex) const;
nsCParserNode* Pop(void);
nsCParserNode* Remove(PRInt32 anIndex,eHTMLTags aTag);
nsCParserNode* NodeAt(PRInt32 anIndex) const;
eHTMLTags First() const;
eHTMLTags TagAt(PRInt32 anIndex) const;
nsTagEntry* EntryAt(PRInt32 anIndex) const;
@ -229,6 +229,8 @@ public:
virtual CToken* CreateTokenOfType(eHTMLTokenTypes aType,eHTMLTags aTag, const nsAReadableString& aString);
virtual CToken* CreateTokenOfType(eHTMLTokenTypes aType,eHTMLTags aTag);
nsFixedSizeAllocator& GetArenaPool() { return mArenaPool; }
protected:
nsFixedSizeAllocator mArenaPool;
@ -245,23 +247,30 @@ protected:
that get created during the run of the system.
************************************************************************/
#ifndef HEAP_ALLOCATED_NODES
class nsCParserNode;
#endif
class nsNodeAllocator {
public:
nsNodeAllocator();
virtual ~nsNodeAllocator();
virtual nsIParserNode* CreateNode(CToken* aToken=nsnull,PRInt32 aLineNumber=1,nsTokenAllocator* aTokenAllocator=0);
virtual nsCParserNode* CreateNode(CToken* aToken=nsnull,PRInt32 aLineNumber=1,nsTokenAllocator* aTokenAllocator=0);
nsFixedSizeAllocator& GetArenaPool() { return mNodePool; }
#ifdef HEAP_ALLOCATED_NODES
void Recycle(nsIParserNode* aNode) { mSharedNodes.Push(NS_STATIC_CAST(void*,aNode)); }
void Recycle(nsCParserNode* aNode) { mSharedNodes.Push(NS_STATIC_CAST(void*,aNode)); }
protected:
nsDeque mSharedNodes;
#ifdef DEBUG_TRACK_NODES
PRInt32 mCount;
#endif
#else
#endif
protected:
nsFixedSizeAllocator mNodePool;
#endif
};
/************************************************************************
@ -273,10 +282,10 @@ public:
nsDTDContext();
~nsDTDContext();
void Push(const nsIParserNode* aNode,nsEntryStack* aStyleStack=0);
nsIParserNode* Pop(nsEntryStack*& aChildStack);
nsIParserNode* Pop();
nsIParserNode* PeekNode() { return mStack.NodeAt(mStack.mCount-1); }
void Push(const nsCParserNode* aNode,nsEntryStack* aStyleStack=0);
nsCParserNode* Pop(nsEntryStack*& aChildStack);
nsCParserNode* Pop();
nsCParserNode* PeekNode() { return mStack.NodeAt(mStack.mCount-1); }
eHTMLTags First(void) const;
eHTMLTags Last(void) const;
nsTagEntry* LastEntry(void) const;
@ -290,11 +299,11 @@ public:
PRInt32 GetCount(void) {return mStack.mCount;}
PRInt32 GetResidualStyleCount(void) {return mResidualStyleCount;}
nsEntryStack* GetStylesAt(PRInt32 anIndex) const;
void PushStyle(const nsIParserNode* aNode);
void PushStyle(const nsCParserNode* aNode);
void PushStyles(nsEntryStack *theStyles);
nsIParserNode* PopStyle(void);
nsIParserNode* PopStyle(eHTMLTags aTag);
nsIParserNode* RemoveStyle(eHTMLTags aTag);
nsCParserNode* PopStyle(void);
nsCParserNode* PopStyle(eHTMLTags aTag);
nsCParserNode* RemoveStyle(eHTMLTags aTag);
static void ReleaseGlobalObjects(void);
@ -342,10 +351,16 @@ public:
Now define the token deallocator class...
**************************************************************/
class CTokenDeallocator: public nsDequeFunctor{
protected:
nsFixedSizeAllocator& mArenaPool;
public:
CTokenDeallocator(nsFixedSizeAllocator& aArenaPool)
: mArenaPool(aArenaPool) {}
virtual void* operator()(void* anObject) {
CToken* aToken = (CToken*)anObject;
delete aToken;
CToken::Destroy(aToken, mArenaPool);
return 0;
}
};

View File

@ -234,7 +234,7 @@ NS_IMETHODIMP nsExpatDTD::BuildModel(nsIParser* aParser,nsITokenizer* aTokenizer
if(theToken) {
result=HandleToken(theToken,aParser);
if(NS_SUCCEEDED(result)) {
IF_FREE(theToken);
IF_FREE(theToken, mTokenizer->GetTokenAllocator());
}
else if(NS_ERROR_HTMLPARSER_BLOCK!=result){
mTokenizer->PushTokenFront(theToken);

View File

@ -133,7 +133,7 @@ NS_IMPL_RELEASE(nsHTMLTokenizer)
*/
nsHTMLTokenizer::~nsHTMLTokenizer(){
if(mTokenDeque.GetSize()){
CTokenDeallocator theDeallocator;
CTokenDeallocator theDeallocator(mTokenAllocator->GetArenaPool());
mTokenDeque.ForEach(theDeallocator);
}
}
@ -149,7 +149,7 @@ void nsHTMLTokenizer::AddToken(CToken*& aToken,nsresult aResult,nsDeque* aDeque,
aDeque->Push(aToken);
}
else {
IF_FREE(aToken);
IF_FREE(aToken, aTokenAllocator);
}
}
}
@ -589,12 +589,12 @@ nsresult nsHTMLTokenizer::ConsumeAttributes(PRUnichar aChar,CStartToken* aToken,
AddToken((CToken*&)theToken,result,&mTokenDeque,theAllocator);
}
else {
IF_FREE(theToken);
IF_FREE(theToken, mTokenAllocator);
}
}
else { //if(NS_ERROR_HTMLPARSER_BADATTRIBUTE==result){
aToken->SetEmpty(PR_TRUE);
IF_FREE(theToken);
IF_FREE(theToken, mTokenAllocator);
if(NS_ERROR_HTMLPARSER_BADATTRIBUTE==result)
result=NS_OK;
}
@ -728,7 +728,7 @@ nsresult nsHTMLTokenizer::ConsumeStartTag(PRUnichar aChar,CToken*& aToken,nsScan
AddToken(endToken,result,&mTokenDeque,theAllocator);
}
else {
IF_FREE(text);
IF_FREE(text, mTokenAllocator);
}
}
}
@ -742,11 +742,11 @@ nsresult nsHTMLTokenizer::ConsumeStartTag(PRUnichar aChar,CToken*& aToken,nsScan
if(!NS_SUCCEEDED(result)) {
while(mTokenDeque.GetSize()>theDequeSize) {
CToken* theToken=(CToken*)mTokenDeque.Pop();
IF_FREE(theToken);
IF_FREE(theToken, mTokenAllocator);
}
}
} //if
else IF_FREE(aToken);
else IF_FREE(aToken, mTokenAllocator);
} //if
return result;
}
@ -900,7 +900,7 @@ nsresult nsHTMLTokenizer::ConsumeText(CToken*& aToken,nsScanner& aScanner){
result=theToken->Consume(ch,aScanner,mParseMode);
if(!NS_SUCCEEDED(result)) {
if(0==theToken->GetTextLength()){
IF_FREE(aToken);
IF_FREE(aToken, mTokenAllocator);
aToken = nsnull;
}
else result=NS_OK;

View File

@ -114,6 +114,8 @@ protected:
* @update gess 3/25/98
*/
class CStartToken: public CHTMLToken {
CTOKEN_IMPL_SIZEOF
public:
CStartToken(eHTMLTags aTag=eHTMLTag_unknown);
CStartToken(const nsAReadableString& aString);
@ -168,6 +170,8 @@ class CStartToken: public CHTMLToken {
* @update gess 3/25/98
*/
class CEndToken: public CHTMLToken {
CTOKEN_IMPL_SIZEOF
public:
CEndToken(eHTMLTags aTag);
CEndToken(const nsAReadableString& aString);
@ -195,6 +199,8 @@ class CEndToken: public CHTMLToken {
* @update gess 3/25/98
*/
class CCommentToken: public CHTMLToken {
CTOKEN_IMPL_SIZEOF
public:
CCommentToken();
CCommentToken(const nsAReadableString& aString);
@ -217,6 +223,8 @@ class CCommentToken: public CHTMLToken {
* @update gess 3/25/98
*/
class CEntityToken : public CHTMLToken {
CTOKEN_IMPL_SIZEOF
public:
CEntityToken();
CEntityToken(const nsAReadableString& aString);
@ -244,6 +252,8 @@ class CEntityToken : public CHTMLToken {
* @update gess 3/25/98
*/
class CWhitespaceToken: public CHTMLToken {
CTOKEN_IMPL_SIZEOF
public:
CWhitespaceToken();
CWhitespaceToken(const nsAReadableString& aString);
@ -264,6 +274,8 @@ class CWhitespaceToken: public CHTMLToken {
* @update gess 3/25/98
*/
class CTextToken: public CHTMLToken {
CTOKEN_IMPL_SIZEOF
public:
CTextToken();
CTextToken(const nsAReadableString& aString);
@ -291,6 +303,8 @@ class CTextToken: public CHTMLToken {
* @update vidur 11/12/98
*/
class CCDATASectionToken : public CHTMLToken {
CTOKEN_IMPL_SIZEOF
public:
CCDATASectionToken();
CCDATASectionToken(const nsAReadableString& aString);
@ -311,6 +325,8 @@ public:
*
*/
class CMarkupDeclToken : public CHTMLToken {
CTOKEN_IMPL_SIZEOF
public:
CMarkupDeclToken();
CMarkupDeclToken(const nsAReadableString& aString);
@ -333,6 +349,8 @@ protected:
* @update gess 3/25/98
*/
class CAttributeToken: public CHTMLToken {
CTOKEN_IMPL_SIZEOF
public:
CAttributeToken();
CAttributeToken(const nsAReadableString& aString);
@ -367,6 +385,8 @@ class CAttributeToken: public CHTMLToken {
* @update gess 3/25/98
*/
class CNewlineToken: public CHTMLToken {
CTOKEN_IMPL_SIZEOF
public:
CNewlineToken();
virtual nsresult Consume(PRUnichar aChar,nsScanner& aScanner,PRInt32 aMode);
@ -389,6 +409,8 @@ class CNewlineToken: public CHTMLToken {
* @update gess 3/25/98
*/
class CScriptToken: public CHTMLToken {
CTOKEN_IMPL_SIZEOF
public:
CScriptToken();
CScriptToken(const nsAReadableString& aString);
@ -410,6 +432,8 @@ class CScriptToken: public CHTMLToken {
* @update gess 3/25/98
*/
class CStyleToken: public CHTMLToken {
CTOKEN_IMPL_SIZEOF
public:
CStyleToken();
CStyleToken(const nsAReadableString& aString);
@ -430,6 +454,8 @@ class CStyleToken: public CHTMLToken {
* @update gess 3/25/98
*/
class CInstructionToken: public CHTMLToken {
CTOKEN_IMPL_SIZEOF
public:
CInstructionToken();
CInstructionToken(const nsAReadableString& aString);
@ -443,6 +469,8 @@ class CInstructionToken: public CHTMLToken {
};
class CErrorToken : public CHTMLToken {
CTOKEN_IMPL_SIZEOF
public:
CErrorToken(nsParserError* aError=0);
~CErrorToken();
@ -469,6 +497,8 @@ protected:
*/
class CDoctypeDeclToken: public CHTMLToken {
CTOKEN_IMPL_SIZEOF
public:
CDoctypeDeclToken(eHTMLTags aTag=eHTMLTag_unknown);
CDoctypeDeclToken(const nsAReadableString& aString,eHTMLTags aTag=eHTMLTag_unknown);

View File

@ -65,7 +65,7 @@ class CToken;
*
* @update gess 3/25/98
*/
class nsIParserNode : public nsISupports {
class nsIParserNode { // XXX Should be nsAParserNode
public:

View File

@ -48,7 +48,7 @@ const nsString& GetEmptyString() {
*/
nsCParserNode::nsCParserNode(CToken* aToken,PRInt32 aLineNumber,nsTokenAllocator* aTokenAllocator,nsNodeAllocator* aNodeAllocator):
nsIParserNode() {
NS_INIT_REFCNT();
mRefCnt = 0;
MOZ_COUNT_CTOR(nsCParserNode);
static int theNodeCount=0;
@ -88,9 +88,6 @@ nsCParserNode::~nsCParserNode() {
}
NS_IMPL_ADDREF(nsCParserNode)
NS_IMPL_RELEASE(nsCParserNode)
/**
* Init
*
@ -105,7 +102,7 @@ nsresult nsCParserNode::Init(CToken* aToken,PRInt32 aLineNumber,nsTokenAllocator
if(mAttributes && (mAttributes->GetSize())) {
CToken* theAttrToken=0;
while((theAttrToken=NS_STATIC_CAST(CToken*,mAttributes->Pop()))) {
IF_FREE(theAttrToken);
IF_FREE(theAttrToken, aTokenAllocator);
}
}
mToken=aToken;
@ -121,40 +118,6 @@ nsresult nsCParserNode::Init(CToken* aToken,PRInt32 aLineNumber,nsTokenAllocator
return NS_OK;
}
/**
* This method gets called as part of our COM-like interfaces.
* Its purpose is to create an interface to parser object
* of some type.
*
* @update gess 3/25/98
* @param nsIID id of object to discover
* @param aInstancePtr ptr to newly discovered interface
* @return NS_xxx result code
*/
nsresult nsCParserNode::QueryInterface(const nsIID& aIID, void** aInstancePtr)
{
if (NULL == aInstancePtr) {
return NS_ERROR_NULL_POINTER;
}
if(aIID.Equals(kISupportsIID)) { //do IUnknown...
*aInstancePtr = (nsIParserNode*)(this);
}
else if(aIID.Equals(kIParserNodeIID)) { //do IParser base class...
*aInstancePtr = (nsIParserNode*)(this);
}
else if(aIID.Equals(kClassIID)) { //do this class...
*aInstancePtr = (nsCParserNode*)(this);
}
else {
*aInstancePtr=0;
return NS_NOINTERFACE;
}
NS_ADDREF_THIS();
return NS_OK;
}
/**
* Causes the given attribute to be added to internal
* mAttributes list, and mAttributeCount to be incremented.
@ -380,7 +343,7 @@ nsresult nsCParserNode::ReleaseAll() {
if(mAttributes) {
CToken* theAttrToken=0;
while((theAttrToken=NS_STATIC_CAST(CToken*,mAttributes->Pop()))) {
IF_FREE(theAttrToken);
IF_FREE(theAttrToken, mTokenAllocator);
}
delete mAttributes;
mAttributes=0;
@ -389,7 +352,7 @@ nsresult nsCParserNode::ReleaseAll() {
delete mSkippedContent;
mSkippedContent=0;
}
IF_FREE(mToken);
IF_FREE(mToken, mTokenAllocator);
return NS_OK;
}

View File

@ -50,40 +50,59 @@
class nsTokenAllocator;
class nsCParserNode : public nsIParserNode {
protected:
PRInt32 mRefCnt;
public:
NS_DECL_ISUPPORTS
void AddRef()
{
++mRefCnt;
}
#ifdef HEAP_ALLOCATED_NODES
void* operator new(size_t aSize) {
return ::operator new(aSize);
}
#else
/**
*
* @update harishd 01/01/01
* @param aSize -
* @param aArena - Allocate memory from this pool.
*/
static void * operator new (size_t aSize, nsFixedSizeAllocator& anArena)
void Release(nsFixedSizeAllocator& aPool)
{
return anArena.Alloc(aSize);
if (--mRefCnt == 0)
Destroy(this, aPool);
}
#endif
/**
*
*
* @update harishd 01/01/01
* @param aPtr - The memory that should be recycled/freed.
* @param aSize - The size of memory that needs to be freed.
*/
static void operator delete (void* aPtr,size_t aSize)
{
// NodeAllocator would take care of heap allocated nodes..
#ifndef HEAP_ALLOCATED_NODES
nsFixedSizeAllocator::Free(aPtr,aSize);
private:
/**
* Hide operator new; clients should use Create() instead.
*/
static void* operator new(size_t) { return 0; }
/**
* Hide operator delete; clients should use Destroy() instead.
*/
static void operator delete(void*,size_t) {}
#endif
public:
static nsCParserNode* Create(CToken* aToken,PRInt32 aLineNumber,nsTokenAllocator* aTokenAllocator,nsNodeAllocator* aNodeAllocator)
{
#ifdef HEAP_ALLOCATED_NODES
return new
#else
nsFixedSizeAllocator& pool = aNodeAllocator->GetArenaPool();
void* place = pool.Alloc(sizeof(nsCParserNode));
return ::new (place)
#endif
nsCParserNode(aToken, aLineNumber, aTokenAllocator, aNodeAllocator);
}
static void Destroy(nsCParserNode* aNode, nsFixedSizeAllocator& aPool)
{
#ifdef HEAP_ALLOCATED_NODES
delete aNode;
#else
aNode->~nsCParserNode();
aPool.Free(aNode, sizeof(*aNode));
#endif
}
@ -248,7 +267,6 @@ class nsCParserNode : public nsIParserNode {
#ifdef HEAP_ALLOCATED_NODES
nsNodeAllocator* mNodeAllocator; // weak
#endif
};
#endif

View File

@ -33,6 +33,20 @@
* of that particular token type gets detected in the
* input stream.
*
* CToken objects that are allocated from the heap _must_ be allocated
* using the nsTokenAllocator: the nsTokenAllocator object uses an
* arena to manage the tokens.
*
* The nsTokenAllocator object's arena implementation requires
* object size at destruction time to properly recycle the object;
* therefore, CToken::operator delete() is not public. Instead,
* heap-allocated tokens should be destroyed using the static
* Destroy() method, which accepts a token and the arena from which
* the token was allocated.
*
* Leaf classes (that are actually instantiated from the heap) must
* implement the SizeOf() method, which Destroy() uses to determine
* the size of the token in order to properly recycle it.
*/
@ -45,9 +59,8 @@
#include "nsFileSpec.h"
#include "nsFixedSizeAllocator.h"
class nsScanner;
class nsTokenAllocator;
enum eContainerInfo {
eWellFormed,
@ -55,6 +68,14 @@ enum eContainerInfo {
eFormUnknown
};
/**
* Implement the SizeOf() method; leaf classes derived from CToken
* must declare this.
*/
#define CTOKEN_IMPL_SIZEOF \
protected: \
virtual size_t SizeOf() const { return sizeof(*this); } \
public:
/**
* Token objects represent sequences of characters as they
@ -70,27 +91,43 @@ class CToken {
enum eTokenOrigin {eSource,eResidualStyle};
protected:
// nsTokenAllocator should be the only class that tries to
// allocate tokens from the heap.
friend class nsTokenAllocator;
/**
*
* @update harishd 08/01/00
* @param aSize -
* @param aArena - Allocate memory from this pool.
*/
static void * operator new (size_t aSize, nsFixedSizeAllocator& anArena)
static void * operator new (size_t aSize,nsFixedSizeAllocator& anArena)
{
return anArena.Alloc(aSize);
}
/**
*
*
* @update harishd 08/01/00
* @param aPtr - The memory that should be recycled/freed.
* @param aSize - The size of memory that needs to be freed.
* Hide operator delete; clients should use Destroy() instead.
*/
static void operator delete (void* aPtr,size_t aSize)
static void operator delete (void*,size_t) {}
public:
/**
* destructor
* @update gess5/11/98
*/
virtual ~CToken();
/**
* Destroy a token.
*/
static void Destroy(CToken* aToken,nsFixedSizeAllocator& aArenaPool)
{
nsFixedSizeAllocator::Free(aPtr,aSize);
size_t sz = aToken->SizeOf();
aToken->~CToken();
aArenaPool.Free(aToken, sz);
}
/**
@ -103,22 +140,17 @@ class CToken {
* Free yourself if no one is holding you.
* @update harishd 08/02/00
*/
void Release() {
void Release(nsFixedSizeAllocator& aArenaPool) {
if(--mUseCount==0)
delete this;
Destroy(this, aArenaPool);
}
/**
* Default constructor
* @update gess7/21/98
*/
CToken(PRInt32 aTag=0);
/**
* destructor
* @update gess5/11/98
*/
virtual ~CToken();
/**
* Retrieve string value of the token
* @update gess5/11/98
@ -229,6 +261,10 @@ class CToken {
PRInt32 mNewlineCount;
protected:
/**
* Returns the size of the token object.
*/
virtual size_t SizeOf() const = 0;
PRInt32 mTypeID;
PRInt16 mAttrCount;

View File

@ -534,7 +534,7 @@ NS_IMETHODIMP CViewSourceHTML::BuildModel(nsIParser* aParser,nsITokenizer* aToke
if(theToken) {
result=HandleToken(theToken,aParser);
if(NS_SUCCEEDED(result)) {
IF_FREE(theToken);
IF_FREE(theToken, mTokenizer->GetTokenAllocator());
}
else if(NS_ERROR_HTMLPARSER_BLOCK!=result){
mTokenizer->PushTokenFront(theToken);

View File

@ -258,7 +258,7 @@ NS_IMETHODIMP CWellFormedDTD::BuildModel(nsIParser* aParser,nsITokenizer* aToken
if(theToken) {
result=HandleToken(theToken,aParser);
if(NS_SUCCEEDED(result) || (NS_ERROR_HTMLPARSER_BLOCK==result)) {
IF_FREE(theToken);
IF_FREE(theToken, mTokenizer->GetTokenAllocator());
}
else {
// if(NS_ERROR_HTMLPARSER_BLOCK!=result){
@ -362,7 +362,7 @@ nsresult CWellFormedDTD::Terminate(nsIParser* aParser)
if(theType==eToken_error) {
result=HandleToken(theToken,aParser);
}
IF_FREE(theToken);
IF_FREE(theToken, mTokenizer->GetTokenAllocator());
}
else break;
}//while
@ -717,7 +717,7 @@ nsresult CWellFormedDTD::HandleErrorToken(CToken* aToken) {
// Do nothing
break;
}
IF_FREE(token);
IF_FREE(token, mTokenizer->GetTokenAllocator());
}
else
break;

View File

@ -196,8 +196,8 @@ void CNavDTD::RecycleNodes(nsEntryStack *aNodeStack) {
PRInt32 theIndex=0;
for(theIndex=0;theIndex<theCount;theIndex++) {
nsIParserNode* node=aNodeStack->NodeAt(theIndex);
NS_IF_RELEASE(node);
nsCParserNode* node=aNodeStack->NodeAt(theIndex);
IF_FREE(node, &mNodeAllocator);
}
}
}
@ -587,12 +587,12 @@ nsresult CNavDTD::DidBuildModel(nsresult anErrorCode,PRBool aNotifySink,nsIParse
while(mBodyContext->GetCount() > 0) {
nsEntryStack *theChildStyles=0;
nsIParserNode* theNode=mBodyContext->Pop(theChildStyles);
nsCParserNode* theNode=mBodyContext->Pop(theChildStyles);
if(theNode) {
if(theChildStyles) {
delete theChildStyles;
}
NS_IF_RELEASE(theNode);
IF_FREE(theNode, &mNodeAllocator);
}
}
}
@ -637,7 +637,7 @@ nsresult CNavDTD::DidBuildModel(nsresult anErrorCode,PRBool aNotifySink,nsIParse
CToken* theToken=0;
while((theToken=(CToken*)mMisplacedContent.Pop())) {
IF_FREE(theToken);
IF_FREE(theToken, mTokenAllocator);
}
if(mDTDDebug) {
@ -726,7 +726,7 @@ nsresult CNavDTD::HandleToken(CToken* aToken,nsIParser* aParser){
mSkipTarget=eHTMLTag_unknown; //stop skipping.
//mTokenizer->PushTokenFront(aToken); //push the end token...
execSkipContent=PR_TRUE;
IF_FREE(aToken);
IF_FREE(aToken, mTokenAllocator);
theToken=(CHTMLToken*)mSkippedContent.PopFront();
theType=eToken_start;
}
@ -741,7 +741,7 @@ nsresult CNavDTD::HandleToken(CToken* aToken,nsIParser* aParser){
if(theType!=eToken_attribute) {
aToken->AppendSource(mScratch);
}
IF_FREE(aToken);
IF_FREE(aToken, mTokenAllocator);
return result;
}
else {
@ -889,7 +889,7 @@ nsresult CNavDTD::HandleToken(CToken* aToken,nsIParser* aParser){
if(NS_SUCCEEDED(result) || (NS_ERROR_HTMLPARSER_BLOCK==result)) {
IF_FREE(theToken);
IF_FREE(theToken, mTokenAllocator);
}
else if(result==NS_ERROR_HTMLPARSER_STOPPARSING) {
mDTDState=result;
@ -937,7 +937,7 @@ nsresult CNavDTD::DidHandleStartTag(nsIParserNode& aNode,eHTMLTags aChildTag){
if(eToken_newline==theType){
mLineNumber++;
theNextToken=mTokenizer->PopToken(); //skip 1st newline inside PRE and LISTING
IF_FREE(theNextToken); // fix for Bug 29379
IF_FREE(theNextToken, mTokenAllocator); // fix for Bug 29379
}//if
}//if
}
@ -1019,7 +1019,7 @@ nsresult CNavDTD::DidHandleStartTag(nsIParserNode& aNode,eHTMLTags aChildTag){
CToken *theEndToken=mTokenAllocator->CreateTokenOfType(eToken_end,aChildTag);
if(theEndToken) {
result=HandleEndToken(theEndToken);
IF_FREE(theEndToken);
IF_FREE(theEndToken, mTokenAllocator);
}
}
}
@ -1172,7 +1172,7 @@ enum eProcessRule {eNormalOp,eLetInlineContainBlock};
* @param aNode -- CParserNode representing this start token
* @return PR_TRUE if all went well; PR_FALSE if error occured
*/
nsresult CNavDTD::HandleDefaultStartToken(CToken* aToken,eHTMLTags aChildTag,nsIParserNode *aNode) {
nsresult CNavDTD::HandleDefaultStartToken(CToken* aToken,eHTMLTags aChildTag,nsCParserNode *aNode) {
NS_PRECONDITION(0!=aToken,kNullToken);
nsresult result=NS_OK;
@ -1607,7 +1607,7 @@ nsresult CNavDTD::HandleStartToken(CToken* aToken) {
//Begin by gathering up attributes...
nsIParserNode* theNode=mNodeAllocator.CreateNode(aToken,mLineNumber,mTokenAllocator);
nsCParserNode* theNode=mNodeAllocator.CreateNode(aToken,mLineNumber,mTokenAllocator);
eHTMLTags theChildTag=(eHTMLTags)aToken->GetTypeID();
PRInt16 attrCount=aToken->GetAttributeCount();
@ -1724,7 +1724,7 @@ nsresult CNavDTD::HandleStartToken(CToken* aToken) {
result=NS_OK;
}
NS_IF_RELEASE(theNode);
IF_FREE(theNode, &mNodeAllocator);
return result;
}
@ -1850,7 +1850,7 @@ static void StripWSFollowingTag(eHTMLTags aChildTag,nsITokenizer* aTokenizer,nsT
case eToken_newline: aNewlineCount++;
case eToken_whitespace:
theToken=aTokenizer->PopToken();
IF_FREE(theToken);
IF_FREE(theToken, aTokenAllocator);
theToken=aTokenizer->PeekToken();
break;
default:
@ -2039,9 +2039,9 @@ nsresult CNavDTD::HandleSavedTokens(PRInt32 anIndex) {
nsEntryStack* theChildStyleStack=0;
for(i=0; i<(theTagCount - theTopIndex); i++) {
nsIParserNode* node=mBodyContext->Pop(theChildStyleStack);
nsCParserNode* node=mBodyContext->Pop(theChildStyleStack);
mTempContext->Push(node);
NS_IF_RELEASE(node); //release the popped node since push will addref for us.
IF_FREE(node, &mNodeAllocator); //release the popped node since push will addref for us.
}
// Now flush out all the bad contents.
@ -2068,7 +2068,7 @@ nsresult CNavDTD::HandleSavedTokens(PRInt32 anIndex) {
PRInt32 theIndex=mBodyContext->LastOf(theTag);
if(theIndex!=kNotFound && theIndex<=mBodyContext->mContextTopIndex) {
IF_FREE(theToken);
IF_FREE(theToken, mTokenAllocator);
continue;
}
}
@ -2082,9 +2082,9 @@ nsresult CNavDTD::HandleSavedTokens(PRInt32 anIndex) {
// Bad-contents were successfully processed. Now, itz time to get
// back to the original body context state.
for(PRInt32 k=0; k<(theTagCount - theTopIndex); k++) {
nsIParserNode* node=mTempContext->Pop(theChildStyleStack);
nsCParserNode* node=mTempContext->Pop(theChildStyleStack);
mBodyContext->Push(node);
NS_IF_RELEASE(node);
IF_FREE(node, &mNodeAllocator);
}
STOP_TIMER()
@ -2135,7 +2135,7 @@ nsresult CNavDTD::HandleEntityToken(CToken* aToken) {
eHTMLTags theParentTag=mBodyContext->Last();
nsIParserNode* theNode=mNodeAllocator.CreateNode(aToken,mLineNumber,0);
nsCParserNode* theNode=mNodeAllocator.CreateNode(aToken,mLineNumber,0);
if(theNode) {
PRBool theParentContains=-1; //set to -1 to force CanOmit to recompute...
if(CanOmit(theParentTag,eHTMLTag_entity,theParentContains)) {
@ -2148,7 +2148,7 @@ nsresult CNavDTD::HandleEntityToken(CToken* aToken) {
#endif
result=AddLeaf(theNode);
}
NS_IF_RELEASE(theNode);
IF_FREE(theNode, &mNodeAllocator);
}
return result;
}
@ -2172,7 +2172,7 @@ nsresult CNavDTD::HandleCommentToken(CToken* aToken) {
const nsAReadableString& theComment = theToken->GetStringValue();
mLineNumber += CountCharInReadable(theComment, PRUnichar(kNewLine));
nsIParserNode* theNode=mNodeAllocator.CreateNode(aToken,mLineNumber,0);
nsCParserNode* theNode=mNodeAllocator.CreateNode(aToken,mLineNumber,0);
if(theNode) {
#ifdef RICKG_DEBUG
@ -2184,7 +2184,7 @@ nsresult CNavDTD::HandleCommentToken(CToken* aToken) {
result=(mSink) ? mSink->AddComment(*theNode) : NS_OK;
NS_IF_RELEASE(theNode);
IF_FREE(theNode, &mNodeAllocator);
MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::HandleCommentToken(), this=%p\n", this));
START_TIMER();
@ -2248,7 +2248,7 @@ nsresult CNavDTD::HandleProcessingInstructionToken(CToken* aToken){
nsresult result=NS_OK;
nsIParserNode* theNode=mNodeAllocator.CreateNode(aToken,mLineNumber,0);
nsCParserNode* theNode=mNodeAllocator.CreateNode(aToken,mLineNumber,0);
if(theNode) {
#ifdef RICKG_DEBUG
@ -2260,7 +2260,7 @@ nsresult CNavDTD::HandleProcessingInstructionToken(CToken* aToken){
result=(mSink) ? mSink->AddProcessingInstruction(*theNode) : NS_OK;
NS_IF_RELEASE(theNode);
IF_FREE(theNode, &mNodeAllocator);
MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::HandleProcessingInstructionToken(), this=%p\n", this));
START_TIMER();
@ -2298,7 +2298,7 @@ nsresult CNavDTD::HandleDocTypeDeclToken(CToken* aToken){
docTypeStr.Cut(0,2); // Now remove "<!" from the begining
theToken->SetStringValue(docTypeStr);
nsIParserNode* theNode=mNodeAllocator.CreateNode(aToken,mLineNumber,0);
nsCParserNode* theNode=mNodeAllocator.CreateNode(aToken,mLineNumber,0);
if(theNode) {
STOP_TIMER();
@ -2321,7 +2321,7 @@ nsresult CNavDTD::HandleDocTypeDeclToken(CToken* aToken){
result = (mSink)? mSink->AddDocTypeDecl(*theNode,theMode):NS_OK;
NS_IF_RELEASE(theNode);
IF_FREE(theNode, &mNodeAllocator);
MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::HandleDocTypeDeclToken(), this=%p\n", this));
START_TIMER();
@ -2431,7 +2431,7 @@ nsresult CNavDTD::CollectSkippedContent(nsIParserNode& aNode,PRInt32 &aCount) {
}
else theNextToken->AppendSource(*theNode->mSkippedContent);
}
IF_FREE(theNextToken);
IF_FREE(theNextToken, mTokenAllocator);
}
// if the string contained CRs (hence is either CR, or CRLF terminated)
@ -2899,8 +2899,8 @@ nsresult CNavDTD::OpenTransientStyles(eHTMLTags aChildTag){
}
else {
//if the node tag can't contain the child tag, then remove the child tag from the style stack
nsIParserNode* node=theStack->Remove(sindex,theNodeTag);
NS_IF_RELEASE(node);
nsCParserNode* node=theStack->Remove(sindex,theNodeTag);
IF_FREE(node, &mNodeAllocator);
theEntry--; //back up by one
}
} //if
@ -2967,8 +2967,8 @@ nsresult CNavDTD::PopStyle(eHTMLTags aTag){
if(mFlags & NS_PARSER_FLAG_ENABLE_RESIDUAL_STYLE) {
#ifdef ENABLE_RESIDUALSTYLE
if(nsHTMLElement::IsResidualStyleTag(aTag)) {
nsIParserNode* node=mBodyContext->PopStyle(aTag);
NS_IF_RELEASE(node);
nsCParserNode* node=mBodyContext->PopStyle(aTag);
IF_FREE(node, &mNodeAllocator);
}
#endif
} //if
@ -2984,7 +2984,7 @@ nsresult CNavDTD::PopStyle(eHTMLTags aTag){
* @update gess4/22/98
* @param aNode -- next node to be added to model
*/
nsresult CNavDTD::OpenHTML(const nsIParserNode *aNode){
nsresult CNavDTD::OpenHTML(const nsCParserNode *aNode){
NS_PRECONDITION(mBodyContext->GetCount() >= 0, kInvalidTagStackPos);
STOP_TIMER();
@ -3084,7 +3084,7 @@ nsresult CNavDTD::CloseHead(const nsIParserNode *aNode){
* @param aNode -- next node to be added to model
* @return TRUE if ok, FALSE if error
*/
nsresult CNavDTD::OpenBody(const nsIParserNode *aNode){
nsresult CNavDTD::OpenBody(const nsCParserNode *aNode){
NS_PRECONDITION(mBodyContext->GetCount() >= 0, kInvalidTagStackPos);
nsresult result=NS_OK;
@ -3209,7 +3209,7 @@ nsresult CNavDTD::CloseForm(const nsIParserNode *aNode){
* @param aNode -- next node to be added to model
* @return TRUE if ok, FALSE if error
*/
nsresult CNavDTD::OpenMap(const nsIParserNode *aNode){
nsresult CNavDTD::OpenMap(const nsCParserNode *aNode){
STOP_TIMER();
MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::OpenMap(), this=%p\n", this));
@ -3260,7 +3260,7 @@ nsresult CNavDTD::CloseMap(const nsIParserNode *aNode){
* @param aNode -- next node to be added to model
* @return TRUE if ok, FALSE if error
*/
nsresult CNavDTD::OpenFrameset(const nsIParserNode *aNode){
nsresult CNavDTD::OpenFrameset(const nsCParserNode *aNode){
NS_PRECONDITION(mBodyContext->GetCount() >= 0, kInvalidTagStackPos);
mFlags |= NS_PARSER_FLAG_HAD_FRAMESET;
@ -3308,7 +3308,7 @@ nsresult CNavDTD::CloseFrameset(const nsIParserNode *aNode){
* @param aNode - The noscript node
* return NS_OK if succeeded else ERROR
*/
nsresult CNavDTD::OpenNoscript(const nsIParserNode *aNode,nsEntryStack* aStyleStack) {
nsresult CNavDTD::OpenNoscript(const nsCParserNode *aNode,nsEntryStack* aStyleStack) {
nsresult result=NS_OK;
if(mSink) {
@ -3381,7 +3381,7 @@ nsresult CNavDTD::CloseNoscript(const nsIParserNode *aNode) {
* @return TRUE if ok, FALSE if error
*/
nsresult
CNavDTD::OpenContainer(const nsIParserNode *aNode,eHTMLTags aTag,PRBool aClosedByStartTag,nsEntryStack* aStyleStack){
CNavDTD::OpenContainer(const nsCParserNode *aNode,eHTMLTags aTag,PRBool aClosedByStartTag,nsEntryStack* aStyleStack){
NS_PRECONDITION(mBodyContext->GetCount() >= 0, kInvalidTagStackPos);
nsresult result=NS_OK;
@ -3505,7 +3505,7 @@ CNavDTD::OpenContainer(const nsIParserNode *aNode,eHTMLTags aTag,PRBool aClosedB
* @return TRUE if ok, FALSE if error
*/
nsresult
CNavDTD::CloseContainer(const nsIParserNode *aNode,eHTMLTags aTarget,PRBool aClosedByStartTag){
CNavDTD::CloseContainer(const nsCParserNode *aNode,eHTMLTags aTarget,PRBool aClosedByStartTag){
nsresult result=NS_OK;
eHTMLTags nodeType=(eHTMLTags)aNode->GetNodeType();
@ -3587,7 +3587,7 @@ nsresult CNavDTD::CloseContainersTo(PRInt32 anIndex,eHTMLTags aTarget, PRBool aC
nsEntryStack *theChildStyleStack=0;
eHTMLTags theTag=mBodyContext->Last();
nsCParserNode *theNode=NS_STATIC_CAST(nsCParserNode*,mBodyContext->Pop(theChildStyleStack));
nsCParserNode *theNode=mBodyContext->Pop(theChildStyleStack);
if(theNode) {
result=CloseContainer(theNode,aTarget,aClosedByStartTag);
@ -3634,8 +3634,8 @@ nsresult CNavDTD::CloseContainersTo(PRInt32 anIndex,eHTMLTags aTarget, PRBool aC
//here's a case we missed: <a><div>text<a>text</a></div>
//The <div> pushes the 1st <a> onto the rs-stack, then the 2nd <a>
//pops the 1st <a> from the rs-stack altogether.
nsIParserNode* node=mBodyContext->PopStyle(theTag);
NS_IF_RELEASE(node);
nsCParserNode* node=mBodyContext->PopStyle(theTag);
IF_FREE(node, &mNodeAllocator);
}
@ -3680,8 +3680,8 @@ nsresult CNavDTD::CloseContainersTo(PRInt32 anIndex,eHTMLTags aTarget, PRBool aC
// This fixes bug 30885 and 29626
// Make sure that the node, which is about to
// get released does not stay on the style stack...
nsIParserNode* node=mBodyContext->PopStyle(theTag);
NS_IF_RELEASE(node);
nsCParserNode* node=mBodyContext->PopStyle(theTag);
IF_FREE(node, &mNodeAllocator);
}
mBodyContext->PushStyles(theChildStyleStack);
}
@ -3705,8 +3705,8 @@ nsresult CNavDTD::CloseContainersTo(PRInt32 anIndex,eHTMLTags aTarget, PRBool aC
//style tag that got onto that tag stack from a stylestack somewhere.
//Pop it from the stylestack if the target is also a style tag.
if(theTargetTagIsStyle) {
nsIParserNode* node=mBodyContext->PopStyle(theTag);
NS_IF_RELEASE(node);
nsCParserNode* node=mBodyContext->PopStyle(theTag);
IF_FREE(node, &mNodeAllocator);
}
}
}
@ -3723,7 +3723,7 @@ nsresult CNavDTD::CloseContainersTo(PRInt32 anIndex,eHTMLTags aTarget, PRBool aC
}
}
#endif
NS_IF_RELEASE(theNode);
IF_FREE(theNode, &mNodeAllocator);
}//if theNode
}

View File

@ -401,7 +401,7 @@ CLASS_EXPORT_HTMLPARS CNavDTD : public nsIDTD {
* @return error code representing construction state; usually 0.
*/
nsresult HandleStartToken(CToken* aToken);
nsresult HandleDefaultStartToken(CToken* aToken,eHTMLTags aChildTag,nsIParserNode *aNode);
nsresult HandleDefaultStartToken(CToken* aToken,eHTMLTags aChildTag,nsCParserNode *aNode);
nsresult HandleEndToken(CToken* aToken);
nsresult HandleEntityToken(CToken* aToken);
nsresult HandleCommentToken(CToken* aToken);
@ -424,14 +424,14 @@ CLASS_EXPORT_HTMLPARS CNavDTD : public nsIDTD {
* @param node to be opened in content sink.
* @return error code representing error condition-- usually 0.
*/
nsresult OpenHTML(const nsIParserNode *aNode);
nsresult OpenHTML(const nsCParserNode *aNode);
nsresult OpenHead(const nsIParserNode *aNode);
nsresult OpenBody(const nsIParserNode *aNode);
nsresult OpenBody(const nsCParserNode *aNode);
nsresult OpenForm(const nsIParserNode *aNode);
nsresult OpenMap(const nsIParserNode *aNode);
nsresult OpenFrameset(const nsIParserNode *aNode);
nsresult OpenNoscript(const nsIParserNode *aNode,nsEntryStack* aStyleStack=0);
nsresult OpenContainer(const nsIParserNode *aNode,eHTMLTags aTag,PRBool aClosedByStartTag,nsEntryStack* aStyleStack=0);
nsresult OpenMap(const nsCParserNode *aNode);
nsresult OpenFrameset(const nsCParserNode *aNode);
nsresult OpenNoscript(const nsCParserNode *aNode,nsEntryStack* aStyleStack=0);
nsresult OpenContainer(const nsCParserNode *aNode,eHTMLTags aTag,PRBool aClosedByStartTag,nsEntryStack* aStyleStack=0);
/**
* The next set of methods close the given HTML element.
@ -454,7 +454,7 @@ CLASS_EXPORT_HTMLPARS CNavDTD : public nsIDTD {
* @update gess5/11/98
* @return error code - 0 if all went well.
*/
nsresult CloseContainer(const nsIParserNode *aNode,eHTMLTags aTarget,PRBool aClosedByStartTag);
nsresult CloseContainer(const nsCParserNode *aNode,eHTMLTags aTarget,PRBool aClosedByStartTag);
nsresult CloseContainersTo(eHTMLTags aTag,PRBool aClosedByStartTag);
nsresult CloseContainersTo(PRInt32 anIndex,eHTMLTags aTag,PRBool aClosedByStartTag);

View File

@ -463,7 +463,7 @@ nsresult COtherDTD::DidBuildModel(nsresult anErrorCode,PRBool aNotifySink,nsIPar
while(theIndex>0) {
eHTMLTags theParent= mBodyContext->TagAt(--theIndex);
CElement *theElement=gElementTable->mElements[theParent];
nsIParserNode *theNode=mBodyContext->PeekNode();
nsCParserNode *theNode=mBodyContext->PeekNode();
theElement->HandleEndToken(theNode,theChild,mBodyContext,mSink);
theChild=theParent;
}
@ -489,7 +489,7 @@ nsresult COtherDTD::DidBuildModel(nsresult anErrorCode,PRBool aNotifySink,nsIPar
if(theChildStyles) {
delete theChildStyles;
}
NS_IF_RELEASE(theNode);
IF_FREE(theNode, mNodeAllocator);
}
}
}
@ -546,7 +546,7 @@ nsresult COtherDTD::HandleToken(CToken* aToken,nsIParser* aParser){
if(NS_SUCCEEDED(result) || (NS_ERROR_HTMLPARSER_BLOCK==result)) {
IF_FREE(theToken);
IF_FREE(theToken, mTokenAllocator);
}
else if(result==NS_ERROR_HTMLPARSER_STOPPARSING)
mDTDState=result;
@ -701,7 +701,7 @@ nsresult COtherDTD::HandleStartToken(CToken* aToken) {
//Begin by gathering up attributes...
nsresult result=NS_OK;
nsIParserNode* theNode=mNodeAllocator->CreateNode(aToken,mLineNumber,mTokenAllocator);
nsCParserNode* theNode=mNodeAllocator->CreateNode(aToken,mLineNumber,mTokenAllocator);
if(theNode) {
eHTMLTags theChildTag=(eHTMLTags)aToken->GetTypeID();
@ -743,7 +743,7 @@ nsresult COtherDTD::HandleStartToken(CToken* aToken) {
} //if
}//if
NS_IF_RELEASE(theNode);
IF_FREE(theNode, mNodeAllocator);
}
else result=NS_ERROR_OUT_OF_MEMORY;
@ -788,10 +788,10 @@ nsresult COtherDTD::HandleEndToken(CToken* aToken) {
}
CElement* theElement=gElementTable->mElements[theParent];
if(theElement) {
nsIParserNode* theNode=mNodeAllocator->CreateNode(aToken,mLineNumber,mTokenAllocator);
nsCParserNode* theNode=mNodeAllocator->CreateNode(aToken,mLineNumber,mTokenAllocator);
if(theNode) {
result=theElement->HandleEndToken(theNode,theChildTag,mBodyContext,mSink);
NS_IF_RELEASE(theNode);
IF_FREE(theNode, mNodeAllocator);
}
}
break;

View File

@ -211,19 +211,19 @@ public:
nsDTDContext* aContext,
nsIHTMLContentSink* aSink);
virtual nsresult HandleStartToken( nsIParserNode* aNode,
virtual nsresult HandleStartToken( nsCParserNode* aNode,
eHTMLTags aTag,
nsDTDContext* aContext,
nsIHTMLContentSink* aSink);
virtual nsresult HandleEndToken(nsIParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink);
virtual nsresult HandleEndToken(nsCParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink);
virtual nsresult HandleMisplacedStartToken(nsIParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
virtual nsresult HandleMisplacedStartToken(nsCParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
nsresult result=NS_OK;
return result;
}
virtual PRInt32 FindAutoCloseTargetForEndTag(nsIParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink, PRInt32& anIndex) {
virtual PRInt32 FindAutoCloseTargetForEndTag(nsCParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink, PRInt32& anIndex) {
PRInt32 result=-1;
if(mTag!=aTag) {
@ -288,7 +288,7 @@ public:
/**********************************************************
this gets called after each tag is opened in the given context
**********************************************************/
virtual nsresult OpenContext(nsIParserNode *aNode,eHTMLTags aTag,nsDTDContext *aContext,nsIHTMLContentSink *aSink) {
virtual nsresult OpenContext(nsCParserNode *aNode,eHTMLTags aTag,nsDTDContext *aContext,nsIHTMLContentSink *aSink) {
aContext->Push(aNode);
@ -300,7 +300,7 @@ public:
/**********************************************************
this gets called after each tag is opened in the given context
**********************************************************/
virtual nsresult OpenContainerInContext(nsIParserNode *aNode,eHTMLTags aTag,nsDTDContext *aContext,nsIHTMLContentSink *aSink) {
virtual nsresult OpenContainerInContext(nsCParserNode *aNode,eHTMLTags aTag,nsDTDContext *aContext,nsIHTMLContentSink *aSink) {
OpenContext(aNode,aTag,aContext,aSink);
return OpenContainer(aNode,aTag,aContext,aSink);
}
@ -315,22 +315,22 @@ public:
/**********************************************************
this gets called to close a tag in the given context
**********************************************************/
virtual nsresult CloseContext(nsIParserNode *aNode,eHTMLTags aTag,nsDTDContext *aContext,nsIHTMLContentSink *aSink) {
virtual nsresult CloseContext(nsCParserNode *aNode,eHTMLTags aTag,nsDTDContext *aContext,nsIHTMLContentSink *aSink) {
nsresult result=NS_OK;
nsEntryStack *theStack=0;
nsIParserNode *theNode=aContext->Pop(theStack);
nsCParserNode *theNode=aContext->Pop(theStack);
CElement *theElement=(aTag==mTag) ? this : GetElement(aTag);
result=theElement->NotifyClose(theNode,aTag,aContext,aSink);
NS_IF_RELEASE(aNode);
IF_FREE(aNode, aContext->mNodeAllocator);
return result;
}
/**********************************************************
this gets called to close a tag in the sink and in the context
**********************************************************/
virtual nsresult CloseContainerInContext(nsIParserNode *aNode,eHTMLTags aTag,nsDTDContext *aContext,nsIHTMLContentSink *aSink) {
virtual nsresult CloseContainerInContext(nsCParserNode *aNode,eHTMLTags aTag,nsDTDContext *aContext,nsIHTMLContentSink *aSink) {
nsresult result=NS_OK;
if(mTag!=aTag) {
CElement *theElement=GetElement(aTag);
@ -762,7 +762,7 @@ public:
/**********************************************************
Table handles the opening of it's own children
**********************************************************/
virtual nsresult HandleStartToken(nsIParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
virtual nsresult HandleStartToken(nsCParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
nsresult result=NS_OK;
switch(aTag) {
@ -808,7 +808,7 @@ public:
if(aContext->mTableStates) {
if(aContext->mTableStates->CanOpenTBody()) {
CToken* theToken=(CStartToken*)aContext->mTokenAllocator->CreateTokenOfType(eToken_start,eHTMLTag_tbody);
nsIParserNode* theNode=aContext->mNodeAllocator->CreateNode(theToken,0,0);
nsCParserNode* theNode=aContext->mNodeAllocator->CreateNode(theToken,0,0);
result=HandleStartToken(theNode,eHTMLTag_tbody,aContext,aSink);
}
@ -831,7 +831,7 @@ public:
/**********************************************************
Table handles the closing of it's own children
**********************************************************/
virtual nsresult HandleEndToken(nsIParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
virtual nsresult HandleEndToken(nsCParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
nsresult result=NS_OK;
if(aContext->HasOpenContainer(aTag)) {
@ -981,7 +981,7 @@ public:
/**********************************************************
handles the opening of it's own children
**********************************************************/
virtual nsresult HandleStartToken( nsIParserNode* aNode,
virtual nsresult HandleStartToken( nsCParserNode* aNode,
eHTMLTags aTag,
nsDTDContext* aContext,
nsIHTMLContentSink* aSink) {
@ -992,7 +992,7 @@ public:
/**********************************************************
this gets called after each tag is opened in the given context
**********************************************************/
virtual nsresult OpenContext(nsIParserNode *aNode,eHTMLTags aTag,nsDTDContext *aContext,nsIHTMLContentSink *aSink) {
virtual nsresult OpenContext(nsCParserNode *aNode,eHTMLTags aTag,nsDTDContext *aContext,nsIHTMLContentSink *aSink) {
CElement::OpenContext(aNode,aTag,aContext,aSink);
nsresult result=NS_OK;
@ -1013,7 +1013,7 @@ public:
/**********************************************************
handles the opening of it's own children
**********************************************************/
virtual nsresult HandleEndToken(nsIParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
virtual nsresult HandleEndToken(nsCParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
return CElement::HandleEndToken(aNode,aTag,aContext,aSink);
}
@ -1262,7 +1262,7 @@ public:
/**********************************************************
Call this for each element as it get's closed
**********************************************************/
virtual nsresult NotifyClose(nsIParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
virtual nsresult NotifyClose(nsCParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
nsresult result=NS_OK;
CElement* theHead=GetElement(eHTMLTag_head);
if(theHead) {
@ -1358,7 +1358,7 @@ public:
/**********************************************************
Call this for each element as it get's closed
**********************************************************/
virtual nsresult NotifyClose(nsIParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
virtual nsresult NotifyClose(nsCParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
nsresult result=NS_OK;
CElement* theHead=GetElement(eHTMLTag_head);
if(theHead) {
@ -1397,7 +1397,7 @@ public:
/**********************************************************
this gets called after each tag is opened in the given context
**********************************************************/
virtual nsresult OpenContainerInContext(nsIParserNode *aNode,eHTMLTags aTag,nsDTDContext *aContext,nsIHTMLContentSink *aSink) {
virtual nsresult OpenContainerInContext(nsCParserNode *aNode,eHTMLTags aTag,nsDTDContext *aContext,nsIHTMLContentSink *aSink) {
OpenContext(aNode,aTag,aContext,aSink);
return NS_OK;
}
@ -1418,7 +1418,7 @@ public:
/**********************************************************
Call this for each element as it get's closed
**********************************************************/
virtual nsresult NotifyClose(nsIParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
virtual nsresult NotifyClose(nsCParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
nsresult result=NS_OK;
if(aContext->HasOpenContainer(eHTMLTag_body)) {
@ -1464,7 +1464,7 @@ public:
/**********************************************************
Pre handles the opening of it's own children
**********************************************************/
virtual nsresult HandleStartToken(nsIParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
virtual nsresult HandleStartToken(nsCParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
nsresult result=CElement::HandleStartToken(aNode,aTag,aContext,aSink);
return result;
}
@ -1473,7 +1473,7 @@ public:
/**********************************************************
Pre handles the closing of it's own children
**********************************************************/
virtual nsresult HandleEndToken(nsIParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
virtual nsresult HandleEndToken(nsCParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
nsresult result=CElement::HandleEndToken(aNode,aTag,aContext,aSink);
return result;
}
@ -1512,7 +1512,7 @@ public:
/**********************************************************
handles the opening of it's own children
**********************************************************/
virtual nsresult HandleStartToken(nsIParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
virtual nsresult HandleStartToken(nsCParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
nsresult result=NS_OK;
nsIParserNode *theNode=aContext->PeekNode();
if(theNode) {
@ -1569,7 +1569,7 @@ public:
/**********************************************************
fieldset handles the opening of it's own children
**********************************************************/
virtual nsresult HandleStartToken(nsIParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
virtual nsresult HandleStartToken(nsCParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
nsresult result=NS_OK;
nsIParserNode *theNode=aContext->PeekNode();
if(theNode) {
@ -1624,7 +1624,7 @@ public:
/**********************************************************
Toplevel handles the opening of it's own children
**********************************************************/
virtual nsresult HandleStartToken( nsIParserNode* aNode,
virtual nsresult HandleStartToken( nsCParserNode* aNode,
eHTMLTags aTag,
nsDTDContext* aContext,
nsIHTMLContentSink* aSink) {
@ -1643,7 +1643,7 @@ public:
/**********************************************************
TopLevel handles the opening of it's own children
**********************************************************/
virtual nsresult HandleEndToken(nsIParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
virtual nsresult HandleEndToken(nsCParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
nsresult result=NS_OK;
@ -1728,7 +1728,7 @@ public:
/**********************************************************
HTML handles the opening of it's own children
**********************************************************/
virtual nsresult HandleStartToken( nsIParserNode* aNode,
virtual nsresult HandleStartToken( nsCParserNode* aNode,
eHTMLTags aTag,
nsDTDContext* aContext,
nsIHTMLContentSink* aSink) {
@ -1795,7 +1795,7 @@ public:
//let's auto open the body
CToken* theToken=(CStartToken*)aContext->mTokenAllocator->CreateTokenOfType(eToken_start,eHTMLTag_body);
nsIParserNode* theNode=aContext->mNodeAllocator->CreateNode(theToken,0,0);
nsCParserNode* theNode=aContext->mNodeAllocator->CreateNode(theToken,0,0);
result=theBody->HandleStartToken(theNode,eHTMLTag_body,aContext,aSink);
@ -1816,7 +1816,7 @@ public:
/**********************************************************
HTML handles the closing of it's own children
**********************************************************/
virtual nsresult HandleEndToken(nsIParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
virtual nsresult HandleEndToken(nsCParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
nsresult result=NS_OK;
switch(aTag) {
@ -1886,7 +1886,7 @@ public:
}
//this gets called after each tag is opened in the given context
virtual nsresult OpenContainer(nsIParserNode *aNode,eHTMLTags aTag,nsDTDContext *aContext,nsIHTMLContentSink *aSink) {
virtual nsresult OpenContainer(nsCParserNode *aNode,eHTMLTags aTag,nsDTDContext *aContext,nsIHTMLContentSink *aSink) {
nsresult result=NS_OK;
if(mTag==aTag) {
// Close the head before opening a body.
@ -1903,7 +1903,7 @@ public:
/**********************************************************
this gets called after each tag is opened in the given context
**********************************************************/
virtual nsresult OpenContainerInContext(nsIParserNode *aNode,eHTMLTags aTag,nsDTDContext *aContext,nsIHTMLContentSink *aSink) {
virtual nsresult OpenContainerInContext(nsCParserNode *aNode,eHTMLTags aTag,nsDTDContext *aContext,nsIHTMLContentSink *aSink) {
NS_ASSERTION(aContext!=nsnull,"need a valid context");
nsresult result=NS_OK;
// Since BODY is optional, we might come across more than one BODY!.
@ -1922,7 +1922,7 @@ public:
/**********************************************************
Body handles the opening of it's own children
**********************************************************/
virtual nsresult HandleStartToken( nsIParserNode* aNode,
virtual nsresult HandleStartToken( nsCParserNode* aNode,
eHTMLTags aTag,
nsDTDContext* aContext,
nsIHTMLContentSink* aSink) {
@ -1951,7 +1951,7 @@ public:
Body doesnt really need to handle it's own kids, but it's
a really convenient break point for debugging purposes.
**********************************************************/
virtual nsresult HandleEndToken(nsIParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
virtual nsresult HandleEndToken(nsCParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
nsresult result=NS_OK;
switch(aTag) {
case eHTMLTag_script:
@ -2645,7 +2645,7 @@ nsresult CElement::WillHandleStartToken( CElement *anElement,
return result;
}
nsresult CElement::HandleStartToken( nsIParserNode* aNode,
nsresult CElement::HandleStartToken( nsCParserNode* aNode,
eHTMLTags aTag,
nsDTDContext* aContext,
nsIHTMLContentSink* aSink) {
@ -2700,7 +2700,7 @@ nsresult CElement::HandleStartToken( nsIParserNode* aNode,
theParentTag=aContext->Last();
theParent=gElementTable->mElements[theParentTag];
nsIParserNode *theNode=aContext->PeekNode(); //this will get popped later...
nsCParserNode *theNode=aContext->PeekNode(); //this will get popped later...
if(theParent->IsSinkContainer()) {
CloseContainerInContext(theNode,theParentTag,aContext,aSink);
}
@ -2755,7 +2755,7 @@ nsresult CElement::HandleStartToken( nsIParserNode* aNode,
}
nsresult CElement::HandleEndToken(nsIParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
nsresult CElement::HandleEndToken(nsCParserNode* aNode,eHTMLTags aTag,nsDTDContext* aContext,nsIHTMLContentSink* aSink) {
nsresult result=NS_OK;
if(aContext->Last()==aTag) {

View File

@ -123,7 +123,7 @@ void nsEntryStack::EnsureCapacityFor(PRInt32 aNewMax,PRInt32 aShiftOffset) {
*
* @update gess 04/22/99
*/
void nsEntryStack::Push(const nsIParserNode* aNode,nsEntryStack* aStyleStack) {
void nsEntryStack::Push(const nsCParserNode* aNode,nsEntryStack* aStyleStack) {
if(aNode) {
EnsureCapacityFor(mCount+1);
@ -131,9 +131,9 @@ void nsEntryStack::Push(const nsIParserNode* aNode,nsEntryStack* aStyleStack) {
((nsCParserNode*)aNode)->mUseCount++;
mEntries[mCount].mTag=(eHTMLTags)aNode->GetNodeType();
mEntries[mCount].mNode=(nsIParserNode*)aNode;
mEntries[mCount].mNode=NS_CONST_CAST(nsCParserNode*,aNode);
NS_ADDREF(mEntries[mCount].mNode);
IF_HOLD(mEntries[mCount].mNode);
mEntries[mCount].mParent=aStyleStack;
mEntries[mCount++].mStyles=0;
@ -146,7 +146,7 @@ void nsEntryStack::Push(const nsIParserNode* aNode,nsEntryStack* aStyleStack) {
*
* @update gess 11/10/99
*/
void nsEntryStack::PushFront(const nsIParserNode* aNode,nsEntryStack* aStyleStack) {
void nsEntryStack::PushFront(const nsCParserNode* aNode,nsEntryStack* aStyleStack) {
if(aNode) {
if(mCount<mCapacity) {
@ -161,9 +161,9 @@ void nsEntryStack::PushFront(const nsIParserNode* aNode,nsEntryStack* aStyleStac
((nsCParserNode*)aNode)->mUseCount++;
mEntries[0].mTag=(eHTMLTags)aNode->GetNodeType();
mEntries[0].mNode=(nsIParserNode*)aNode;
mEntries[0].mNode=NS_CONST_CAST(nsCParserNode*,aNode);
NS_ADDREF(mEntries[0].mNode);
IF_HOLD(mEntries[0].mNode);
mEntries[0].mParent=aStyleStack;
mEntries[0].mStyles=0;
@ -203,8 +203,8 @@ void nsEntryStack::Append(nsEntryStack *aStack) {
* aTag: the id of the tag to be removed
* @update gess 02/25/00
*/
nsIParserNode* nsEntryStack::Remove(PRInt32 anIndex,eHTMLTags aTag) {
nsIParserNode* result=0;
nsCParserNode* nsEntryStack::Remove(PRInt32 anIndex,eHTMLTags aTag) {
nsCParserNode* result=0;
if((0<mCount) && (anIndex<mCount)){
result=mEntries[anIndex].mNode;
@ -246,9 +246,9 @@ nsIParserNode* nsEntryStack::Remove(PRInt32 anIndex,eHTMLTags aTag) {
* @update harishd 04/04/99
* @update gess 04/21/99
*/
nsIParserNode* nsEntryStack::Pop(void) {
nsCParserNode* nsEntryStack::Pop(void) {
nsIParserNode* result=0;
nsCParserNode* result=0;
if(0<mCount) {
result=mEntries[--mCount].mNode;
@ -297,8 +297,8 @@ eHTMLTags nsEntryStack::First() const {
* @update harishd 04/04/99
* @update gess 04/21/99
*/
nsIParserNode* nsEntryStack::NodeAt(PRInt32 anIndex) const {
nsIParserNode* result=0;
nsCParserNode* nsEntryStack::NodeAt(PRInt32 anIndex) const {
nsCParserNode* result=0;
if((0<mCount) && (anIndex<mCount)) {
result=mEntries[anIndex].mNode;
}
@ -885,7 +885,7 @@ PRBool nsDTDContext::HasOpenContainer(eHTMLTags aTag) const {
*
* @update gess7/9/98
*/
void nsDTDContext::Push(const nsIParserNode* aNode,nsEntryStack* aStyleStack) {
void nsDTDContext::Push(const nsCParserNode* aNode,nsEntryStack* aStyleStack) {
if(aNode) {
#ifdef NS_DEBUG
@ -894,7 +894,7 @@ void nsDTDContext::Push(const nsIParserNode* aNode,nsEntryStack* aStyleStack) {
if(size< eMaxTags)
mXTags[size]=theTag;
#endif
mStack.Push((nsIParserNode*)aNode,aStyleStack);
mStack.Push(aNode,aStyleStack);
}
}
@ -902,10 +902,10 @@ void nsDTDContext::Push(const nsIParserNode* aNode,nsEntryStack* aStyleStack) {
* @update gess 11/11/99,
* harishd 04/04/99
*/
nsIParserNode* nsDTDContext::Pop(nsEntryStack *&aChildStyleStack) {
nsCParserNode* nsDTDContext::Pop(nsEntryStack *&aChildStyleStack) {
PRInt32 theSize=mStack.mCount;
nsIParserNode* result=0;
nsCParserNode* result=0;
if(0<theSize) {
@ -932,7 +932,7 @@ nsIParserNode* nsDTDContext::Pop(nsEntryStack *&aChildStyleStack) {
* @update harishd 04/07/00
*/
nsIParserNode* nsDTDContext::Pop() {
nsCParserNode* nsDTDContext::Pop() {
nsEntryStack *theTempStyleStack=0; // This has no use here...
return Pop(theTempStyleStack);
}
@ -992,7 +992,7 @@ nsEntryStack* nsDTDContext::GetStylesAt(PRInt32 anIndex) const {
*
* @update gess 04/28/99
*/
void nsDTDContext::PushStyle(const nsIParserNode* aNode){
void nsDTDContext::PushStyle(const nsCParserNode* aNode){
nsTagEntry* theEntry=mStack.EntryAt(mStack.mCount-1);
if(theEntry ) {
@ -1045,8 +1045,8 @@ void nsDTDContext::PushStyles(nsEntryStack *aStyles){
// If you're here it means that we have hit the rock bottom
// ,of the stack, and there's no need to handle anymore styles.
// Fix for bug 29048
nsIParserNode* theNode=aStyles->Pop();
NS_IF_RELEASE(theNode);
nsCParserNode* theNode=aStyles->Pop();
IF_HOLD(theNode);
delete aStyles;
aStyles=0;
}
@ -1058,8 +1058,8 @@ void nsDTDContext::PushStyles(nsEntryStack *aStyles){
*
* @update gess 04/28/99
*/
nsIParserNode* nsDTDContext::PopStyle(void){
nsIParserNode *result=0;
nsCParserNode* nsDTDContext::PopStyle(void){
nsCParserNode *result=0;
nsTagEntry *theEntry=mStack.EntryAt(mStack.mCount-1);
if(theEntry && (theEntry->mNode)) {
@ -1076,10 +1076,10 @@ nsIParserNode* nsDTDContext::PopStyle(void){
*
* @update gess 04/28/99
*/
nsIParserNode* nsDTDContext::PopStyle(eHTMLTags aTag){
nsCParserNode* nsDTDContext::PopStyle(eHTMLTags aTag){
PRInt32 theLevel=0;
nsIParserNode* result=0;
nsCParserNode* result=0;
for(theLevel=mStack.mCount-1;theLevel>0;theLevel--) {
nsEntryStack *theStack=mStack.mEntries[theLevel].mStyles;
@ -1105,10 +1105,10 @@ nsIParserNode* nsDTDContext::PopStyle(eHTMLTags aTag){
*
* @update gess 01/26/00
*/
nsIParserNode* nsDTDContext::RemoveStyle(eHTMLTags aTag){
nsCParserNode* nsDTDContext::RemoveStyle(eHTMLTags aTag){
PRInt32 theLevel=0;
nsIParserNode* result=0;
nsCParserNode* result=0;
for(theLevel=mStack.mCount-1;theLevel>0;theLevel--) {
nsEntryStack *theStack=mStack.mEntries[theLevel].mStyles;
@ -1337,7 +1337,7 @@ nsNodeAllocator::~nsNodeAllocator() {
#endif
}
nsIParserNode* nsNodeAllocator::CreateNode(CToken* aToken,PRInt32 aLineNumber,nsTokenAllocator* aTokenAllocator) {
nsCParserNode* nsNodeAllocator::CreateNode(CToken* aToken,PRInt32 aLineNumber,nsTokenAllocator* aTokenAllocator) {
nsCParserNode* result=0;
#ifdef HEAP_ALLOCATED_NODES
@ -1352,18 +1352,18 @@ nsIParserNode* nsNodeAllocator::CreateNode(CToken* aToken,PRInt32 aLineNumber,ns
result->Init(aToken,aLineNumber,aTokenAllocator,this);
}
else{
result=new nsCParserNode(aToken,aLineNumber,aTokenAllocator,this);
result=nsCParserNode::Create(aToken,aLineNumber,aTokenAllocator,this);
#ifdef DEBUG_TRACK_NODES
mCount++;
AddNode(NS_STATIC_CAST(nsCParserNode*,result));
#endif
NS_IF_ADDREF(result);
IF_HOLD(result);
}
#else
result=new(mNodePool) nsCParserNode(aToken,aLineNumber,aTokenAllocator);
NS_IF_ADDREF(result);
result=nsCParserNode::Create(aToken,aLineNumber,aTokenAllocator,this);
IF_HOLD(result);
#endif
return NS_STATIC_CAST(nsIParserNode*,result);
return result;
}
void DebugDumpContainmentRules(nsIDTD& theDTD,const char* aFilename,const char* aTitle) {

View File

@ -46,7 +46,7 @@
#include "nsVoidArray.h"
#define IF_HOLD(_ptr) if(_ptr) { _ptr->AddRef(); }
#define IF_FREE(_ptr) if(_ptr) { _ptr->Release(); _ptr=0; } // recycles _ptr
#define IF_FREE(_ptr, _allocator) if(_ptr) { _ptr->Release((_allocator)->GetArenaPool()); _ptr=0; } // recycles _ptr
class nsIParserNode;
class nsCParserNode;
@ -67,7 +67,7 @@ class nsEntryStack; //forware declare to make compilers happy.
struct nsTagEntry {
eHTMLTags mTag; //for speedier access to tag id
nsIParserNode* mNode;
nsCParserNode* mNode;
nsEntryStack* mParent;
nsEntryStack* mStyles;
};
@ -78,12 +78,12 @@ public:
~nsEntryStack();
void EnsureCapacityFor(PRInt32 aNewMax, PRInt32 aShiftOffset=0);
void Push(const nsIParserNode* aNode,nsEntryStack* aStyleStack=0);
void PushFront(const nsIParserNode* aNode,nsEntryStack* aStyleStack=0);
void Push(const nsCParserNode* aNode,nsEntryStack* aStyleStack=0);
void PushFront(const nsCParserNode* aNode,nsEntryStack* aStyleStack=0);
void Append(nsEntryStack *theStack);
nsIParserNode* Pop(void);
nsIParserNode* Remove(PRInt32 anIndex,eHTMLTags aTag);
nsIParserNode* NodeAt(PRInt32 anIndex) const;
nsCParserNode* Pop(void);
nsCParserNode* Remove(PRInt32 anIndex,eHTMLTags aTag);
nsCParserNode* NodeAt(PRInt32 anIndex) const;
eHTMLTags First() const;
eHTMLTags TagAt(PRInt32 anIndex) const;
nsTagEntry* EntryAt(PRInt32 anIndex) const;
@ -229,6 +229,8 @@ public:
virtual CToken* CreateTokenOfType(eHTMLTokenTypes aType,eHTMLTags aTag, const nsAReadableString& aString);
virtual CToken* CreateTokenOfType(eHTMLTokenTypes aType,eHTMLTags aTag);
nsFixedSizeAllocator& GetArenaPool() { return mArenaPool; }
protected:
nsFixedSizeAllocator mArenaPool;
@ -245,23 +247,30 @@ protected:
that get created during the run of the system.
************************************************************************/
#ifndef HEAP_ALLOCATED_NODES
class nsCParserNode;
#endif
class nsNodeAllocator {
public:
nsNodeAllocator();
virtual ~nsNodeAllocator();
virtual nsIParserNode* CreateNode(CToken* aToken=nsnull,PRInt32 aLineNumber=1,nsTokenAllocator* aTokenAllocator=0);
virtual nsCParserNode* CreateNode(CToken* aToken=nsnull,PRInt32 aLineNumber=1,nsTokenAllocator* aTokenAllocator=0);
nsFixedSizeAllocator& GetArenaPool() { return mNodePool; }
#ifdef HEAP_ALLOCATED_NODES
void Recycle(nsIParserNode* aNode) { mSharedNodes.Push(NS_STATIC_CAST(void*,aNode)); }
void Recycle(nsCParserNode* aNode) { mSharedNodes.Push(NS_STATIC_CAST(void*,aNode)); }
protected:
nsDeque mSharedNodes;
#ifdef DEBUG_TRACK_NODES
PRInt32 mCount;
#endif
#else
#endif
protected:
nsFixedSizeAllocator mNodePool;
#endif
};
/************************************************************************
@ -273,10 +282,10 @@ public:
nsDTDContext();
~nsDTDContext();
void Push(const nsIParserNode* aNode,nsEntryStack* aStyleStack=0);
nsIParserNode* Pop(nsEntryStack*& aChildStack);
nsIParserNode* Pop();
nsIParserNode* PeekNode() { return mStack.NodeAt(mStack.mCount-1); }
void Push(const nsCParserNode* aNode,nsEntryStack* aStyleStack=0);
nsCParserNode* Pop(nsEntryStack*& aChildStack);
nsCParserNode* Pop();
nsCParserNode* PeekNode() { return mStack.NodeAt(mStack.mCount-1); }
eHTMLTags First(void) const;
eHTMLTags Last(void) const;
nsTagEntry* LastEntry(void) const;
@ -290,11 +299,11 @@ public:
PRInt32 GetCount(void) {return mStack.mCount;}
PRInt32 GetResidualStyleCount(void) {return mResidualStyleCount;}
nsEntryStack* GetStylesAt(PRInt32 anIndex) const;
void PushStyle(const nsIParserNode* aNode);
void PushStyle(const nsCParserNode* aNode);
void PushStyles(nsEntryStack *theStyles);
nsIParserNode* PopStyle(void);
nsIParserNode* PopStyle(eHTMLTags aTag);
nsIParserNode* RemoveStyle(eHTMLTags aTag);
nsCParserNode* PopStyle(void);
nsCParserNode* PopStyle(eHTMLTags aTag);
nsCParserNode* RemoveStyle(eHTMLTags aTag);
static void ReleaseGlobalObjects(void);
@ -342,10 +351,16 @@ public:
Now define the token deallocator class...
**************************************************************/
class CTokenDeallocator: public nsDequeFunctor{
protected:
nsFixedSizeAllocator& mArenaPool;
public:
CTokenDeallocator(nsFixedSizeAllocator& aArenaPool)
: mArenaPool(aArenaPool) {}
virtual void* operator()(void* anObject) {
CToken* aToken = (CToken*)anObject;
delete aToken;
CToken::Destroy(aToken, mArenaPool);
return 0;
}
};

View File

@ -234,7 +234,7 @@ NS_IMETHODIMP nsExpatDTD::BuildModel(nsIParser* aParser,nsITokenizer* aTokenizer
if(theToken) {
result=HandleToken(theToken,aParser);
if(NS_SUCCEEDED(result)) {
IF_FREE(theToken);
IF_FREE(theToken, mTokenizer->GetTokenAllocator());
}
else if(NS_ERROR_HTMLPARSER_BLOCK!=result){
mTokenizer->PushTokenFront(theToken);

View File

@ -133,7 +133,7 @@ NS_IMPL_RELEASE(nsHTMLTokenizer)
*/
nsHTMLTokenizer::~nsHTMLTokenizer(){
if(mTokenDeque.GetSize()){
CTokenDeallocator theDeallocator;
CTokenDeallocator theDeallocator(mTokenAllocator->GetArenaPool());
mTokenDeque.ForEach(theDeallocator);
}
}
@ -149,7 +149,7 @@ void nsHTMLTokenizer::AddToken(CToken*& aToken,nsresult aResult,nsDeque* aDeque,
aDeque->Push(aToken);
}
else {
IF_FREE(aToken);
IF_FREE(aToken, aTokenAllocator);
}
}
}
@ -589,12 +589,12 @@ nsresult nsHTMLTokenizer::ConsumeAttributes(PRUnichar aChar,CStartToken* aToken,
AddToken((CToken*&)theToken,result,&mTokenDeque,theAllocator);
}
else {
IF_FREE(theToken);
IF_FREE(theToken, mTokenAllocator);
}
}
else { //if(NS_ERROR_HTMLPARSER_BADATTRIBUTE==result){
aToken->SetEmpty(PR_TRUE);
IF_FREE(theToken);
IF_FREE(theToken, mTokenAllocator);
if(NS_ERROR_HTMLPARSER_BADATTRIBUTE==result)
result=NS_OK;
}
@ -728,7 +728,7 @@ nsresult nsHTMLTokenizer::ConsumeStartTag(PRUnichar aChar,CToken*& aToken,nsScan
AddToken(endToken,result,&mTokenDeque,theAllocator);
}
else {
IF_FREE(text);
IF_FREE(text, mTokenAllocator);
}
}
}
@ -742,11 +742,11 @@ nsresult nsHTMLTokenizer::ConsumeStartTag(PRUnichar aChar,CToken*& aToken,nsScan
if(!NS_SUCCEEDED(result)) {
while(mTokenDeque.GetSize()>theDequeSize) {
CToken* theToken=(CToken*)mTokenDeque.Pop();
IF_FREE(theToken);
IF_FREE(theToken, mTokenAllocator);
}
}
} //if
else IF_FREE(aToken);
else IF_FREE(aToken, mTokenAllocator);
} //if
return result;
}
@ -900,7 +900,7 @@ nsresult nsHTMLTokenizer::ConsumeText(CToken*& aToken,nsScanner& aScanner){
result=theToken->Consume(ch,aScanner,mParseMode);
if(!NS_SUCCEEDED(result)) {
if(0==theToken->GetTextLength()){
IF_FREE(aToken);
IF_FREE(aToken, mTokenAllocator);
aToken = nsnull;
}
else result=NS_OK;

View File

@ -114,6 +114,8 @@ protected:
* @update gess 3/25/98
*/
class CStartToken: public CHTMLToken {
CTOKEN_IMPL_SIZEOF
public:
CStartToken(eHTMLTags aTag=eHTMLTag_unknown);
CStartToken(const nsAReadableString& aString);
@ -168,6 +170,8 @@ class CStartToken: public CHTMLToken {
* @update gess 3/25/98
*/
class CEndToken: public CHTMLToken {
CTOKEN_IMPL_SIZEOF
public:
CEndToken(eHTMLTags aTag);
CEndToken(const nsAReadableString& aString);
@ -195,6 +199,8 @@ class CEndToken: public CHTMLToken {
* @update gess 3/25/98
*/
class CCommentToken: public CHTMLToken {
CTOKEN_IMPL_SIZEOF
public:
CCommentToken();
CCommentToken(const nsAReadableString& aString);
@ -217,6 +223,8 @@ class CCommentToken: public CHTMLToken {
* @update gess 3/25/98
*/
class CEntityToken : public CHTMLToken {
CTOKEN_IMPL_SIZEOF
public:
CEntityToken();
CEntityToken(const nsAReadableString& aString);
@ -244,6 +252,8 @@ class CEntityToken : public CHTMLToken {
* @update gess 3/25/98
*/
class CWhitespaceToken: public CHTMLToken {
CTOKEN_IMPL_SIZEOF
public:
CWhitespaceToken();
CWhitespaceToken(const nsAReadableString& aString);
@ -264,6 +274,8 @@ class CWhitespaceToken: public CHTMLToken {
* @update gess 3/25/98
*/
class CTextToken: public CHTMLToken {
CTOKEN_IMPL_SIZEOF
public:
CTextToken();
CTextToken(const nsAReadableString& aString);
@ -291,6 +303,8 @@ class CTextToken: public CHTMLToken {
* @update vidur 11/12/98
*/
class CCDATASectionToken : public CHTMLToken {
CTOKEN_IMPL_SIZEOF
public:
CCDATASectionToken();
CCDATASectionToken(const nsAReadableString& aString);
@ -311,6 +325,8 @@ public:
*
*/
class CMarkupDeclToken : public CHTMLToken {
CTOKEN_IMPL_SIZEOF
public:
CMarkupDeclToken();
CMarkupDeclToken(const nsAReadableString& aString);
@ -333,6 +349,8 @@ protected:
* @update gess 3/25/98
*/
class CAttributeToken: public CHTMLToken {
CTOKEN_IMPL_SIZEOF
public:
CAttributeToken();
CAttributeToken(const nsAReadableString& aString);
@ -367,6 +385,8 @@ class CAttributeToken: public CHTMLToken {
* @update gess 3/25/98
*/
class CNewlineToken: public CHTMLToken {
CTOKEN_IMPL_SIZEOF
public:
CNewlineToken();
virtual nsresult Consume(PRUnichar aChar,nsScanner& aScanner,PRInt32 aMode);
@ -389,6 +409,8 @@ class CNewlineToken: public CHTMLToken {
* @update gess 3/25/98
*/
class CScriptToken: public CHTMLToken {
CTOKEN_IMPL_SIZEOF
public:
CScriptToken();
CScriptToken(const nsAReadableString& aString);
@ -410,6 +432,8 @@ class CScriptToken: public CHTMLToken {
* @update gess 3/25/98
*/
class CStyleToken: public CHTMLToken {
CTOKEN_IMPL_SIZEOF
public:
CStyleToken();
CStyleToken(const nsAReadableString& aString);
@ -430,6 +454,8 @@ class CStyleToken: public CHTMLToken {
* @update gess 3/25/98
*/
class CInstructionToken: public CHTMLToken {
CTOKEN_IMPL_SIZEOF
public:
CInstructionToken();
CInstructionToken(const nsAReadableString& aString);
@ -443,6 +469,8 @@ class CInstructionToken: public CHTMLToken {
};
class CErrorToken : public CHTMLToken {
CTOKEN_IMPL_SIZEOF
public:
CErrorToken(nsParserError* aError=0);
~CErrorToken();
@ -469,6 +497,8 @@ protected:
*/
class CDoctypeDeclToken: public CHTMLToken {
CTOKEN_IMPL_SIZEOF
public:
CDoctypeDeclToken(eHTMLTags aTag=eHTMLTag_unknown);
CDoctypeDeclToken(const nsAReadableString& aString,eHTMLTags aTag=eHTMLTag_unknown);

View File

@ -65,7 +65,7 @@ class CToken;
*
* @update gess 3/25/98
*/
class nsIParserNode : public nsISupports {
class nsIParserNode { // XXX Should be nsAParserNode
public:

View File

@ -48,7 +48,7 @@ const nsString& GetEmptyString() {
*/
nsCParserNode::nsCParserNode(CToken* aToken,PRInt32 aLineNumber,nsTokenAllocator* aTokenAllocator,nsNodeAllocator* aNodeAllocator):
nsIParserNode() {
NS_INIT_REFCNT();
mRefCnt = 0;
MOZ_COUNT_CTOR(nsCParserNode);
static int theNodeCount=0;
@ -88,9 +88,6 @@ nsCParserNode::~nsCParserNode() {
}
NS_IMPL_ADDREF(nsCParserNode)
NS_IMPL_RELEASE(nsCParserNode)
/**
* Init
*
@ -105,7 +102,7 @@ nsresult nsCParserNode::Init(CToken* aToken,PRInt32 aLineNumber,nsTokenAllocator
if(mAttributes && (mAttributes->GetSize())) {
CToken* theAttrToken=0;
while((theAttrToken=NS_STATIC_CAST(CToken*,mAttributes->Pop()))) {
IF_FREE(theAttrToken);
IF_FREE(theAttrToken, aTokenAllocator);
}
}
mToken=aToken;
@ -121,40 +118,6 @@ nsresult nsCParserNode::Init(CToken* aToken,PRInt32 aLineNumber,nsTokenAllocator
return NS_OK;
}
/**
* This method gets called as part of our COM-like interfaces.
* Its purpose is to create an interface to parser object
* of some type.
*
* @update gess 3/25/98
* @param nsIID id of object to discover
* @param aInstancePtr ptr to newly discovered interface
* @return NS_xxx result code
*/
nsresult nsCParserNode::QueryInterface(const nsIID& aIID, void** aInstancePtr)
{
if (NULL == aInstancePtr) {
return NS_ERROR_NULL_POINTER;
}
if(aIID.Equals(kISupportsIID)) { //do IUnknown...
*aInstancePtr = (nsIParserNode*)(this);
}
else if(aIID.Equals(kIParserNodeIID)) { //do IParser base class...
*aInstancePtr = (nsIParserNode*)(this);
}
else if(aIID.Equals(kClassIID)) { //do this class...
*aInstancePtr = (nsCParserNode*)(this);
}
else {
*aInstancePtr=0;
return NS_NOINTERFACE;
}
NS_ADDREF_THIS();
return NS_OK;
}
/**
* Causes the given attribute to be added to internal
* mAttributes list, and mAttributeCount to be incremented.
@ -380,7 +343,7 @@ nsresult nsCParserNode::ReleaseAll() {
if(mAttributes) {
CToken* theAttrToken=0;
while((theAttrToken=NS_STATIC_CAST(CToken*,mAttributes->Pop()))) {
IF_FREE(theAttrToken);
IF_FREE(theAttrToken, mTokenAllocator);
}
delete mAttributes;
mAttributes=0;
@ -389,7 +352,7 @@ nsresult nsCParserNode::ReleaseAll() {
delete mSkippedContent;
mSkippedContent=0;
}
IF_FREE(mToken);
IF_FREE(mToken, mTokenAllocator);
return NS_OK;
}

View File

@ -50,40 +50,59 @@
class nsTokenAllocator;
class nsCParserNode : public nsIParserNode {
protected:
PRInt32 mRefCnt;
public:
NS_DECL_ISUPPORTS
void AddRef()
{
++mRefCnt;
}
#ifdef HEAP_ALLOCATED_NODES
void* operator new(size_t aSize) {
return ::operator new(aSize);
}
#else
/**
*
* @update harishd 01/01/01
* @param aSize -
* @param aArena - Allocate memory from this pool.
*/
static void * operator new (size_t aSize, nsFixedSizeAllocator& anArena)
void Release(nsFixedSizeAllocator& aPool)
{
return anArena.Alloc(aSize);
if (--mRefCnt == 0)
Destroy(this, aPool);
}
#endif
/**
*
*
* @update harishd 01/01/01
* @param aPtr - The memory that should be recycled/freed.
* @param aSize - The size of memory that needs to be freed.
*/
static void operator delete (void* aPtr,size_t aSize)
{
// NodeAllocator would take care of heap allocated nodes..
#ifndef HEAP_ALLOCATED_NODES
nsFixedSizeAllocator::Free(aPtr,aSize);
private:
/**
* Hide operator new; clients should use Create() instead.
*/
static void* operator new(size_t) { return 0; }
/**
* Hide operator delete; clients should use Destroy() instead.
*/
static void operator delete(void*,size_t) {}
#endif
public:
static nsCParserNode* Create(CToken* aToken,PRInt32 aLineNumber,nsTokenAllocator* aTokenAllocator,nsNodeAllocator* aNodeAllocator)
{
#ifdef HEAP_ALLOCATED_NODES
return new
#else
nsFixedSizeAllocator& pool = aNodeAllocator->GetArenaPool();
void* place = pool.Alloc(sizeof(nsCParserNode));
return ::new (place)
#endif
nsCParserNode(aToken, aLineNumber, aTokenAllocator, aNodeAllocator);
}
static void Destroy(nsCParserNode* aNode, nsFixedSizeAllocator& aPool)
{
#ifdef HEAP_ALLOCATED_NODES
delete aNode;
#else
aNode->~nsCParserNode();
aPool.Free(aNode, sizeof(*aNode));
#endif
}
@ -248,7 +267,6 @@ class nsCParserNode : public nsIParserNode {
#ifdef HEAP_ALLOCATED_NODES
nsNodeAllocator* mNodeAllocator; // weak
#endif
};
#endif

View File

@ -33,6 +33,20 @@
* of that particular token type gets detected in the
* input stream.
*
* CToken objects that are allocated from the heap _must_ be allocated
* using the nsTokenAllocator: the nsTokenAllocator object uses an
* arena to manage the tokens.
*
* The nsTokenAllocator object's arena implementation requires
* object size at destruction time to properly recycle the object;
* therefore, CToken::operator delete() is not public. Instead,
* heap-allocated tokens should be destroyed using the static
* Destroy() method, which accepts a token and the arena from which
* the token was allocated.
*
* Leaf classes (that are actually instantiated from the heap) must
* implement the SizeOf() method, which Destroy() uses to determine
* the size of the token in order to properly recycle it.
*/
@ -45,9 +59,8 @@
#include "nsFileSpec.h"
#include "nsFixedSizeAllocator.h"
class nsScanner;
class nsTokenAllocator;
enum eContainerInfo {
eWellFormed,
@ -55,6 +68,14 @@ enum eContainerInfo {
eFormUnknown
};
/**
* Implement the SizeOf() method; leaf classes derived from CToken
* must declare this.
*/
#define CTOKEN_IMPL_SIZEOF \
protected: \
virtual size_t SizeOf() const { return sizeof(*this); } \
public:
/**
* Token objects represent sequences of characters as they
@ -70,27 +91,43 @@ class CToken {
enum eTokenOrigin {eSource,eResidualStyle};
protected:
// nsTokenAllocator should be the only class that tries to
// allocate tokens from the heap.
friend class nsTokenAllocator;
/**
*
* @update harishd 08/01/00
* @param aSize -
* @param aArena - Allocate memory from this pool.
*/
static void * operator new (size_t aSize, nsFixedSizeAllocator& anArena)
static void * operator new (size_t aSize,nsFixedSizeAllocator& anArena)
{
return anArena.Alloc(aSize);
}
/**
*
*
* @update harishd 08/01/00
* @param aPtr - The memory that should be recycled/freed.
* @param aSize - The size of memory that needs to be freed.
* Hide operator delete; clients should use Destroy() instead.
*/
static void operator delete (void* aPtr,size_t aSize)
static void operator delete (void*,size_t) {}
public:
/**
* destructor
* @update gess5/11/98
*/
virtual ~CToken();
/**
* Destroy a token.
*/
static void Destroy(CToken* aToken,nsFixedSizeAllocator& aArenaPool)
{
nsFixedSizeAllocator::Free(aPtr,aSize);
size_t sz = aToken->SizeOf();
aToken->~CToken();
aArenaPool.Free(aToken, sz);
}
/**
@ -103,22 +140,17 @@ class CToken {
* Free yourself if no one is holding you.
* @update harishd 08/02/00
*/
void Release() {
void Release(nsFixedSizeAllocator& aArenaPool) {
if(--mUseCount==0)
delete this;
Destroy(this, aArenaPool);
}
/**
* Default constructor
* @update gess7/21/98
*/
CToken(PRInt32 aTag=0);
/**
* destructor
* @update gess5/11/98
*/
virtual ~CToken();
/**
* Retrieve string value of the token
* @update gess5/11/98
@ -229,6 +261,10 @@ class CToken {
PRInt32 mNewlineCount;
protected:
/**
* Returns the size of the token object.
*/
virtual size_t SizeOf() const = 0;
PRInt32 mTypeID;
PRInt16 mAttrCount;

View File

@ -534,7 +534,7 @@ NS_IMETHODIMP CViewSourceHTML::BuildModel(nsIParser* aParser,nsITokenizer* aToke
if(theToken) {
result=HandleToken(theToken,aParser);
if(NS_SUCCEEDED(result)) {
IF_FREE(theToken);
IF_FREE(theToken, mTokenizer->GetTokenAllocator());
}
else if(NS_ERROR_HTMLPARSER_BLOCK!=result){
mTokenizer->PushTokenFront(theToken);

View File

@ -258,7 +258,7 @@ NS_IMETHODIMP CWellFormedDTD::BuildModel(nsIParser* aParser,nsITokenizer* aToken
if(theToken) {
result=HandleToken(theToken,aParser);
if(NS_SUCCEEDED(result) || (NS_ERROR_HTMLPARSER_BLOCK==result)) {
IF_FREE(theToken);
IF_FREE(theToken, mTokenizer->GetTokenAllocator());
}
else {
// if(NS_ERROR_HTMLPARSER_BLOCK!=result){
@ -362,7 +362,7 @@ nsresult CWellFormedDTD::Terminate(nsIParser* aParser)
if(theType==eToken_error) {
result=HandleToken(theToken,aParser);
}
IF_FREE(theToken);
IF_FREE(theToken, mTokenizer->GetTokenAllocator());
}
else break;
}//while
@ -717,7 +717,7 @@ nsresult CWellFormedDTD::HandleErrorToken(CToken* aToken) {
// Do nothing
break;
}
IF_FREE(token);
IF_FREE(token, mTokenizer->GetTokenAllocator());
}
else
break;

View File

@ -48,6 +48,7 @@
*/
#include <new>
#include "nsCOMPtr.h"
#include "nsIComponentManager.h"
#include "nsIEnumerator.h"
@ -76,6 +77,10 @@ static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
// CompositeDataSourceImpl
//
class CompositeEnumeratorImpl;
class CompositeArcsInOutEnumeratorImpl;
class CompositeAssertionEnumeratorImpl;
class CompositeDataSourceImpl : public nsIRDFCompositeDataSource,
public nsIRDFObserver
{
@ -112,6 +117,10 @@ protected:
nsFixedSizeAllocator mAllocator;
virtual ~CompositeDataSourceImpl() {}
friend class CompositeEnumeratorImpl;
friend class CompositeArcsInOutEnumeratorImpl;
friend class CompositeAssertionEnumeratorImpl;
};
//----------------------------------------------------------------------
@ -121,25 +130,7 @@ protected:
class CompositeEnumeratorImpl : public nsISimpleEnumerator
{
public:
static void* operator new(size_t aSize, nsFixedSizeAllocator& aAllocator) {
return aAllocator.Alloc(aSize); }
static void operator delete(void* aPtr, size_t aSize) {
nsFixedSizeAllocator::Free(aPtr, aSize); }
#if defined(HAVE_CPP_EXCEPTIONS) && defined(HAVE_CPP_PLACEMENT_DELETE)
static void operator delete(void* aPtr, size_t aSize, nsFixedSizeAllocator& aAllocator) {
nsFixedSizeAllocator::Free(aPtr, aSize); }
#endif
CompositeEnumeratorImpl(CompositeDataSourceImpl* aCompositeDataSource,
PRBool aAllowNegativeAssertions,
PRBool aCoalesceDuplicateArcs);
virtual ~CompositeEnumeratorImpl();
// nsISupports interface
// nsISupports
NS_DECL_ISUPPORTS
// nsISimpleEnumerator interface
@ -152,7 +143,15 @@ public:
virtual nsresult
HasNegation(nsIRDFDataSource* aDataSource, nsIRDFNode* aNode, PRBool* aResult) = 0;
virtual void Destroy() = 0;
protected:
CompositeEnumeratorImpl(CompositeDataSourceImpl* aCompositeDataSource,
PRBool aAllowNegativeAssertions,
PRBool aCoalesceDuplicateArcs);
virtual ~CompositeEnumeratorImpl();
CompositeDataSourceImpl* mCompositeDataSource;
nsISimpleEnumerator* mCurrent;
@ -165,8 +164,8 @@ protected:
CompositeEnumeratorImpl::CompositeEnumeratorImpl(CompositeDataSourceImpl* aCompositeDataSource,
PRBool aAllowNegativeAssertions,
PRBool aCoalesceDuplicateArcs)
PRBool aAllowNegativeAssertions,
PRBool aCoalesceDuplicateArcs)
: mCompositeDataSource(aCompositeDataSource),
mCurrent(nsnull),
mResult(nsnull),
@ -195,8 +194,9 @@ CompositeEnumeratorImpl::~CompositeEnumeratorImpl(void)
NS_RELEASE(mCompositeDataSource);
}
NS_IMPL_ISUPPORTS1(CompositeEnumeratorImpl, nsISimpleEnumerator);
NS_IMPL_ADDREF(CompositeEnumeratorImpl)
NS_IMPL_RELEASE_WITH_DESTROY(CompositeEnumeratorImpl, Destroy())
NS_IMPL_QUERY_INTERFACE1(CompositeEnumeratorImpl, nsISimpleEnumerator);
NS_IMETHODIMP
CompositeEnumeratorImpl::HasMoreElements(PRBool* aResult)
@ -356,11 +356,20 @@ class CompositeArcsInOutEnumeratorImpl : public CompositeEnumeratorImpl
public:
enum Type { eArcsIn, eArcsOut };
CompositeArcsInOutEnumeratorImpl(CompositeDataSourceImpl* aCompositeDataSource,
nsIRDFNode* aNode,
Type aType,
PRBool aAllowNegativeAssertions,
PRBool aCoalesceDuplicateArcs);
static CompositeArcsInOutEnumeratorImpl*
Create(nsFixedSizeAllocator& aAllocator,
CompositeDataSourceImpl* aCompositeDataSource,
nsIRDFNode* aNode,
Type aType,
PRBool aAllowNegativeAssertions,
PRBool aCoalesceDuplicateArcs) {
void* place = aAllocator.Alloc(sizeof(CompositeArcsInOutEnumeratorImpl));
return place
? ::new (place) CompositeArcsInOutEnumeratorImpl(aCompositeDataSource,
aNode, aType,
aAllowNegativeAssertions,
aCoalesceDuplicateArcs)
: nsnull; }
virtual ~CompositeArcsInOutEnumeratorImpl();
@ -370,11 +379,25 @@ public:
virtual nsresult
HasNegation(nsIRDFDataSource* aDataSource, nsIRDFNode* aNode, PRBool* aResult);
virtual void Destroy();
protected:
CompositeArcsInOutEnumeratorImpl(CompositeDataSourceImpl* aCompositeDataSource,
nsIRDFNode* aNode,
Type aType,
PRBool aAllowNegativeAssertions,
PRBool aCoalesceDuplicateArcs);
private:
nsIRDFNode* mNode;
Type mType;
PRBool mAllowNegativeAssertions;
PRBool mCoalesceDuplicateArcs;
// Hide so that only Create() and Destroy() can be used to
// allocate and deallocate from the heap
static void* operator new(size_t) { return 0; }
static void operator delete(void*, size_t) {}
};
@ -423,6 +446,19 @@ CompositeArcsInOutEnumeratorImpl::HasNegation(
return NS_OK;
}
void
CompositeArcsInOutEnumeratorImpl::Destroy()
{
// Keep the datasource alive for the duration of the stack
// frame so its allocator stays valid.
nsCOMPtr<nsIRDFCompositeDataSource> kungFuDeathGrip =
dont_QueryInterface(mCompositeDataSource);
nsFixedSizeAllocator& pool = mCompositeDataSource->mAllocator;
this->~CompositeArcsInOutEnumeratorImpl();
pool.Free(this, sizeof(*this));
}
//----------------------------------------------------------------------
//
@ -432,6 +468,33 @@ CompositeArcsInOutEnumeratorImpl::HasNegation(
class CompositeAssertionEnumeratorImpl : public CompositeEnumeratorImpl
{
public:
static CompositeAssertionEnumeratorImpl*
Create(nsFixedSizeAllocator& aAllocator,
CompositeDataSourceImpl* aCompositeDataSource,
nsIRDFResource* aSource,
nsIRDFResource* aProperty,
nsIRDFNode* aTarget,
PRBool aTruthValue,
PRBool aAllowNegativeAssertions,
PRBool aCoalesceDuplicateArcs) {
void* place = aAllocator.Alloc(sizeof(CompositeAssertionEnumeratorImpl));
return place
? ::new (place) CompositeAssertionEnumeratorImpl(aCompositeDataSource,
aSource, aProperty, aTarget,
aTruthValue,
aAllowNegativeAssertions,
aCoalesceDuplicateArcs)
: nsnull; }
virtual nsresult
GetEnumerator(nsIRDFDataSource* aDataSource, nsISimpleEnumerator** aResult);
virtual nsresult
HasNegation(nsIRDFDataSource* aDataSource, nsIRDFNode* aNode, PRBool* aResult);
virtual void Destroy();
protected:
CompositeAssertionEnumeratorImpl(CompositeDataSourceImpl* aCompositeDataSource,
nsIRDFResource* aSource,
nsIRDFResource* aProperty,
@ -442,12 +505,6 @@ public:
virtual ~CompositeAssertionEnumeratorImpl();
virtual nsresult
GetEnumerator(nsIRDFDataSource* aDataSource, nsISimpleEnumerator** aResult);
virtual nsresult
HasNegation(nsIRDFDataSource* aDataSource, nsIRDFNode* aNode, PRBool* aResult);
private:
nsIRDFResource* mSource;
nsIRDFResource* mProperty;
@ -455,6 +512,11 @@ private:
PRBool mTruthValue;
PRBool mAllowNegativeAssertions;
PRBool mCoalesceDuplicateArcs;
// Hide so that only Create() and Destroy() can be used to
// allocate and deallocate from the heap
static void* operator new(size_t) { return 0; }
static void operator delete(void*, size_t) {}
};
@ -515,6 +577,19 @@ CompositeAssertionEnumeratorImpl::HasNegation(
}
}
void
CompositeAssertionEnumeratorImpl::Destroy()
{
// Keep the datasource alive for the duration of the stack
// frame so its allocator stays valid.
nsCOMPtr<nsIRDFCompositeDataSource> kungFuDeathGrip =
dont_QueryInterface(mCompositeDataSource);
nsFixedSizeAllocator& pool = mCompositeDataSource->mAllocator;
this->~CompositeAssertionEnumeratorImpl();
pool.Free(this, sizeof(*this));
}
////////////////////////////////////////////////////////////////////////
nsresult
@ -693,8 +768,12 @@ CompositeDataSourceImpl::GetSources(nsIRDFResource* aProperty,
if ((mAllowNegativeAssertions == PR_FALSE) && (aTruthValue == PR_FALSE))
return(NS_RDF_NO_VALUE);
*aResult = new (mAllocator) CompositeAssertionEnumeratorImpl(this, nsnull, aProperty,
aTarget, aTruthValue, mAllowNegativeAssertions, mCoalesceDuplicateArcs);
*aResult = CompositeAssertionEnumeratorImpl::Create(mAllocator,
this, nsnull, aProperty,
aTarget, aTruthValue,
mAllowNegativeAssertions,
mCoalesceDuplicateArcs);
if (! *aResult)
return NS_ERROR_OUT_OF_MEMORY;
@ -797,8 +876,13 @@ CompositeDataSourceImpl::GetTargets(nsIRDFResource* aSource,
if ((mAllowNegativeAssertions == PR_FALSE) && (aTruthValue == PR_FALSE))
return(NS_RDF_NO_VALUE);
*aResult = new (mAllocator) CompositeAssertionEnumeratorImpl(this, aSource, aProperty,
nsnull, aTruthValue, mAllowNegativeAssertions, mCoalesceDuplicateArcs);
*aResult =
CompositeAssertionEnumeratorImpl::Create(mAllocator, this,
aSource, aProperty, nsnull,
aTruthValue,
mAllowNegativeAssertions,
mCoalesceDuplicateArcs);
if (! *aResult)
return NS_ERROR_OUT_OF_MEMORY;
@ -1133,9 +1217,10 @@ CompositeDataSourceImpl::ArcLabelsIn(nsIRDFNode* aTarget, nsISimpleEnumerator**
return NS_ERROR_NULL_POINTER;
nsISimpleEnumerator* result =
new (mAllocator) CompositeArcsInOutEnumeratorImpl(this, aTarget,
CompositeArcsInOutEnumeratorImpl::eArcsIn,
mAllowNegativeAssertions, mCoalesceDuplicateArcs);
CompositeArcsInOutEnumeratorImpl::Create(mAllocator, this, aTarget,
CompositeArcsInOutEnumeratorImpl::eArcsIn,
mAllowNegativeAssertions,
mCoalesceDuplicateArcs);
if (! result)
return NS_ERROR_OUT_OF_MEMORY;
@ -1158,9 +1243,10 @@ CompositeDataSourceImpl::ArcLabelsOut(nsIRDFResource* aSource,
return NS_ERROR_NULL_POINTER;
nsISimpleEnumerator* result =
new (mAllocator) CompositeArcsInOutEnumeratorImpl(this, aSource,
CompositeArcsInOutEnumeratorImpl::eArcsOut,
mAllowNegativeAssertions, mCoalesceDuplicateArcs);
CompositeArcsInOutEnumeratorImpl::Create(mAllocator, this, aSource,
CompositeArcsInOutEnumeratorImpl::eArcsOut,
mAllowNegativeAssertions,
mCoalesceDuplicateArcs);
if (! result)
return NS_ERROR_OUT_OF_MEMORY;

View File

@ -73,7 +73,7 @@
#include "nsXPIDLString.h"
#include "nsFixedSizeAllocator.h"
#include "rdfutil.h"
#include "plhash.h"
#include "pldhash.h"
#include "plstr.h"
#include "prlog.h"
#include "rdf.h"
@ -98,32 +98,35 @@ static PRLogModuleInfo* gLog = nsnull;
class Assertion
{
public:
static void* operator new(size_t aSize, nsFixedSizeAllocator& aAllocator) {
return aAllocator.Alloc(aSize); }
static Assertion*
Create(nsFixedSizeAllocator& aAllocator,
nsIRDFResource* aSource,
nsIRDFResource* aProperty,
nsIRDFNode* aTarget,
PRBool aTruthValue) {
void* place = aAllocator.Alloc(sizeof(Assertion));
return place
? ::new (place) Assertion(aSource, aProperty, aTarget, aTruthValue)
: nsnull; }
static void operator delete(void* aPtr, size_t aSize) {
nsFixedSizeAllocator::Free(aPtr, aSize); }
#if defined(HAVE_CPP_EXCEPTIONS) && defined(HAVE_CPP_PLACEMENT_DELETE)
static void operator delete(void* aPtr, size_t aSize, nsFixedSizeAllocator& aAllocator) {
nsFixedSizeAllocator::Free(aPtr, aSize); }
#endif
static void
Destroy(nsFixedSizeAllocator& aAllocator,
Assertion* aAssertion) {
aAssertion->~Assertion();
aAllocator.Free(aAssertion, sizeof(*aAssertion)); }
Assertion(nsIRDFResource* aSource,
nsIRDFResource* aProperty,
nsIRDFNode* aTarget,
PRBool aTruthValue);
void AddRef()
{
++mRefCnt;
}
~Assertion();
void Release()
{
void AddRef() { ++mRefCnt; }
void Release(nsFixedSizeAllocator& aAllocator) {
if (--mRefCnt == 0)
delete this;
}
Destroy(aAllocator, this); }
// public for now, because I'm too lazy to go thru and clean this up.
nsIRDFResource* mSource; // OWNER
@ -140,8 +143,11 @@ public:
PRBool IsMarked() { return mMarked; }
void Unmark() { mMarked = PR_FALSE; }
protected:
~Assertion();
private:
// Hide so that only Create() and Destroy() can be used to
// allocate and deallocate from the heap
static void* operator new(size_t) { return 0; }
static void operator delete(void*, size_t) {}
};
@ -191,6 +197,8 @@ rdf_HashPointer(const void* key)
////////////////////////////////////////////////////////////////////////
// InMemoryDataSource
class InMemoryArcsEnumeratorImpl;
class InMemoryAssertionEnumeratorImpl;
class InMemoryResourceEnumeratorImpl;
class InMemoryDataSource : public nsIRDFDataSource,
@ -204,31 +212,23 @@ protected:
// nsIRDFResource object per unique URI). The value of an entry is
// an Assertion struct, which is a linked list of (subject
// predicate object) triples.
PLHashTable* mForwardArcs;
PLHashTable* mReverseArcs;
static PLHashAllocOps gAllocOps;
static void* PR_CALLBACK AllocTable(void* aPool, PRSize aSize) {
return new char[aSize]; }
static void PR_CALLBACK FreeTable(void* aPool, void* aItem) {
delete[] NS_STATIC_CAST(char*, aItem); }
static PLHashEntry* PR_CALLBACK AllocEntry(void* aPool, const void* aKey) {
void* result = NS_STATIC_CAST(nsFixedSizeAllocator*, aPool)->Alloc(sizeof(PLHashEntry));
return NS_REINTERPRET_CAST(PLHashEntry*, result); }
static void PR_CALLBACK FreeEntry(void* aPool, PLHashEntry* aHashEntry, PRUintn aFlag) {
if (aFlag == HT_FREE_ENTRY)
nsFixedSizeAllocator::Free(aHashEntry, sizeof(PLHashEntry)); }
PLDHashTable mForwardArcs;
PLDHashTable mReverseArcs;
nsCOMPtr<nsISupportsArray> mObservers;
static const PRInt32 kInitialTableSize;
static PRIntn PR_CALLBACK DeleteForwardArcsEntry(PLHashEntry* he, PRIntn i, void* arg);
static PLDHashOperator PR_CALLBACK
DeleteForwardArcsEntry(PLDHashTable* aTable, PLDHashEntryHdr* aHdr,
PRUint32 aNumber, void* aArg);
static PLDHashOperator PR_CALLBACK
ResourceEnumerator(PLDHashTable* aTable, PLDHashEntryHdr* aHdr,
PRUint32 aNumber, void* aArg);
friend class InMemoryArcsEnumeratorImpl;
friend class InMemoryAssertionEnumeratorImpl;
friend class InMemoryResourceEnumeratorImpl; // b/c it needs to enumerate mForwardArcs
// Thread-safe writer implementation methods.
@ -251,7 +251,6 @@ protected:
NS_NewRDFInMemoryDataSource(nsISupports* aOuter, const nsIID& aIID, void** aResult);
public:
NS_DECL_AGGREGATED
// nsIRDFDataSource methods
@ -261,43 +260,51 @@ public:
NS_DECL_NSIRDFPURGEABLEDATASOURCE
protected:
static PRIntn PR_CALLBACK SweepForwardArcsEntries(PLHashEntry* he, PRIntn i, void* arg);
static PLDHashOperator PR_CALLBACK
SweepForwardArcsEntries(PLDHashTable* aTable, PLDHashEntryHdr* aHdr,
PRUint32 aNumber, void* aArg);
struct Entry {
PLDHashEntryHdr mHdr;
nsIRDFNode* mNode;
Assertion* mAssertions;
};
public:
// Implementation methods
Assertion* GetForwardArcs(nsIRDFResource* u)
{
// Use PL_HashTableRawLookup() so we can inline the hash
PLHashEntry** hep = PL_HashTableRawLookup(mForwardArcs, rdf_HashPointer(u), u);
return NS_REINTERPRET_CAST(Assertion*, *hep ? ((*hep)->value) : 0);
}
Assertion*
GetForwardArcs(nsIRDFResource* u) {
PLDHashEntryHdr* hdr = PL_DHashTableOperate(&mForwardArcs, u, PL_DHASH_LOOKUP);
return PL_DHASH_ENTRY_IS_BUSY(hdr)
? NS_REINTERPRET_CAST(Entry*, hdr)->mAssertions
: nsnull; }
Assertion* GetReverseArcs(nsIRDFNode* v)
{
// Use PL_HashTableRawLookup() so we can inline the hash
PLHashEntry** hep = PL_HashTableRawLookup(mReverseArcs, rdf_HashPointer(v), v);
return NS_REINTERPRET_CAST(Assertion*, *hep ? ((*hep)->value) : 0);
}
Assertion*
GetReverseArcs(nsIRDFNode* v) {
PLDHashEntryHdr* hdr = PL_DHashTableOperate(&mReverseArcs, v, PL_DHASH_LOOKUP);
return PL_DHASH_ENTRY_IS_BUSY(hdr)
? NS_REINTERPRET_CAST(Entry*, hdr)->mAssertions
: nsnull; }
void SetForwardArcs(nsIRDFResource* u, Assertion* as)
{
if (as) {
PL_HashTableAdd(mForwardArcs, u, as);
}
else {
PL_HashTableRemove(mForwardArcs, u);
}
}
void
SetForwardArcs(nsIRDFResource* u, Assertion* as) {
PLDHashEntryHdr* hdr = PL_DHashTableOperate(&mForwardArcs, u,
as ? PL_DHASH_ADD : PL_DHASH_REMOVE);
if (as && hdr) {
Entry* entry = NS_REINTERPRET_CAST(Entry*, hdr);
entry->mNode = u;
entry->mAssertions = as;
} }
void SetReverseArcs(nsIRDFNode* v, Assertion* as)
{
if (as) {
PL_HashTableAdd(mReverseArcs, v, as);
}
else {
PL_HashTableRemove(mReverseArcs, v);
}
}
void
SetReverseArcs(nsIRDFNode* v, Assertion* as) {
PLDHashEntryHdr* hdr = PL_DHashTableOperate(&mReverseArcs, v,
as ? PL_DHASH_ADD : PL_DHASH_REMOVE);
if (as && hdr) {
Entry* entry = NS_REINTERPRET_CAST(Entry*, hdr);
entry->mNode = v;
entry->mAssertions = as;
} }
#ifdef PR_LOGGING
void
@ -314,13 +321,10 @@ public:
#endif
};
PLHashAllocOps InMemoryDataSource::gAllocOps = {
AllocTable, FreeTable, AllocEntry, FreeEntry };
const PRInt32 InMemoryDataSource::kInitialTableSize = 32;
////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------
//
// InMemoryAssertionEnumeratorImpl
//
/**
* InMemoryAssertionEnumeratorImpl
@ -337,17 +341,10 @@ private:
PRBool mTruthValue;
Assertion* mNextAssertion;
public:
static void* operator new(size_t aSize, nsFixedSizeAllocator& aAllocator) {
return aAllocator.Alloc(aSize); }
static void operator delete(void* aPtr, size_t aSize) {
nsFixedSizeAllocator::Free(aPtr, aSize); }
#if defined(HAVE_CPP_EXCEPTIONS) && defined(HAVE_CPP_PLACEMENT_DELETE)
static void operator delete(void* aPtr, size_t aSize, nsFixedSizeAllocator& aAllocator) {
nsFixedSizeAllocator::Free(aPtr, aSize); }
#endif
// Hide so that only Create() and Destroy() can be used to
// allocate and deallocate from the heap
static void* operator new(size_t) { return 0; }
static void operator delete(void*, size_t) {}
InMemoryAssertionEnumeratorImpl(InMemoryDataSource* aDataSource,
nsIRDFResource* aSource,
@ -357,6 +354,33 @@ public:
virtual ~InMemoryAssertionEnumeratorImpl();
public:
static InMemoryAssertionEnumeratorImpl*
Create(InMemoryDataSource* aDataSource,
nsIRDFResource* aSource,
nsIRDFResource* aProperty,
nsIRDFNode* aTarget,
PRBool aTruthValue) {
void* place = aDataSource->mAllocator.Alloc(sizeof(InMemoryAssertionEnumeratorImpl));
return place
? ::new (place) InMemoryAssertionEnumeratorImpl(aDataSource,
aSource, aProperty, aTarget,
aTruthValue)
: nsnull; }
static void
Destroy(InMemoryAssertionEnumeratorImpl* aEnumerator) {
// Keep the datasource alive for the duration of the stack
// frame so its allocator stays valid.
nsCOMPtr<nsIRDFDataSource> kungFuDeathGrip =
dont_QueryInterface(aEnumerator->mDataSource);
// Grab the pool from the datasource; since we keep the
// datasource alive, this has to be safe.
nsFixedSizeAllocator& pool = aEnumerator->mDataSource->mAllocator;
aEnumerator->~InMemoryAssertionEnumeratorImpl();
pool.Free(aEnumerator, sizeof(*aEnumerator)); }
// nsISupports interface
NS_DECL_ISUPPORTS
@ -409,7 +433,7 @@ InMemoryAssertionEnumeratorImpl::~InMemoryAssertionEnumeratorImpl()
#endif
if (mNextAssertion)
mNextAssertion->Release();
mNextAssertion->Release(mDataSource->mAllocator);
NS_IF_RELEASE(mDataSource);
NS_IF_RELEASE(mSource);
@ -418,7 +442,9 @@ InMemoryAssertionEnumeratorImpl::~InMemoryAssertionEnumeratorImpl()
NS_IF_RELEASE(mValue);
}
NS_IMPL_ISUPPORTS1(InMemoryAssertionEnumeratorImpl, nsISimpleEnumerator)
NS_IMPL_ADDREF(InMemoryAssertionEnumeratorImpl)
NS_IMPL_RELEASE_WITH_DESTROY(InMemoryAssertionEnumeratorImpl, Destroy(this))
NS_IMPL_QUERY_INTERFACE1(InMemoryAssertionEnumeratorImpl, nsISimpleEnumerator)
NS_IMETHODIMP
InMemoryAssertionEnumeratorImpl::HasMoreElements(PRBool* aResult)
@ -455,7 +481,7 @@ InMemoryAssertionEnumeratorImpl::HasMoreElements(PRBool* aResult)
mNextAssertion->AddRef();
// ...and release the reference from the enumerator to the old one.
as->Release();
as->Release(mDataSource->mAllocator);
if (foundIt) {
*aResult = PR_TRUE;
@ -501,6 +527,11 @@ InMemoryAssertionEnumeratorImpl::GetNext(nsISupports** aResult)
class InMemoryArcsEnumeratorImpl : public nsISimpleEnumerator
{
private:
// Hide so that only Create() and Destroy() can be used to
// allocate and deallocate from the heap
static void* operator new(size_t) { return 0; }
static void operator delete(void*, size_t) {}
InMemoryDataSource* mDataSource;
nsIRDFResource* mSource;
nsIRDFNode* mTarget;
@ -508,29 +539,40 @@ private:
nsIRDFResource* mCurrent;
Assertion* mAssertion;
public:
static void* operator new(size_t aSize, nsFixedSizeAllocator& aAllocator) {
return aAllocator.Alloc(aSize); }
static void operator delete(void* aPtr, size_t aSize) {
nsFixedSizeAllocator::Free(aPtr, aSize); }
#if defined(HAVE_CPP_EXCEPTIONS) && defined(HAVE_CPP_PLACEMENT_DELETE)
static void operator delete(void* aPtr, size_t aSize, nsFixedSizeAllocator& aAllocator) {
nsFixedSizeAllocator::Free(aPtr, aSize); }
#endif
InMemoryArcsEnumeratorImpl(InMemoryDataSource* aDataSource,
nsIRDFResource* aSource,
nsIRDFNode* aTarget);
virtual ~InMemoryArcsEnumeratorImpl();
public:
// nsISupports interface
NS_DECL_ISUPPORTS
// nsISimpleEnumerator interface
NS_DECL_NSISIMPLEENUMERATOR
static InMemoryArcsEnumeratorImpl*
Create(InMemoryDataSource* aDataSource,
nsIRDFResource* aSource,
nsIRDFNode* aTarget) {
void* place = aDataSource->mAllocator.Alloc(sizeof(InMemoryArcsEnumeratorImpl));
return place
? ::new (place) InMemoryArcsEnumeratorImpl(aDataSource, aSource, aTarget)
: nsnull; }
static void
Destroy(InMemoryArcsEnumeratorImpl* aEnumerator) {
// Keep the datasource alive for the duration of the stack
// frame so its allocator stays valid.
nsCOMPtr<nsIRDFDataSource> kungFuDeathGrip =
dont_QueryInterface(aEnumerator->mDataSource);
// Grab the pool from the datasource; since we keep the
// datasource alive, this has to be safe.
nsFixedSizeAllocator& pool = aEnumerator->mDataSource->mAllocator;
aEnumerator->~InMemoryArcsEnumeratorImpl();
pool.Free(aEnumerator, sizeof(*aEnumerator)); }
};
@ -574,7 +616,9 @@ InMemoryArcsEnumeratorImpl::~InMemoryArcsEnumeratorImpl()
}
}
NS_IMPL_ISUPPORTS1(InMemoryArcsEnumeratorImpl, nsISimpleEnumerator)
NS_IMPL_ADDREF(InMemoryArcsEnumeratorImpl)
NS_IMPL_RELEASE_WITH_DESTROY(InMemoryArcsEnumeratorImpl, Destroy(this))
NS_IMPL_QUERY_INTERFACE1(InMemoryArcsEnumeratorImpl, nsISimpleEnumerator)
NS_IMETHODIMP
InMemoryArcsEnumeratorImpl::HasMoreElements(PRBool* aResult)
@ -678,8 +722,6 @@ NS_NewRDFInMemoryDataSource(nsISupports* aOuter, const nsIID& aIID, void** aResu
InMemoryDataSource::InMemoryDataSource(nsISupports* aOuter)
: mForwardArcs(nsnull),
mReverseArcs(nsnull)
{
NS_INIT_AGGREGATED(aOuter);
@ -705,25 +747,17 @@ InMemoryDataSource::InMemoryDataSource(nsISupports* aOuter)
nsresult
InMemoryDataSource::Init()
{
mForwardArcs = PL_NewHashTable(kInitialTableSize,
rdf_HashPointer,
PL_CompareValues,
PL_CompareValues,
&gAllocOps,
&mAllocator);
PL_DHashTableInit(&mForwardArcs,
PL_DHashGetStubOps(),
nsnull,
sizeof(Entry),
PL_DHASH_MIN_SIZE);
if (! mForwardArcs)
return NS_ERROR_OUT_OF_MEMORY;
mReverseArcs = PL_NewHashTable(kInitialTableSize,
rdf_HashPointer,
PL_CompareValues,
PL_CompareValues,
&gAllocOps,
&mAllocator);
if (! mReverseArcs)
return NS_ERROR_OUT_OF_MEMORY;
PL_DHashTableInit(&mReverseArcs,
PL_DHashGetStubOps(),
nsnull,
sizeof(Entry),
PL_DHASH_MIN_SIZE);
#ifdef MOZ_THREADSAFE_RDF
mLock = PR_NewLock();
@ -747,20 +781,14 @@ InMemoryDataSource::~InMemoryDataSource()
fprintf(stdout, "%d - RDF: InMemoryDataSource\n", gInstanceCount);
#endif
if (mForwardArcs) {
// This'll release all of the Assertion objects that are
// associated with this data source. We only need to do this
// for the forward arcs, because the reverse arcs table
// indexes the exact same set of resources.
PL_HashTableEnumerateEntries(mForwardArcs, DeleteForwardArcsEntry, nsnull);
// This'll release all of the Assertion objects that are
// associated with this data source. We only need to do this
// for the forward arcs, because the reverse arcs table
// indexes the exact same set of resources.
PL_DHashTableEnumerate(&mForwardArcs, DeleteForwardArcsEntry, &mAllocator);
PL_DHashTableFinish(&mForwardArcs);
PL_HashTableDestroy(mForwardArcs);
mForwardArcs = nsnull;
}
if (mReverseArcs) {
PL_HashTableDestroy(mReverseArcs);
mReverseArcs = nsnull;
}
PL_DHashTableFinish(&mReverseArcs);
PR_LOG(gLog, PR_LOG_ALWAYS,
("InMemoryDataSource(%p): destroyed.", this));
@ -770,19 +798,23 @@ InMemoryDataSource::~InMemoryDataSource()
#endif
}
PRIntn
InMemoryDataSource::DeleteForwardArcsEntry(PLHashEntry* he, PRIntn i, void* arg)
PLDHashOperator PR_CALLBACK
InMemoryDataSource::DeleteForwardArcsEntry(PLDHashTable* aTable, PLDHashEntryHdr* aHdr,
PRUint32 aNumber, void* aArg)
{
Assertion* as = (Assertion*) he->value;
Entry* entry = NS_REINTERPRET_CAST(Entry*, aHdr);
nsFixedSizeAllocator* allocator = NS_STATIC_CAST(nsFixedSizeAllocator*, aArg);
Assertion* as = entry->mAssertions;
while (as) {
Assertion* doomed = as;
as = as->mNext;
// Unlink, and release the datasource's reference.
doomed->mNext = doomed->mInvNext = nsnull;
doomed->Release();
doomed->Release(*allocator);
}
return HT_ENUMERATE_NEXT;
return PL_DHASH_NEXT;
}
@ -1005,8 +1037,9 @@ InMemoryDataSource::GetSources(nsIRDFResource* aProperty,
NS_AUTOLOCK(mLock);
InMemoryAssertionEnumeratorImpl* result
= new (mAllocator) InMemoryAssertionEnumeratorImpl(this, nsnull, aProperty, aTarget, aTruthValue);
InMemoryAssertionEnumeratorImpl* result =
InMemoryAssertionEnumeratorImpl::Create(this, nsnull, aProperty,
aTarget, aTruthValue);
if (! result)
return NS_ERROR_OUT_OF_MEMORY;
@ -1037,8 +1070,9 @@ InMemoryDataSource::GetTargets(nsIRDFResource* aSource,
NS_AUTOLOCK(mLock);
InMemoryAssertionEnumeratorImpl* result
= new (mAllocator) InMemoryAssertionEnumeratorImpl(this, aSource, aProperty, nsnull, aTruthValue);
InMemoryAssertionEnumeratorImpl* result =
InMemoryAssertionEnumeratorImpl::Create(this, aSource, aProperty,
nsnull, aTruthValue);
if (! result)
return NS_ERROR_OUT_OF_MEMORY;
@ -1080,7 +1114,7 @@ InMemoryDataSource::LockedAssert(nsIRDFResource* aSource,
next = next->mNext;
}
as = new (mAllocator) Assertion(aSource, aProperty, aTarget, aTruthValue);
as = Assertion::Create(mAllocator, aSource, aProperty, aTarget, aTruthValue);
if (! as)
return NS_ERROR_OUT_OF_MEMORY;
@ -1219,7 +1253,7 @@ InMemoryDataSource::LockedUnassert(nsIRDFResource* aSource,
// Unlink, and release the datasource's reference
as->mNext = as->mInvNext = nsnull;
as->Release();
as->Release(mAllocator);
return NS_OK;
}
@ -1457,7 +1491,7 @@ InMemoryDataSource::ArcLabelsIn(nsIRDFNode* aTarget, nsISimpleEnumerator** aResu
return NS_ERROR_NULL_POINTER;
InMemoryArcsEnumeratorImpl* result =
new (mAllocator) InMemoryArcsEnumeratorImpl(this, nsnull, aTarget);
InMemoryArcsEnumeratorImpl::Create(this, nsnull, aTarget);
if (! result)
return NS_ERROR_OUT_OF_MEMORY;
@ -1478,7 +1512,7 @@ InMemoryDataSource::ArcLabelsOut(nsIRDFResource* aSource, nsISimpleEnumerator**
NS_AUTOLOCK(mLock);
InMemoryArcsEnumeratorImpl* result =
new (mAllocator) InMemoryArcsEnumeratorImpl(this, aSource, nsnull);
InMemoryArcsEnumeratorImpl::Create(this, aSource, nsnull);
if (! result)
return NS_ERROR_OUT_OF_MEMORY;
@ -1489,16 +1523,16 @@ InMemoryDataSource::ArcLabelsOut(nsIRDFResource* aSource, nsISimpleEnumerator**
return NS_OK;
}
static PRIntn PR_CALLBACK
rdf_ResourceEnumerator(PLHashEntry* he, PRIntn i, void* closure)
PLDHashOperator PR_CALLBACK
InMemoryDataSource::ResourceEnumerator(PLDHashTable* aTable,
PLDHashEntryHdr* aHdr,
PRUint32 aNumber, void* aArg)
{
nsISupportsArray* resources = NS_STATIC_CAST(nsISupportsArray*, closure);
Entry* entry = NS_REINTERPRET_CAST(Entry*, aHdr);
nsISupportsArray* resources = NS_STATIC_CAST(nsISupportsArray*, aArg);
nsIRDFResource* resource =
NS_CONST_CAST(nsIRDFResource*, NS_STATIC_CAST(const nsIRDFResource*, he->key));
resources->AppendElement(resource);
return HT_ENUMERATE_NEXT;
resources->AppendElement(entry->mNode);
return PL_DHASH_NEXT;
}
@ -1514,7 +1548,7 @@ InMemoryDataSource::GetAllResources(nsISimpleEnumerator** aResult)
NS_AUTOLOCK(mLock);
// Enumerate all of our entries into an nsISupportsArray.
PL_HashTableEnumerateEntries(mForwardArcs, rdf_ResourceEnumerator, values.get());
PL_DHashTableEnumerate(&mForwardArcs, ResourceEnumerator, values.get());
*aResult = new nsArrayEnumerator(values);
if (! *aResult)
@ -1610,18 +1644,18 @@ InMemoryDataSource::Mark(nsIRDFResource* aSource,
struct SweepInfo {
Assertion* mUnassertList;
PLHashTable* mReverseArcs;
PLDHashTable* mReverseArcs;
};
NS_IMETHODIMP
InMemoryDataSource::Sweep()
{
SweepInfo info = { nsnull, mReverseArcs };
SweepInfo info = { nsnull, &mReverseArcs };
{
// Remove all the assertions while holding the lock, but don't notify anyone.
NS_AUTOLOCK(mLock);
PL_HashTableEnumerateEntries(mForwardArcs, SweepForwardArcsEntries, &info);
PL_DHashTableEnumerate(&mForwardArcs, SweepForwardArcsEntries, &info);
}
// Now we've left the autolock. Do the notification.
@ -1649,19 +1683,22 @@ InMemoryDataSource::Sweep()
// Unlink, and release the datasource's reference
doomed->mNext = doomed->mInvNext = nsnull;
doomed->Release();
doomed->Release(mAllocator);
}
return NS_OK;
}
PRIntn
InMemoryDataSource::SweepForwardArcsEntries(PLHashEntry* he, PRIntn i, void* arg)
PLDHashOperator PR_CALLBACK
InMemoryDataSource::SweepForwardArcsEntries(PLDHashTable* aTable,
PLDHashEntryHdr* aHdr,
PRUint32 aNumber, void* aArg)
{
SweepInfo* info = (SweepInfo*) arg;
Entry* entry = NS_REINTERPRET_CAST(Entry*, aHdr);
SweepInfo* info = NS_STATIC_CAST(SweepInfo*, aArg);
Assertion* as = (Assertion*) he->value;
Assertion* as = entry->mAssertions;
Assertion* prev = nsnull;
while (as) {
if (as->IsMarked()) {
@ -1677,17 +1714,17 @@ InMemoryDataSource::SweepForwardArcsEntries(PLHashEntry* he, PRIntn i, void* arg
}
else {
// it's the first one. update the hashtable entry.
he->value = next;
entry->mAssertions = next;
}
// remove from the reverse arcs
PLHashEntry** hep =
PL_HashTableRawLookup(info->mReverseArcs,
rdf_HashPointer(as->mTarget),
as->mTarget);
Assertion* ras = (Assertion*) ((*hep)->value);
NS_ASSERTION(ras != nsnull, "no assertion in reverse arcs");
PLDHashEntryHdr* hdr =
PL_DHashTableOperate(info->mReverseArcs, as->mTarget, PL_DHASH_LOOKUP);
NS_ASSERTION(PL_DHASH_ENTRY_IS_BUSY(hdr), "no assertion in reverse arcs");
Entry* rentry = NS_REINTERPRET_CAST(Entry*, hdr);
Assertion* ras = rentry->mAssertions;
Assertion* rprev = nsnull;
while (ras) {
if (ras == as) {
@ -1696,7 +1733,7 @@ InMemoryDataSource::SweepForwardArcsEntries(PLHashEntry* he, PRIntn i, void* arg
}
else {
// it's the first one. update the hashtable entry.
(*hep)->value = ras->mInvNext;
rentry->mAssertions = ras->mInvNext;
}
as->mInvNext = nsnull; // for my sanity.
break;
@ -1706,9 +1743,8 @@ InMemoryDataSource::SweepForwardArcsEntries(PLHashEntry* he, PRIntn i, void* arg
}
// Wow, it was the _only_ one. Unhash it.
if (! (*hep)->value)
PL_HashTableRawRemove(info->mReverseArcs, hep, *hep);
if (! rentry->mAssertions)
PL_DHashTableOperate(info->mReverseArcs, as->mTarget, PL_DHASH_REMOVE);
// add to the list of assertions to unassert
as->mNext = info->mUnassertList;
@ -1719,11 +1755,11 @@ InMemoryDataSource::SweepForwardArcsEntries(PLHashEntry* he, PRIntn i, void* arg
}
}
PRIntn result = HT_ENUMERATE_NEXT;
PLDHashOperator result = PL_DHASH_NEXT;
// if no more assertions exist for this resource, then unhash it.
if (! he->value)
result |= HT_ENUMERATE_REMOVE;
if (! entry->mAssertions)
result = PL_DHASH_REMOVE;
return result;
}

View File

@ -229,6 +229,40 @@ NS_IMETHODIMP_(nsrefcnt) _class::AddRef(void) \
return mRefCnt; \
}
/**
* Use this macro to implement the Release method for a given
* <i>_class</i>.
* @param _class The name of the class implementing the method
* @param _destroy A statement that is executed when the object's
* refcount drops to zero.
*
* For example,
*
* NS_IMPL_RELEASE_WITH_DESTROY(Foo, Destroy(this))
*
* will cause
*
* Destroy(this);
*
* to be invoked when the object's refcount drops to zero. This
* allows for arbitrary teardown activity to occur (e.g., deallocation
* of object allocated with placement new).
*/
#define NS_IMPL_RELEASE_WITH_DESTROY(_class, _destroy) \
NS_IMETHODIMP_(nsrefcnt) _class::Release(void) \
{ \
NS_PRECONDITION(0 != mRefCnt, "dup release"); \
NS_ASSERT_OWNINGTHREAD(_class); \
--mRefCnt; \
NS_LOG_RELEASE(this, mRefCnt, #_class); \
if (mRefCnt == 0) { \
mRefCnt = 1; /* stabilize */ \
_destroy; \
return 0; \
} \
return mRefCnt; \
}
/**
* Use this macro to implement the Release method for a given <i>_class</i>
* @param _class The name of the class implementing the method
@ -242,20 +276,8 @@ NS_IMETHODIMP_(nsrefcnt) _class::AddRef(void) \
* destructor, we make sure that no balanced refcounting can return
* the refcount to |0|.
*/
#define NS_IMPL_RELEASE(_class) \
NS_IMETHODIMP_(nsrefcnt) _class::Release(void) \
{ \
NS_PRECONDITION(0 != mRefCnt, "dup release"); \
NS_ASSERT_OWNINGTHREAD(_class); \
--mRefCnt; \
NS_LOG_RELEASE(this, mRefCnt, #_class); \
if (mRefCnt == 0) { \
mRefCnt = 1; /* stabilize */ \
NS_DELETEXPCOM(this); \
return 0; \
} \
return mRefCnt; \
}
#define NS_IMPL_RELEASE(_class) \
NS_IMPL_RELEASE_WITH_DESTROY(_class, NS_DELETEXPCOM(this))
///////////////////////////////////////////////////////////////////////////////

View File

@ -32,14 +32,13 @@
#include "nsCRT.h"
#include "nsFixedSizeAllocator.h"
nsresult
nsFixedSizeAllocator::Bucket *
nsFixedSizeAllocator::AddBucket(size_t aSize)
{
void* p;
PL_ARENA_ALLOCATE(p, &mPool, sizeof(Bucket));
if (! p)
return NS_ERROR_OUT_OF_MEMORY;
return nsnull;
Bucket* bucket = NS_STATIC_CAST(Bucket*, p);
bucket->mSize = aSize;
@ -47,11 +46,9 @@ nsFixedSizeAllocator::AddBucket(size_t aSize)
bucket->mNext = mBuckets;
mBuckets = bucket;
return NS_OK;
return bucket;
}
nsresult
nsFixedSizeAllocator::Init(const char* aName,
const size_t* aBucketSizes,
@ -77,33 +74,36 @@ nsFixedSizeAllocator::Init(const char* aName,
return NS_OK;
}
void*
nsFixedSizeAllocator::Alloc(size_t aSize)
nsFixedSizeAllocator::Bucket *
nsFixedSizeAllocator::FindBucket(size_t aSize)
{
Bucket** link = &mBuckets;
Bucket* bucket = mBuckets;
Bucket* bucket;
while (bucket != nsnull) {
while ((bucket = *link) != nsnull) {
if (aSize == bucket->mSize) {
// Promote to the head of the list, under the assumption
// that we'll allocate same-sized object cotemporaneously.
// that we'll allocate same-sized object contemporaneously.
*link = bucket->mNext;
bucket->mNext = mBuckets;
mBuckets = bucket;
break;
return bucket;
}
link = &bucket->mNext;
bucket = bucket->mNext;
}
return nsnull;
}
void*
nsFixedSizeAllocator::Alloc(size_t aSize)
{
Bucket* bucket = FindBucket(aSize);
if (! bucket) {
// Oops, we don't carry that size. Let's fix that.
nsresult rv = AddBucket(aSize);
if (NS_FAILED(rv))
bucket = AddBucket(aSize);
if (! bucket)
return nsnull;
bucket = mBuckets;
}
void* next;
@ -112,37 +112,29 @@ nsFixedSizeAllocator::Alloc(size_t aSize)
bucket->mFirst = bucket->mFirst->mNext;
}
else {
// Allocate headroom so we can have a backpointer. Use
// 'sizeof double' so that the block stays well-aligned
PL_ARENA_ALLOCATE(next, &mPool, aSize + sizeof(double));
FreeEntry* entry = NS_STATIC_CAST(FreeEntry*, next);
entry->mBucket = bucket;
PL_ARENA_ALLOCATE(next, &mPool, aSize);
if (!next)
return nsnull;
}
next = NS_STATIC_CAST(void*, NS_STATIC_CAST(char*, next) + sizeof(double));
#ifdef DEBUG
nsCRT::memset(next, 0xc8, bucket->mSize);
nsCRT::memset(next, 0xc8, aSize);
#endif
return next;
}
void
nsFixedSizeAllocator::Free(void* aPtr, size_t aSize)
{
FreeEntry* entry = NS_REINTERPRET_CAST(FreeEntry*, NS_STATIC_CAST(char*, aPtr) - sizeof(double));
Bucket* bucket = entry->mBucket;
FreeEntry* entry = NS_REINTERPRET_CAST(FreeEntry*, aPtr);
Bucket* bucket = FindBucket(aSize);
#ifdef DEBUG
NS_ASSERTION(bucket->mSize == aSize, "ack! corruption! bucket->mSize != aSize!");
NS_ASSERTION(bucket && bucket->mSize == aSize, "ack! corruption! bucket->mSize != aSize!");
nsCRT::memset(aPtr, 0xd8, bucket->mSize);
#endif
entry->mNext = bucket->mFirst;
bucket->mFirst = entry;
}

View File

@ -111,7 +111,7 @@
#include "nsError.h"
#include "plarena.h"
#define NS_SIZE_IN_HEAP(_size) ((_size) + sizeof(double))
#define NS_SIZE_IN_HEAP(_size) (_size)
class NS_COM nsFixedSizeAllocator
{
@ -125,7 +125,6 @@ protected:
friend struct FreeEntry;
struct FreeEntry {
Bucket* mBucket;
FreeEntry* mNext;
};
@ -137,15 +136,19 @@ protected:
Bucket* mBuckets;
nsresult
Bucket *
AddBucket(size_t aSize);
Bucket *
FindBucket(size_t aSize);
public:
nsFixedSizeAllocator() : mBuckets(nsnull) {}
~nsFixedSizeAllocator() {
if (mBuckets)
PL_FinishArenaPool(&mPool); }
PL_FinishArenaPool(&mPool);
}
/**
* Initialize the fixed size allocator. 'aName' is used to tag
@ -169,7 +172,7 @@ public:
/**
* Free a pointer allocated using a fixed-size allocator
*/
static void Free(void* aPtr, size_t aSize);
void Free(void* aPtr, size_t aSize);
};

View File

@ -229,6 +229,40 @@ NS_IMETHODIMP_(nsrefcnt) _class::AddRef(void) \
return mRefCnt; \
}
/**
* Use this macro to implement the Release method for a given
* <i>_class</i>.
* @param _class The name of the class implementing the method
* @param _destroy A statement that is executed when the object's
* refcount drops to zero.
*
* For example,
*
* NS_IMPL_RELEASE_WITH_DESTROY(Foo, Destroy(this))
*
* will cause
*
* Destroy(this);
*
* to be invoked when the object's refcount drops to zero. This
* allows for arbitrary teardown activity to occur (e.g., deallocation
* of object allocated with placement new).
*/
#define NS_IMPL_RELEASE_WITH_DESTROY(_class, _destroy) \
NS_IMETHODIMP_(nsrefcnt) _class::Release(void) \
{ \
NS_PRECONDITION(0 != mRefCnt, "dup release"); \
NS_ASSERT_OWNINGTHREAD(_class); \
--mRefCnt; \
NS_LOG_RELEASE(this, mRefCnt, #_class); \
if (mRefCnt == 0) { \
mRefCnt = 1; /* stabilize */ \
_destroy; \
return 0; \
} \
return mRefCnt; \
}
/**
* Use this macro to implement the Release method for a given <i>_class</i>
* @param _class The name of the class implementing the method
@ -242,20 +276,8 @@ NS_IMETHODIMP_(nsrefcnt) _class::AddRef(void) \
* destructor, we make sure that no balanced refcounting can return
* the refcount to |0|.
*/
#define NS_IMPL_RELEASE(_class) \
NS_IMETHODIMP_(nsrefcnt) _class::Release(void) \
{ \
NS_PRECONDITION(0 != mRefCnt, "dup release"); \
NS_ASSERT_OWNINGTHREAD(_class); \
--mRefCnt; \
NS_LOG_RELEASE(this, mRefCnt, #_class); \
if (mRefCnt == 0) { \
mRefCnt = 1; /* stabilize */ \
NS_DELETEXPCOM(this); \
return 0; \
} \
return mRefCnt; \
}
#define NS_IMPL_RELEASE(_class) \
NS_IMPL_RELEASE_WITH_DESTROY(_class, NS_DELETEXPCOM(this))
///////////////////////////////////////////////////////////////////////////////