Bug 600257. Only flush in content lists if we're in an XML document. r=peterv
authorBoris Zbarsky <bzbarsky@mit.edu>
Tue, 28 Sep 2010 13:46:08 -0400
changeset 63638 77483e45592e8dc5dd1e45d40d30eb4101b5accf
parent 63637 17d2910e2941f992881812363ff677e91e5ccacf
child 63639 85eb53e80ce1872292d6510c906e60d1c53333fe
push id19248
push usereakhgari@mozilla.com
push dateWed, 23 Mar 2011 23:19:35 +0000
treeherdermozilla-central@ab95ab9e389b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspeterv
bugs600257
milestone2.0b13pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 600257. Only flush in content lists if we're in an XML document. r=peterv
content/base/src/nsContentList.cpp
content/base/src/nsContentList.h
content/base/src/nsDocument.cpp
--- a/content/base/src/nsContentList.cpp
+++ b/content/base/src/nsContentList.cpp
@@ -410,16 +410,24 @@ nsContentList::nsContentList(nsINode* aR
   if (nsGkAtoms::_asterix == mHTMLMatchAtom) {
     NS_ASSERTION(mXMLMatchAtom == nsGkAtoms::_asterix, "HTML atom and XML atom are not both asterix?");
     mMatchAll = PR_TRUE;
   }
   else {
     mMatchAll = PR_FALSE;
   }
   mRootNode->AddMutationObserver(this);
+
+  // We only need to flush if we're in an non-HTML document, since the
+  // HTML5 parser doesn't need flushing.  Further, if we're not in a
+  // document at all right now (in the GetCurrentDoc() sense), we're
+  // not parser-created and don't need to be flushing stuff under us
+  // to get our kids right.
+  nsIDocument* doc = mRootNode->GetCurrentDoc();
+  mFlushesNeeded = doc && !doc->IsHTML();
 }
 
 nsContentList::nsContentList(nsINode* aRootNode,
                              nsContentListMatchFunc aFunc,
                              nsContentListDestroyFunc aDestroyFunc,
                              void* aData,
                              PRBool aDeep,
                              nsIAtom* aMatchAtom,
@@ -480,17 +488,17 @@ nsContentList::Length(PRBool aDoFlush)
   BringSelfUpToDate(aDoFlush);
     
   return mElements.Count();
 }
 
 nsIContent *
 nsContentList::Item(PRUint32 aIndex, PRBool aDoFlush)
 {
-  if (mRootNode && aDoFlush) {
+  if (mRootNode && aDoFlush && mFlushesNeeded) {
     // XXX sXBL/XBL2 issue
     nsIDocument* doc = mRootNode->GetCurrentDoc();
     if (doc) {
       // Flush pending content changes Bug 4891.
       doc->FlushPendingNotifications(Flush_ContentAndNotify);
     }
   }
 
@@ -927,17 +935,17 @@ nsContentList::RemoveFromHashtable()
     PL_DHashTableFinish(&gContentListHashTable);
     gContentListHashTable.ops = nsnull;
   }
 }
 
 void
 nsContentList::BringSelfUpToDate(PRBool aDoFlush)
 {
-  if (mRootNode && aDoFlush) {
+  if (mRootNode && aDoFlush && mFlushesNeeded) {
     // XXX sXBL/XBL2 issue
     nsIDocument* doc = mRootNode->GetCurrentDoc();
     if (doc) {
       // Flush pending content changes Bug 4891.
       doc->FlushPendingNotifications(Flush_ContentAndNotify);
     }
   }
 
--- a/content/base/src/nsContentList.h
+++ b/content/base/src/nsContentList.h
@@ -391,34 +391,44 @@ protected:
    * Cleanup closure data with this.
    */
   nsContentListDestroyFunc mDestroyFunc;
   /**
    * Closure data to pass to mFunc when we call it
    */
   void* mData;
   /**
-   * True if we are looking for elements named "*"
-   */
-  PRPackedBool mMatchAll;
-  /**
    * The current state of the list (possible values are:
    * LIST_UP_TO_DATE, LIST_LAZY, LIST_DIRTY
    */
   PRUint8 mState;
+
+  // The booleans have to use PRUint8 to pack with mState, because MSVC won't
+  // pack different typedefs together.  Once we no longer have to worry about
+  // flushes in XML documents, we can go back to using PRPackedBool for the
+  // booleans.
+  
+  /**
+   * True if we are looking for elements named "*"
+   */
+  PRUint8 mMatchAll : 1;
   /**
    * Whether to actually descend the tree.  If this is false, we won't
    * consider grandkids of mRootNode.
    */
-  PRPackedBool mDeep;
+  PRUint8 mDeep : 1;
   /**
    * Whether the return value of mFunc could depend on the values of
    * attributes.
    */
-  PRPackedBool mFuncMayDependOnAttr;
+  PRUint8 mFuncMayDependOnAttr : 1;
+  /**
+   * Whether we actually need to flush to get our state correct.
+   */
+  PRUint8 mFlushesNeeded : 1;
 
 #ifdef DEBUG_CONTENT_LIST
   void AssertInSync();
 #endif
 };
 
 /**
  * A class of cacheable content list; cached on the combination of aRootNode + aFunc + aDataString
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -6416,17 +6416,18 @@ nsDocument::CreateEventGroup(nsIDOMEvent
   NS_ADDREF(*aInstancePtrResult);
 
   return NS_OK;
 }
 
 void
 nsDocument::FlushPendingNotifications(mozFlushType aType)
 {
-  if (mParser || mWeakSink) {
+  if ((!IsHTML() || aType > Flush_ContentAndNotify) &&
+      (mParser || mWeakSink)) {
     nsCOMPtr<nsIContentSink> sink;
     if (mParser) {
       sink = mParser->GetContentSink();
     } else {
       sink = do_QueryReferent(mWeakSink);
       if (!sink) {
         mWeakSink = nsnull;
       }