mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-01-27 07:34:20 +00:00
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:
parent
b6f122d161
commit
3dcee9b795
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user