Bug 386769 - "Make setting innerHTML faster". r=jst, sr=peterv, a=blocking1.9.

This commit is contained in:
bent.mozilla@gmail.com 2008-02-08 14:07:51 -08:00
parent d582aeb0c8
commit 588f30c270
17 changed files with 235 additions and 65 deletions

View File

@ -941,6 +941,16 @@ public:
mJSObject = aJSObject;
}
// This method should return an addrefed nsIParser* or nsnull. Implementations
// should transfer ownership of the parser to the caller.
virtual already_AddRefed<nsIParser> GetFragmentParser() {
return nsnull;
}
virtual void SetFragmentParser(nsIParser* aParser) {
// Do nothing.
}
protected:
~nsIDocument()
{

View File

@ -147,10 +147,17 @@ nsScriptLoaderObserverProxy::ScriptEvaluated(nsresult aResult,
}
NS_IMPL_ISUPPORTS3(nsContentSink,
nsICSSLoaderObserver,
nsISupportsWeakReference,
nsIScriptLoaderObserver)
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsContentSink)
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsContentSink)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsContentSink)
NS_INTERFACE_MAP_ENTRY(nsICSSLoaderObserver)
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
NS_INTERFACE_MAP_ENTRY(nsIScriptLoaderObserver)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIScriptLoaderObserver)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTION_2(nsContentSink, mDocument, mParser)
nsContentSink::nsContentSink()
{

View File

@ -62,6 +62,7 @@
#include "prlog.h"
#include "nsIRequest.h"
#include "nsTimer.h"
#include "nsCycleCollectionParticipant.h"
class nsIDocument;
class nsIURI;
@ -114,7 +115,9 @@ class nsContentSink : public nsICSSLoaderObserver,
public nsStubDocumentObserver,
public nsITimerCallback
{
NS_DECL_ISUPPORTS
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsContentSink,
nsIScriptLoaderObserver)
NS_DECL_NSISCRIPTLOADEROBSERVER
// nsITimerCallback

View File

@ -78,6 +78,8 @@
#include "nsIParser.h"
#include "nsIFragmentContentSink.h"
#include "nsIContentSink.h"
#include "nsIHTMLContentSink.h"
#include "nsIXMLContentSink.h"
#include "nsHTMLParts.h"
#include "nsIParserService.h"
#include "nsIServiceManager.h"
@ -130,7 +132,6 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_XTFSERVICE_CID);
#include "nsIEventListenerManager.h"
#include "nsAttrName.h"
#include "nsIDOMUserDataHandler.h"
#include "nsIFragmentContentSink.h"
#include "nsContentCreatorFunctions.h"
#include "nsTPtrArray.h"
#include "nsGUIEvent.h"
@ -3325,11 +3326,7 @@ nsContentUtils::CreateContextualFragment(nsIDOMNode* aContextNode,
NS_ENSURE_ARG(aContextNode);
*aReturn = nsnull;
// Create a new parser for this entire operation
nsresult rv;
nsCOMPtr<nsIParser> parser = do_CreateInstance(kCParserCID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsINode> node = do_QueryInterface(aContextNode);
NS_ENSURE_TRUE(node, NS_ERROR_NOT_AVAILABLE);
@ -3402,17 +3399,52 @@ nsContentUtils::CreateContextualFragment(nsIDOMNode* aContextNode,
nsCOMPtr<nsIHTMLDocument> htmlDoc(do_QueryInterface(document));
PRBool bHTML = htmlDoc && !bCaseSensitive;
nsCOMPtr<nsIFragmentContentSink> sink;
if (bHTML) {
rv = NS_NewHTMLFragmentContentSink(getter_AddRefs(sink));
} else {
rv = NS_NewXMLFragmentContentSink(getter_AddRefs(sink));
// See if the document has a cached fragment parser. nsHTMLDocument is the
// only one that should really have one at the moment.
nsCOMPtr<nsIParser> parser = document->GetFragmentParser();
if (parser) {
// Get the parser ready to use.
parser->Reset();
}
else {
// Create a new parser for this operation.
parser = do_CreateInstance(kCParserCID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
}
// See if the parser already has a content sink that we can reuse.
nsCOMPtr<nsIFragmentContentSink> sink;
nsCOMPtr<nsIContentSink> contentsink = parser->GetContentSink();
if (contentsink) {
// Make sure it's the correct type.
if (bHTML) {
nsCOMPtr<nsIHTMLContentSink> htmlsink = do_QueryInterface(contentsink);
sink = do_QueryInterface(htmlsink);
}
else {
nsCOMPtr<nsIXMLContentSink> xmlsink = do_QueryInterface(contentsink);
sink = do_QueryInterface(xmlsink);
}
}
if (!sink) {
// Either there was no cached content sink or it was the wrong type. Make a
// new one.
if (bHTML) {
rv = NS_NewHTMLFragmentContentSink(getter_AddRefs(sink));
} else {
rv = NS_NewXMLFragmentContentSink(getter_AddRefs(sink));
}
NS_ENSURE_SUCCESS(rv, rv);
contentsink = do_QueryInterface(sink);
NS_ASSERTION(contentsink, "Sink doesn't QI to nsIContentSink!");
parser->SetContentSink(contentsink);
}
NS_ENSURE_SUCCESS(rv, rv);
sink->SetTargetDocument(document);
nsCOMPtr<nsIContentSink> contentsink(do_QueryInterface(sink));
parser->SetContentSink(contentsink);
nsDTDMode mode = eDTDMode_autodetect;
switch (document->GetCompatibilityMode()) {
@ -3437,6 +3469,8 @@ nsContentUtils::CreateContextualFragment(nsIDOMNode* aContextNode,
rv = sink->GetFragment(aReturn);
}
document->SetFragmentParser(parser);
return NS_OK;
}

View File

@ -408,6 +408,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsHTMLDocument, nsDocument)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mEmbeds)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mLinks)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mAnchors)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mFragmentParser)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mForms, nsIDOMNodeList)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mFormControls,
nsIDOMNodeList)

