Bug 159314: Fastload is wasteful wrt nodenames. Instead of serializing nodename+namespaceURI for each element/attribute, serialize a table of all nodename+namespaces used by a document and then serialize pointers into that.

r=jst sr=hyatt
This commit is contained in:
sicking%bigfoot.com 2002-09-03 22:31:38 +00:00
parent b6f122d161
commit 3dcee9b795
7 changed files with 137 additions and 56 deletions

View File

@ -68,6 +68,7 @@ class nsINameSpaceManager;
class nsIDocument;
class nsIURI;
class nsIPrincipal;
class nsISupportsArray;
// IID for the nsINodeInfo interface
@ -384,6 +385,10 @@ public:
*/
NS_IMETHOD SetDocumentPrincipal(nsIPrincipal* aPrincipal) = 0;
/**
* Returns an nsISupportsArray of all nsINodeInfos managed by this manager
*/
NS_IMETHOD GetNodeInfoArray(nsISupportsArray** aArray) = 0;
};
extern nsresult NS_NewNodeInfoManager(nsINodeInfoManager** aResult);

View File

@ -43,6 +43,7 @@
#include "nsIAtom.h"
#include "nsIDocument.h"
#include "nsIPrincipal.h"
#include "nsISupportsArray.h"
nsNodeInfoManager* nsNodeInfoManager::gAnonymousNodeInfoManager = nsnull;
PRUint32 nsNodeInfoManager::gNodeManagerCount = 0;
@ -334,7 +335,6 @@ nsNodeInfoManager::GetNamespaceManager(nsINameSpaceManager*& aNameSpaceManager)
return NS_OK;
}
NS_IMETHODIMP
nsNodeInfoManager::GetDocument(nsIDocument*& aDocument)
{
@ -376,6 +376,44 @@ nsNodeInfoManager::SetDocumentPrincipal(nsIPrincipal* aPrincipal)
return NS_OK;
}
NS_IMETHODIMP
nsNodeInfoManager::GetNodeInfoArray(nsISupportsArray** aArray)
{
*aArray = nsnull;
nsCOMPtr<nsISupportsArray> array;
nsresult rv = NS_NewISupportsArray(getter_AddRefs(array));
NS_ENSURE_SUCCESS(rv, rv);
PL_HashTableEnumerateEntries(mNodeInfoHash,
GetNodeInfoArrayEnumerator,
array);
PRUint32 n;
array->Count(&n);
NS_ENSURE_TRUE(n == mNodeInfoHash->nentries, NS_ERROR_OUT_OF_MEMORY);
*aArray = array;
NS_ADDREF(*aArray);
return NS_OK;
}
//static
PRIntn
nsNodeInfoManager::GetNodeInfoArrayEnumerator(PLHashEntry* he, PRIntn i,
void* arg)
{
NS_ASSERTION(arg, "missing array");
nsISupportsArray* array = (nsISupportsArray*)arg;
nsresult rv = array->AppendElement((nsINodeInfo*)he->value);
if (NS_FAILED(rv)) {
return HT_ENUMERATE_STOP;
}
return HT_ENUMERATE_NEXT;
}
void
nsNodeInfoManager::RemoveNodeInfo(nsNodeInfo *aNodeInfo)
{

View File

@ -74,6 +74,7 @@ public:
NS_IMETHOD GetDocument(nsIDocument*& aDocument);
NS_IMETHOD GetDocumentPrincipal(nsIPrincipal** aPrincipal);
NS_IMETHOD SetDocumentPrincipal(nsIPrincipal* aPrincipal);
NS_IMETHOD GetNodeInfoArray(nsISupportsArray** aArray);
// nsNodeInfoManager
nsNodeInfoManager();
@ -88,6 +89,9 @@ private:
const void *key2);
static PLHashNumber PR_CALLBACK GetNodeInfoInnerHashValue(const void *key);
PR_STATIC_CALLBACK(PRIntn) GetNodeInfoArrayEnumerator(PLHashEntry* he,
PRIntn i,
void* arg);
PLHashTable *mNodeInfoHash;
nsCOMPtr<nsINameSpaceManager> mNameSpaceManager;

