Fixing bug 91241. Don't use the service manager to get the element factory everty time it's needed, cache it per namespace id, we spent about 0.9% of startup getting the element factory service. r=dp@netscape.com, sr=rpotts@netscape.com

This commit is contained in:
jst%netscape.com 2001-09-05 04:20:54 +00:00
Родитель 988c747a4f
Коммит 836da25092
6 изменённых файлов: 115 добавлений и 69 удалений

Просмотреть файл

@ -30,6 +30,7 @@
class nsIAtom;
class nsString;
class nsINameSpace;
class nsIElementFactory;
#define kNameSpaceID_Unknown -1
#define kNameSpaceID_None 0
@ -67,17 +68,24 @@ class nsINameSpace;
* The "html" and "xml" namespaces come "pre-canned" from the root.
*
*/
class nsINameSpaceManager : public nsISupports {
class nsINameSpaceManager : public nsISupports
{
public:
static const nsIID& GetIID() { static nsIID iid = NS_INAMESPACEMANAGER_IID; return iid; }
NS_DEFINE_STATIC_IID_ACCESSOR(NS_INAMESPACEMANAGER_IID)
NS_IMETHOD CreateRootNameSpace(nsINameSpace*& aRootNameSpace) = 0;
NS_IMETHOD RegisterNameSpace(const nsAReadableString& aURI,
PRInt32& aNameSpaceID) = 0;
NS_IMETHOD GetNameSpaceURI(PRInt32 aNameSpaceID, nsAWritableString& aURI) = 0;
NS_IMETHOD GetNameSpaceID(const nsAReadableString& aURI, PRInt32& aNameSpaceID) = 0;
NS_IMETHOD GetNameSpaceURI(PRInt32 aNameSpaceID,
nsAWritableString& aURI) = 0;
NS_IMETHOD GetNameSpaceID(const nsAReadableString& aURI,
PRInt32& aNameSpaceID) = 0;
NS_IMETHOD GetElementFactory(PRInt32 aNameSpaceID,
nsIElementFactory **aElementFactory) = 0;
};
extern NS_LAYOUT nsresult

Просмотреть файл

@ -22,13 +22,18 @@
#include "nscore.h"
#include "nsINameSpaceManager.h"
#include "nsINameSpace.h"
#include "nsISupportsArray.h"
#include "nsIElementFactory.h"
#include "nsIServiceManager.h"
#include "nsHashtable.h"
#include "nsVoidArray.h"
#include "nsLayoutAtoms.h"
#include "nsString.h"
#include "nsCRT.h"
#include "nsContentCID.h"
extern nsresult NS_NewXMLElementFactory(nsIElementFactory** aResult);
static const char kXMLNSNameSpaceURI[] = "http://www.w3.org/2000/xmlns/";
static const char kXMLNameSpaceURI[] = "http://www.w3.org/XML/1998/namespace";
@ -41,9 +46,10 @@ static const char kXSLTNameSpaceURI[] = "http://www.w3.org/1999/XSL/Transform";
//-----------------------------------------------------------
// Name Space ID table support
static PRInt32 gNameSpaceTableRefs;
static nsHashtable* gURIToIDTable;
static nsVoidArray* gURIArray;
static PRInt32 gNameSpaceTableRefs;
static nsHashtable* gURIToIDTable;
static nsVoidArray* gURIArray;
static nsISupportsArray* gElementFactoryArray;
static void AddRefTable()
{
@ -78,9 +84,12 @@ static void AddRefTable()
gURIToIDTable->Put(&xlinkKey, (void*)kNameSpaceID_XLink);
gURIToIDTable->Put(&htmlKey, (void*)kNameSpaceID_HTML);
gURIToIDTable->Put(&xsltKey, (void*)kNameSpaceID_XSLT);
NS_NewISupportsArray(&gElementFactoryArray);
}
NS_ASSERTION(nsnull != gURIToIDTable, "no URI table");
NS_ASSERTION(nsnull != gURIArray, "no URI array");
NS_ASSERTION(nsnull != gElementFactoryArray, "no element factory array");
}
static void ReleaseTable()
@ -95,6 +104,8 @@ static void ReleaseTable()
delete gURIArray;
gURIToIDTable = nsnull;
gURIArray = nsnull;
NS_IF_RELEASE(gElementFactoryArray);
}
}
@ -341,8 +352,10 @@ public:
PRInt32& aNameSpaceID);
NS_IMETHOD GetNameSpaceURI(PRInt32 aNameSpaceID, nsAWritableString& aURI);
NS_IMETHOD GetNameSpaceID(const nsAReadableString& aURI, PRInt32& aNameSpaceID);
NS_IMETHOD GetNameSpaceID(const nsAReadableString& aURI,
PRInt32& aNameSpaceID);
NS_IMETHOD GetElementFactory(PRInt32 aNameSpaceID,
nsIElementFactory **aElementFactory);
private:
// These are not supported and are not implemented!
NameSpaceManagerImpl(const NameSpaceManagerImpl& aCopy);
@ -427,6 +440,67 @@ NameSpaceManagerImpl::GetNameSpaceID(const nsAReadableString& aURI, PRInt32& aNa
return NS_OK;
}
NS_IMETHODIMP
NameSpaceManagerImpl::GetElementFactory(PRInt32 aNameSpaceID,
nsIElementFactory **aElementFactory)
{
*aElementFactory = nsnull;
NS_ENSURE_TRUE(gElementFactoryArray, NS_ERROR_NOT_INITIALIZED);
NS_ENSURE_TRUE(aNameSpaceID >= 0, NS_ERROR_ILLEGAL_VALUE);
gElementFactoryArray->QueryElementAt(aNameSpaceID,
NS_GET_IID(nsIElementFactory),
(void **)aElementFactory);
if (*aElementFactory) {
return NS_OK;
}
nsAutoString uri;
GetNameSpaceURI(aNameSpaceID, uri);
nsCOMPtr<nsIElementFactory> ef;
if (!uri.IsEmpty()) {
nsCAutoString contract_id(NS_ELEMENT_FACTORY_CONTRACTID_PREFIX);
contract_id.Append(NS_ConvertUCS2toUTF8(uri));
ef = do_GetService(contract_id.get());
}
if (!ef) {
nsresult rv = NS_NewXMLElementFactory(getter_AddRefs(ef));
if (NS_FAILED(rv)) {
return rv;
}
}
PRUint32 count = 0;
gElementFactoryArray->Count(&count);
if ((PRUint32)aNameSpaceID < count) {
gElementFactoryArray->ReplaceElementAt(ef, aNameSpaceID);
} else {
// This sucks, simply doing an InsertElementAt() should IMNSHO
// automatically grow the array and insert null's as needed to
// fill up the array!?!!
for (PRInt32 i = count; i < aNameSpaceID; i++) {
gElementFactoryArray->AppendElement(nsnull);
}
gElementFactoryArray->AppendElement(ef);
}
*aElementFactory = ef;
NS_ADDREF(*aElementFactory);
return NS_OK;
}
NS_LAYOUT nsresult
NS_NewNameSpaceManager(nsINameSpaceManager** aInstancePtrResult)
{

Просмотреть файл

@ -193,6 +193,8 @@ nsXMLContentSink::Init(nsIDocument* aDoc,
nsIURI* aURL,
nsIWebShell* aContainer)
{
NS_ENSURE_TRUE(gNameSpaceManager, NS_ERROR_OUT_OF_MEMORY);
NS_PRECONDITION(nsnull != aDoc, "null ptr");
NS_PRECONDITION(nsnull != aURL, "null ptr");
if ((nsnull == aDoc) || (nsnull == aURL)) {
@ -691,8 +693,6 @@ nsXMLContentSink::OpenContainer(const nsIParserNode& aNode)
// This is done based off a contractid/namespace scheme.
nsCOMPtr<nsIElementFactory> elementFactory;
// This should *not* be done for every node, only when we find
// a new namespace!!! -- jst
GetElementFactory(nameSpaceID, getter_AddRefs(elementFactory));
if (elementFactory) {
// Create the content element using the element factory.
@ -1542,7 +1542,8 @@ PRInt32
nsXMLContentSink::GetNameSpaceId(nsIAtom* aPrefix)
{
PRInt32 id = (nsnull == aPrefix) ? kNameSpaceID_None : kNameSpaceID_Unknown;
if ((nsnull != mNameSpaceStack) && (0 < mNameSpaceStack->Count())) {
if (mNameSpaceStack && mNameSpaceStack->Count() > 0) {
PRInt32 index = mNameSpaceStack->Count() - 1;
nsINameSpace* nameSpace = (nsINameSpace*)mNameSpaceStack->ElementAt(index);
nameSpace->FindNameSpaceID(aPrefix, id);
@ -1890,18 +1891,8 @@ XMLElementFactoryImpl::CreateInstanceByTag(nsINodeInfo *aNodeInfo,
}
void
nsXMLContentSink::GetElementFactory(PRInt32 aNameSpaceID, nsIElementFactory** aResult)
nsXMLContentSink::GetElementFactory(PRInt32 aNameSpaceID,
nsIElementFactory** aResult)
{
nsresult rv;
nsAutoString nameSpace;
gNameSpaceManager->GetNameSpaceURI(aNameSpaceID, nameSpace);
nsCAutoString contractID( NS_ELEMENT_FACTORY_CONTRACTID_PREFIX );
contractID.AppendWithConversion(nameSpace);
// Retrieve the appropriate factory.
nsCOMPtr<nsIElementFactory> elementFactory(do_GetService(contractID, &rv));
*aResult = elementFactory;
NS_IF_ADDREF(*aResult);
gNameSpaceManager->GetElementFactory(aNameSpaceID, aResult);
}

Просмотреть файл

@ -4347,14 +4347,6 @@ nsXULDocument::CreateElement(nsINodeInfo *aNodeInfo, nsIContent** aResult)
rv = nsXULElement::Create(aNodeInfo, getter_AddRefs(result));
if (NS_FAILED(rv)) return rv;
}
else if (aNodeInfo->NamespaceEquals(kNameSpaceID_HTML)) {
rv = gHTMLElementFactory->CreateInstanceByTag(aNodeInfo,
getter_AddRefs(result));
if (NS_FAILED(rv)) return rv;
if (! result)
return NS_ERROR_UNEXPECTED;
}
else {
PRInt32 namespaceID;
aNodeInfo->GetNamespaceID(namespaceID);
@ -5844,8 +5836,8 @@ nsXULDocument::CreateElement(nsXULPrototypeElement* aPrototype, nsIContent** aRe
nsCOMPtr<nsIElementFactory> elementFactory;
GetElementFactory(namespaceID,
getter_AddRefs(elementFactory));
elementFactory->CreateInstanceByTag(aPrototype->mNodeInfo,
getter_AddRefs(result));
rv = elementFactory->CreateInstanceByTag(aPrototype->mNodeInfo,
getter_AddRefs(result));
if (NS_FAILED(rv)) return rv;
if (! result)
@ -6582,27 +6574,18 @@ nsXULDocument::RemoveElement(nsIContent* aParent, nsIContent* aChild)
return NS_OK;
}
void
nsXULDocument::GetElementFactory(PRInt32 aNameSpaceID, nsIElementFactory** aResult)
void
nsXULDocument::GetElementFactory(PRInt32 aNameSpaceID,
nsIElementFactory** aResult)
{
nsresult rv;
nsAutoString nameSpace;
gNameSpaceManager->GetNameSpaceURI(aNameSpaceID, nameSpace);
// Retrieve the appropriate factory.
gNameSpaceManager->GetElementFactory(aNameSpaceID, aResult);
nsCAutoString contractID(NS_ELEMENT_FACTORY_CONTRACTID_PREFIX);
contractID.AppendWithConversion(nameSpace);
// Retrieve the appropriate factory.
nsCOMPtr<nsIElementFactory> elementFactory(do_GetService(contractID, &rv));
if (!elementFactory)
elementFactory = gXMLElementFactory; // Nothing found. Use generic XML element.
*aResult = elementFactory;
NS_IF_ADDREF(*aResult);
if (!*aResult) {
// Nothing found. Use generic XML element.
*aResult = gXMLElementFactory;
NS_IF_ADDREF(*aResult);
}
}
NS_IMETHODIMP

Просмотреть файл

@ -1634,21 +1634,12 @@ nsXULContentBuilder::SetContainerAttrs(nsIContent *aElement, const nsTemplateMat
void
nsXULContentBuilder::GetElementFactory(PRInt32 aNameSpaceID, nsIElementFactory** aResult)
{
nsresult rv;
nsAutoString nameSpace;
gNameSpaceManager->GetNameSpaceURI(aNameSpaceID, nameSpace);
gNameSpaceManager->GetElementFactory(aNameSpaceID, aResult);
nsCAutoString contractID(NS_ELEMENT_FACTORY_CONTRACTID_PREFIX);
contractID.AppendWithConversion(nameSpace.get());
// Retrieve the appropriate factory.
nsCOMPtr<nsIElementFactory> elementFactory(do_GetService(contractID, &rv));
if (!elementFactory)
elementFactory = gXMLElementFactory; // Nothing found. Use generic XML element.
*aResult = elementFactory;
NS_IF_ADDREF(*aResult);
if (!*aResult) {
*aResult = gXMLElementFactory; // Nothing found. Use generic XML element.
NS_IF_ADDREF(*aResult);
}
}
//----------------------------------------------------------------------

Просмотреть файл

@ -59,7 +59,6 @@
#include "nsIBindingManager.h"
#include "nsIDOMNodeList.h"
#include "nsIHTMLContent.h"
#include "nsIElementFactory.h"
#include "nsINameSpace.h"
#include "nsINameSpaceManager.h"
#include "nsIRDFCompositeDataSource.h"