View File

@ -216,6 +216,13 @@ public:
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(nsHTMLDocument, nsDocument)
virtual already_AddRefed<nsIParser> GetFragmentParser() {
return mFragmentParser.forget();
}
virtual void SetFragmentParser(nsIParser* aParser) {
mFragmentParser = aParser;
}
protected:
nsresult GetBodySize(PRInt32* aWidth,
PRInt32* aHeight);
@ -382,6 +389,9 @@ protected:
PRInt32 mDefaultNamespaceID;
PRBool mDisableCookieAccess;
// Parser used for constructing document fragments.
nsCOMPtr<nsIParser> mFragmentParser;
};
#endif /* nsHTMLDocument_h___ */

View File

@ -64,6 +64,7 @@
#include "nsIScriptSecurityManager.h"
#include "nsContentSink.h"
#include "nsTHashtable.h"
#include "nsCycleCollectionParticipant.h"
//
// XXX THIS IS TEMPORARY CODE
@ -79,7 +80,9 @@ public:
virtual ~nsHTMLFragmentContentSink();
// nsISupports
NS_DECL_ISUPPORTS
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsHTMLFragmentContentSink,
nsIContentSink)
NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
@ -223,12 +226,22 @@ nsHTMLFragmentContentSink::~nsHTMLFragmentContentSink()
}
}
NS_IMPL_ISUPPORTS3(nsHTMLFragmentContentSink,
nsIFragmentContentSink,
nsIHTMLContentSink,
nsIContentSink)
NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsHTMLFragmentContentSink,
nsIContentSink)
NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(nsHTMLFragmentContentSink,
nsIContentSink)
NS_IMETHODIMP
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsHTMLFragmentContentSink)
NS_INTERFACE_MAP_ENTRY(nsIFragmentContentSink)
NS_INTERFACE_MAP_ENTRY(nsIHTMLContentSink)
NS_INTERFACE_MAP_ENTRY(nsIContentSink)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContentSink)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTION_3(nsHTMLFragmentContentSink, mParser, mTargetDocument,
mRoot)
NS_IMETHODIMP
nsHTMLFragmentContentSink::WillBuildModel(void)
{
if (mRoot) {

View File

@ -185,15 +185,30 @@ nsXMLContentSink::Init(nsIDocument* aDoc,
return NS_OK;
}
NS_IMPL_ISUPPORTS_INHERITED7(nsXMLContentSink,
nsContentSink,
nsIContentSink,
nsIXMLContentSink,
nsIExpatSink,
nsITimerCallback,
nsIDocumentObserver,
nsIMutationObserver,
nsITransformObserver)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsXMLContentSink)
NS_INTERFACE_MAP_ENTRY(nsIContentSink)
NS_INTERFACE_MAP_ENTRY(nsIXMLContentSink)
NS_INTERFACE_MAP_ENTRY(nsIExpatSink)
NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
NS_INTERFACE_MAP_ENTRY(nsIDocumentObserver)
NS_INTERFACE_MAP_ENTRY(nsIMutationObserver)
NS_INTERFACE_MAP_ENTRY(nsITransformObserver)
NS_INTERFACE_MAP_END_INHERITING(nsContentSink)
NS_IMPL_ADDREF_INHERITED(nsXMLContentSink, nsContentSink)
NS_IMPL_RELEASE_INHERITED(nsXMLContentSink, nsContentSink)
NS_IMPL_CYCLE_COLLECTION_CLASS(nsXMLContentSink)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXMLContentSink,
nsContentSink)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mCurrentHead)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(mDocElement)
for (PRUint32 i = 0, count = tmp->mContentStack.Length(); i < count; i++) {
const StackNode& node = tmp->mContentStack.ElementAt(i);
cb.NoteXPCOMChild(node.mContent);
}
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
// nsIContentSink
NS_IMETHODIMP