View File

@ -4926,7 +4926,8 @@ nsXULPrototypeAttribute::~nsXULPrototypeAttribute()
nsresult
nsXULPrototypeElement::Serialize(nsIObjectOutputStream* aStream,
nsIScriptContext* aContext)
nsIScriptContext* aContext,
nsISupportsArray* aNodeInfos)
{
nsresult rv;
@ -4935,25 +4936,19 @@ nsXULPrototypeElement::Serialize(nsIObjectOutputStream* aStream,
rv |= aStream->Write32(mLineNo);
// Write Node Info
nsAutoString namespaceURI;
rv |= mNodeInfo->GetNamespaceURI(namespaceURI);
rv |= aStream->WriteWStringZ(namespaceURI.get());
nsAutoString qualifiedName;
rv |= mNodeInfo->GetQualifiedName(qualifiedName);
rv |= aStream->WriteWStringZ(qualifiedName.get());
PRInt32 index = aNodeInfos->IndexOf(mNodeInfo);
NS_ASSERTION(index >= 0, "unknown nsINodeInfo index");
rv |= aStream->Write32(index);
// Write Attributes
rv |= aStream->Write32(mNumAttributes);
nsAutoString attributeValue, attributeNamespaceURI, attributeName;
nsAutoString attributeValue;
PRInt32 i;
for (i = 0; i < mNumAttributes; ++i) {
rv |= mAttributes[i].mNodeInfo->GetNamespaceURI(attributeNamespaceURI);
rv |= aStream->WriteWStringZ(attributeNamespaceURI.get());
rv |= mAttributes[i].mNodeInfo->GetQualifiedName(attributeName);
rv |= aStream->WriteWStringZ(attributeName.get());
index = aNodeInfos->IndexOf(mAttributes[i].mNodeInfo);
NS_ASSERTION(index >= 0, "unknown nsINodeInfo index");
rv |= aStream->Write32(index);
rv |= mAttributes[i].mValue.GetValue(attributeValue);
rv |= aStream->WriteWStringZ(attributeValue.get());
@ -4966,7 +4961,7 @@ nsXULPrototypeElement::Serialize(nsIObjectOutputStream* aStream,
switch (child->mType) {
case eType_Element:
case eType_Text:
rv |= child->Serialize(aStream, aContext);
rv |= child->Serialize(aStream, aContext, aNodeInfos);
break;
case eType_Script:
rv |= aStream->Write32(child->mType);
@ -4975,7 +4970,7 @@ nsXULPrototypeElement::Serialize(nsIObjectOutputStream* aStream,
if (script) {
rv |= aStream->WriteBoolean(script->mOutOfLine);
if (! script->mOutOfLine)
rv |= script->Serialize(aStream, aContext);
rv |= script->Serialize(aStream, aContext, aNodeInfos);
else
rv |= aStream->WriteCompoundObject(script->mSrcURI,
NS_GET_IID(nsIURI),
@ -4992,9 +4987,9 @@ nsresult
nsXULPrototypeElement::Deserialize(nsIObjectInputStream* aStream,
nsIScriptContext* aContext,
nsIURI* aDocumentURI,
nsINodeInfoManager* aNimgr)
nsISupportsArray* aNodeInfos)
{
NS_PRECONDITION(aNimgr, "missing nsINodeInfoManager");
NS_PRECONDITION(aNodeInfos, "missing nodeinfo array");
nsresult rv;
PRUint32 number;
@ -5002,13 +4997,10 @@ nsXULPrototypeElement::Deserialize(nsIObjectInputStream* aStream,
mLineNo = (PRInt32)number;
// Read Node Info
nsXPIDLString namespaceURI;
rv |= aStream->ReadWStringZ(getter_Copies(namespaceURI));
nsXPIDLString qualifiedName;
rv |= aStream->ReadWStringZ(getter_Copies(qualifiedName));
rv |= aNimgr->GetNodeInfo(qualifiedName, namespaceURI, *getter_AddRefs(mNodeInfo));
rv |= aStream->Read32(&number);
mNodeInfo = do_QueryElementAt(aNodeInfos, number);
if (!mNodeInfo)
return NS_ERROR_UNEXPECTED;
// Read Attributes
rv |= aStream->Read32(&number);
@ -5022,11 +5014,10 @@ nsXULPrototypeElement::Deserialize(nsIObjectInputStream* aStream,
nsXPIDLString attributeValue, attributeNamespaceURI, attributeName;
for (i = 0; i < mNumAttributes; ++i) {
rv |= aStream->ReadWStringZ(getter_Copies(attributeNamespaceURI));
rv |= aStream->ReadWStringZ(getter_Copies(attributeName));
rv |= aNimgr->GetNodeInfo(attributeName, attributeNamespaceURI,
*getter_AddRefs(mAttributes[i].mNodeInfo));
rv |= aStream->Read32(&number);
mAttributes[i].mNodeInfo = do_QueryElementAt(aNodeInfos, number);
if (!mAttributes[i].mNodeInfo)
return NS_ERROR_UNEXPECTED;
rv |= aStream->ReadWStringZ(getter_Copies(attributeValue));
mAttributes[i].mValue.SetValue(attributeValue);
@ -5074,7 +5065,7 @@ nsXULPrototypeElement::Deserialize(nsIObjectInputStream* aStream,
child->mType = childType;
rv |= child->Deserialize(aStream, aContext, aDocumentURI,
aNimgr);
aNodeInfos);
break;
case eType_Text:
child = new nsXULPrototypeText(-1);
@ -5083,7 +5074,7 @@ nsXULPrototypeElement::Deserialize(nsIObjectInputStream* aStream,
child->mType = childType;
rv |= child->Deserialize(aStream, aContext, aDocumentURI,
aNimgr);
aNodeInfos);
break;
case eType_Script:
// language version obtained during deserialization.
@ -5097,12 +5088,12 @@ nsXULPrototypeElement::Deserialize(nsIObjectInputStream* aStream,
rv |= aStream->ReadBoolean(&script->mOutOfLine);
if (! script->mOutOfLine) {
rv |= script->Deserialize(aStream, aContext,
aDocumentURI, aNimgr);
aDocumentURI, aNodeInfos);
}
else {
rv |= aStream->ReadObject(PR_TRUE, getter_AddRefs(script->mSrcURI));
rv |= script->DeserializeOutOfLineScript(aStream, aContext, aNimgr);
rv |= script->DeserializeOutOfLineScript(aStream, aContext);
}
}
@ -5168,7 +5159,8 @@ nsXULPrototypeScript::~nsXULPrototypeScript()
nsresult
nsXULPrototypeScript::Serialize(nsIObjectOutputStream* aStream,
nsIScriptContext* aContext)
nsIScriptContext* aContext,
nsISupportsArray* aNodeInfos)
{
nsresult rv;
@ -5230,7 +5222,7 @@ nsresult
nsXULPrototypeScript::Deserialize(nsIObjectInputStream* aStream,
nsIScriptContext* aContext,
nsIURI* aDocumentURI,
nsINodeInfoManager* aNimgr)
nsISupportsArray* aNodeInfos)
{
NS_TIMELINE_MARK_FUNCTION("chrome js deserialize");
nsresult rv;
@ -5316,8 +5308,7 @@ nsXULPrototypeScript::Deserialize(nsIObjectInputStream* aStream,
nsresult
nsXULPrototypeScript::DeserializeOutOfLineScript(nsIObjectInputStream* aInput,
nsIScriptContext* aContext,
nsINodeInfoManager* aNimgr)
nsIScriptContext* aContext)
{
// Keep track of FastLoad failure via rv, so we can
// AbortFastLoads if things look bad.
@ -5378,7 +5369,7 @@ nsXULPrototypeScript::DeserializeOutOfLineScript(nsIObjectInputStream* aInput,
// We're better off slow-loading than bailing out due to a
// FastLoad error.
if (NS_SUCCEEDED(rv))
rv = Deserialize(objectInput, aContext, nsnull, aNimgr);
rv = Deserialize(objectInput, aContext, nsnull, nsnull);
if (NS_SUCCEEDED(rv) && mSrcURI) {
rv = fastLoadService->EndMuxedDocument(mSrcURI);
@ -5503,7 +5494,7 @@ nsXULPrototypeScript::Compile(const PRUnichar* aText,
nsCOMPtr<nsIObjectOutputStream> objectOutput;
fastLoadService->GetOutputStream(getter_AddRefs(objectOutput));
if (objectOutput) {
rv = Serialize(objectOutput, context);
rv = Serialize(objectOutput, context, nsnull);
if (NS_FAILED(rv))
cache->AbortFastLoads();
}
@ -5522,7 +5513,8 @@ nsXULPrototypeScript::Compile(const PRUnichar* aText,
nsresult
nsXULPrototypeText::Serialize(nsIObjectOutputStream* aStream,
nsIScriptContext* aContext)
nsIScriptContext* aContext,
nsISupportsArray* aNodeInfos)
{
nsresult rv;
@ -5539,7 +5531,7 @@ nsresult
nsXULPrototypeText::Deserialize(nsIObjectInputStream* aStream,
nsIScriptContext* aContext,
nsIURI* aDocumentURI,
nsINodeInfoManager* aNimgr)
nsISupportsArray* aNodeInfos)
{
nsresult rv;

View File

@ -201,11 +201,12 @@ public:
virtual ~nsXULPrototypeNode() {}
virtual nsresult Serialize(nsIObjectOutputStream* aStream,
nsIScriptContext* aContext) = 0;
nsIScriptContext* aContext,
nsISupportsArray* aNodeInfos) = 0;
virtual nsresult Deserialize(nsIObjectInputStream* aStream,
nsIScriptContext* aContext,
nsIURI* aDocumentURI,
nsINodeInfoManager* aNimgr) = 0;
nsISupportsArray* aNodeInfos) = 0;
void AddRef() { mRefCnt++; };
void Release()
@ -258,11 +259,12 @@ public:
}
virtual nsresult Serialize(nsIObjectOutputStream* aStream,
nsIScriptContext* aContext);
nsIScriptContext* aContext,
nsISupportsArray* aNodeInfos);
virtual nsresult Deserialize(nsIObjectInputStream* aStream,
nsIScriptContext* aContext,
nsIURI* aDocumentURI,
nsINodeInfoManager* aNimgr);
nsISupportsArray* aNodeInfos);
PRInt32 mNumChildren;
nsXULPrototypeNode** mChildren; // [OWNER]
@ -304,14 +306,14 @@ public:
virtual ~nsXULPrototypeScript();
virtual nsresult Serialize(nsIObjectOutputStream* aStream,
nsIScriptContext* aContext);
nsIScriptContext* aContext,
nsISupportsArray* aNodeInfos);
virtual nsresult Deserialize(nsIObjectInputStream* aStream,
nsIScriptContext* aContext,
nsIURI* aDocumentURI,
nsINodeInfoManager* aNimgr);
nsISupportsArray* aNodeInfos);
virtual nsresult DeserializeOutOfLineScript(nsIObjectInputStream* aInput,
nsIScriptContext* aContext,
nsINodeInfoManager* aNimgr);
nsIScriptContext* aContext);
nsresult Compile(const PRUnichar* aText, PRInt32 aTextLength,
nsIURI* aURI, PRInt32 aLineNo,
@ -356,11 +358,12 @@ public:
}
virtual nsresult Serialize(nsIObjectOutputStream* aStream,
nsIScriptContext* aContext);
nsIScriptContext* aContext,
nsISupportsArray* aNodeInfos);
virtual nsresult Deserialize(nsIObjectInputStream* aStream,
nsIScriptContext* aContext,
nsIURI* aDocumentURI,
nsINodeInfoManager* aNimgr);
nsISupportsArray* aNodeInfos);
nsString mValue;
};

View File

@ -132,7 +132,8 @@ NS_NewXULPrototypeCache(nsISupports* aOuter, REFNSIID aIID, void** aResult);
const char XUL_FASTLOAD_FILE_BASENAME[] = "XUL";
#define XUL_FASTLOAD_FILE_VERSION (0xfeedbeef - 4)
// increase the subtractor when changing version
#define XUL_FASTLOAD_FILE_VERSION (0xfeedbeef - 5)
#define XUL_SERIALIZATION_BUFFER_SIZE (64 * 1024)
#define XUL_DESERIALIZATION_BUFFER_SIZE (8 * 1024)

View File

@ -367,13 +367,30 @@ nsXULPrototypeDocument::Read(nsIObjectInputStream* aStream)
NS_ASSERTION(scriptContext != nsnull,
"no prototype script context!");
// nsINodeInfo table
nsCOMPtr<nsISupportsArray> nodeInfos;
rv |= NS_NewISupportsArray(getter_AddRefs(nodeInfos));
NS_ENSURE_TRUE(nodeInfos, rv);
rv |= aStream->Read32(&referenceCount);
nsXPIDLString namespaceURI, qualifiedName;
for (i = 0; i < referenceCount; ++i) {
rv |= aStream->ReadWStringZ(getter_Copies(namespaceURI));
rv |= aStream->ReadWStringZ(getter_Copies(qualifiedName));
nsCOMPtr<nsINodeInfo> nodeInfo;
rv |= mNodeInfoManager->GetNodeInfo(qualifiedName, namespaceURI, *getter_AddRefs(nodeInfo));
rv |= nodeInfos->AppendElement(nodeInfo);
}
// Document contents
PRUint32 type;
rv |= aStream->Read32(&type);
if ((nsXULPrototypeNode::Type)type != nsXULPrototypeNode::eType_Element)
return NS_ERROR_FAILURE;
rv |= mRoot->Deserialize(aStream, scriptContext, mURI, mNodeInfoManager);
rv |= mRoot->Deserialize(aStream, scriptContext, mURI, nodeInfos);
rv |= NotifyLoadDone();
return rv;
@ -417,6 +434,27 @@ nsXULPrototypeDocument::Write(nsIObjectOutputStream* aStream)
// nsIPrincipal mDocumentPrincipal
rv |= NS_WriteOptionalObject(aStream, mDocumentPrincipal, PR_TRUE);
// nsINodeInfo table
nsCOMPtr<nsISupportsArray> nodeInfos;
rv |= mNodeInfoManager->GetNodeInfoArray(getter_AddRefs(nodeInfos));
NS_ENSURE_SUCCESS(rv, rv);
PRUint32 nodeInfoCount;
nodeInfos->Count(&nodeInfoCount);
rv |= aStream->Write32(nodeInfoCount);
for (i = 0; i < nodeInfoCount; ++i) {
nsCOMPtr<nsINodeInfo> nodeInfo = do_QueryElementAt(nodeInfos, i);
NS_ENSURE_TRUE(nodeInfo, NS_ERROR_FAILURE);
nsAutoString namespaceURI;
rv |= nodeInfo->GetNamespaceURI(namespaceURI);
rv |= aStream->WriteWStringZ(namespaceURI.get());
nsAutoString qualifiedName;
rv |= nodeInfo->GetQualifiedName(qualifiedName);
rv |= aStream->WriteWStringZ(qualifiedName.get());
}
// Now serialize the document contents
nsCOMPtr<nsIScriptGlobalObject> globalObject;
rv |= GetScriptGlobalObject(getter_AddRefs(globalObject));
@ -425,7 +463,7 @@ nsXULPrototypeDocument::Write(nsIObjectOutputStream* aStream)
rv |= globalObject->GetContext(getter_AddRefs(scriptContext));
if (mRoot)
rv |= mRoot->Serialize(aStream, scriptContext);
rv |= mRoot->Serialize(aStream, scriptContext, nodeInfos);
return rv;
}