View File

@ -45,7 +45,7 @@
#include "nsTArray.h"
#include "nsCOMPtr.h"
#include "nsCRT.h"
#include "nsCycleCollectionParticipant.h"
class nsIDocument;
class nsIURI;
@ -84,6 +84,9 @@ public:
// nsISupports
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(nsXMLContentSink,
nsContentSink)
NS_DECL_NSIEXPATSINK
// nsIContentSink

View File

@ -60,6 +60,7 @@
#include "nsTHashtable.h"
#include "nsHashKeys.h"
#include "nsTArray.h"
#include "nsCycleCollectionParticipant.h"
class nsXMLFragmentContentSink : public nsXMLContentSink,
public nsIFragmentContentSink
@ -72,6 +73,8 @@ public:
// nsISupports
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(nsXMLFragmentContentSink,
nsXMLContentSink)
// nsIExpatSink
NS_IMETHOD HandleDoctypeDecl(const nsAString & aSubset,
@ -169,9 +172,20 @@ nsXMLFragmentContentSink::~nsXMLFragmentContentSink()
{
}
NS_IMPL_ISUPPORTS_INHERITED1(nsXMLFragmentContentSink,
nsXMLContentSink,
nsIFragmentContentSink)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsXMLFragmentContentSink)
NS_INTERFACE_MAP_ENTRY(nsIFragmentContentSink)
NS_INTERFACE_MAP_END_INHERITING(nsXMLContentSink)
NS_IMPL_ADDREF_INHERITED(nsXMLFragmentContentSink, nsXMLContentSink)
NS_IMPL_RELEASE_INHERITED(nsXMLFragmentContentSink, nsXMLContentSink)
NS_IMPL_CYCLE_COLLECTION_CLASS(nsXMLFragmentContentSink)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXMLFragmentContentSink,
nsXMLContentSink)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mTargetDocument)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mRoot)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMETHODIMP
nsXMLFragmentContentSink::WillBuildModel(void)

View File

@ -287,6 +287,8 @@ class nsIParser : public nsISupports {
*/
NS_IMETHOD CancelParsingEvents() = 0;
virtual void Reset() = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIParser, NS_IPARSER_IID)

View File

@ -113,11 +113,18 @@ static const char kInvalidTagStackPos[] = "Error: invalid tag stack position";
#define NS_DTD_FLAG_HAS_MAIN_CONTAINER (NS_DTD_FLAG_HAD_BODY | \
NS_DTD_FLAG_HAD_FRAMESET)
NS_IMPL_ISUPPORTS1(CNavDTD, nsIDTD)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CNavDTD)
NS_INTERFACE_MAP_ENTRY(nsIDTD)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDTD)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(CNavDTD)
NS_IMPL_CYCLE_COLLECTING_RELEASE(CNavDTD)
NS_IMPL_CYCLE_COLLECTION_1(CNavDTD, mSink)
CNavDTD::CNavDTD()
: mMisplacedContent(0),
mSink(0),
mTokenAllocator(0),
mBodyContext(new nsDTDContext()),
mTempContext(0),
@ -181,8 +188,6 @@ CNavDTD::~CNavDTD()
}
}
#endif
NS_IF_RELEASE(mSink);
}
nsresult
@ -212,7 +217,7 @@ CNavDTD::WillBuildModel(const CParserContext& aParserContext,
START_TIMER();
if (NS_SUCCEEDED(result) && !mSink) {
result = CallQueryInterface(aSink, &mSink);
mSink = do_QueryInterface(aSink, &result);
if (NS_FAILED(result)) {
mFlags |= NS_DTD_FLAG_STOP_PARSING;
return result;

View File

@ -106,6 +106,7 @@
#include "nsTime.h"
#include "nsDTDUtils.h"
#include "nsParser.h"
#include "nsCycleCollectionParticipant.h"
class nsIHTMLContentSink;
class nsIParserNode;
@ -158,8 +159,9 @@ public:
eHTMLTags aTag,
nsEntryStack* aStyleStack = nsnull);
NS_DECL_ISUPPORTS
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_NSIDTD
NS_DECL_CYCLE_COLLECTION_CLASS(CNavDTD)
private:
/**
@ -381,7 +383,7 @@ protected:
nsDeque mMisplacedContent;
nsIHTMLContentSink* mSink;
nsCOMPtr<nsIHTMLContentSink> mSink;
nsTokenAllocator* mTokenAllocator;
nsDTDContext* mBodyContext;
nsDTDContext* mTempContext;

View File

@ -378,9 +378,16 @@ IsLoadableDTD(const nsCatalogData* aCatalogData, nsIURI* aDTD,
/***************************** END CATALOG UTILS *****************************/
NS_IMPL_ISUPPORTS2(nsExpatDriver,
nsITokenizer,
nsIDTD)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsExpatDriver)
NS_INTERFACE_MAP_ENTRY(nsITokenizer)
NS_INTERFACE_MAP_ENTRY(nsIDTD)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDTD)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsExpatDriver)
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsExpatDriver)
NS_IMPL_CYCLE_COLLECTION_2(nsExpatDriver, mSink, mExtendedSink)
nsExpatDriver::nsExpatDriver()
: mExpatParser(nsnull),

View File

@ -46,6 +46,7 @@
#include "nsITokenizer.h"
#include "nsIInputStream.h"
#include "nsIParser.h"
#include "nsCycleCollectionParticipant.h"
class nsIExpatSink;
class nsIExtendedExpatSink;
@ -55,9 +56,10 @@ class nsExpatDriver : public nsIDTD,
public nsITokenizer
{
public:
NS_DECL_ISUPPORTS
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_NSIDTD
NS_DECL_NSITOKENIZER
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsExpatDriver, nsIDTD)
nsExpatDriver();
virtual ~nsExpatDriver();

View File

@ -244,6 +244,17 @@ static PRBool gDumpContent=PR_FALSE;
* default constructor
*/
nsParser::nsParser()
{
Initialize(PR_TRUE);
}
nsParser::~nsParser()
{
Cleanup();
}
void
nsParser::Initialize(PRBool aConstructor)
{
#ifdef NS_DEBUG
if (!gDumpContent) {
@ -251,13 +262,22 @@ nsParser::nsParser()
}
#endif
if (aConstructor) {
// Raw pointer
mParserContext = 0;
}
else {
// nsCOMPtrs
mObserver = nsnull;
mParserFilter = nsnull;
}
mContinueEvent = nsnull;
mCharsetSource = kCharsetUninitialized;
mCharset.AssignLiteral("ISO-8859-1");
mParserContext=0;
mStreamStatus=0;
mCharsetSource=kCharsetUninitialized;
mInternalState=NS_OK;
mContinueEvent=nsnull;
mCommand=eViewNormal;
mInternalState = NS_OK;
mStreamStatus = 0;
mCommand = eViewNormal;
mFlags = NS_PARSER_FLAG_OBSERVERS_ENABLED |
NS_PARSER_FLAG_PARSER_ENABLED |
NS_PARSER_FLAG_CAN_TOKENIZE;
@ -268,12 +288,9 @@ nsParser::nsParser()
MOZ_TIMER_RESET(mTokenizeTime);
}
/**
* Destructor
*/
nsParser::~nsParser()
void
nsParser::Cleanup()
{
#ifdef NS_DEBUG
if (gDumpContent) {
if (mSink) {
@ -306,14 +323,31 @@ nsParser::~nsParser()
NS_ASSERTION(!(mFlags & NS_PARSER_FLAG_PENDING_CONTINUE_EVENT), "bad");
}
NS_IMPL_CYCLE_COLLECTION_2(nsParser, mSink, mObserver)
NS_IMPL_CYCLE_COLLECTION_CLASS(nsParser)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsParser)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mSink)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mObserver)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsParser)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mSink)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mObserver)
CParserContext *pc = tmp->mParserContext;
while (pc) {
cb.NoteXPCOMChild(pc->mDTD);
cb.NoteXPCOMChild(pc->mTokenizer);
pc = pc->mPrevContext;
}
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsParser, nsIParser)
NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(nsParser, nsIParser)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsParser)
NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
NS_INTERFACE_MAP_ENTRY(nsIParser)
NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIParser)
NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
NS_INTERFACE_MAP_ENTRY(nsIParser)
NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIParser)
NS_INTERFACE_MAP_END
// The parser continue event is posted only if

View File

@ -381,7 +381,15 @@ class nsParser : public nsIParser,
return sCharsetConverterManager;
}
protected:
virtual void Reset() {
Cleanup();
Initialize();
}
protected:
void Initialize(PRBool aConstructor = PR_FALSE);
void Cleanup();
/**
*