Bug 1113238 - Part 2: Only maintain the pre level status which can be potentially expensive if we may end up using it; r=bzbarsky

This patch ensures that we check ShouldMaintainPreLevel() before attempting
to modify or read mPreLevel in order to avoid wasting time to compute
mPreLevel for elements without frames needlessly.  Computing this value for
such elements can incur expensive style calculations.
This commit is contained in:
Ehsan Akhgari 2015-01-12 11:41:10 -05:00
parent 4975900e1d
commit 1e702f0544
4 changed files with 60 additions and 36 deletions

View File

@ -192,7 +192,7 @@ nsHTMLContentSerializer::AppendElementStart(Element* aElement,
bool lineBreakBeforeOpen = LineBreakBeforeOpen(ns, name);
if ((mDoFormat || forceFormat) && !mPreLevel && !mDoRaw) {
if ((mDoFormat || forceFormat) && !mDoRaw && !PreLevel()) {
if (mColPos && lineBreakBeforeOpen) {
AppendNewLineToString(aStr);
}
@ -225,7 +225,7 @@ nsHTMLContentSerializer::AppendElementStart(Element* aElement,
MaybeEnterInPreContent(content);
// for block elements, we increase the indentation
if ((mDoFormat || forceFormat) && !mPreLevel && !mDoRaw)
if ((mDoFormat || forceFormat) && !mDoRaw && !PreLevel())
IncrIndentation(name);
// Need to keep track of OL and LI elements in order to get ordinal number
@ -280,8 +280,8 @@ nsHTMLContentSerializer::AppendElementStart(Element* aElement,
++mDisableEntityEncoding;
}
if ((mDoFormat || forceFormat) && !mPreLevel &&
!mDoRaw && LineBreakAfterOpen(ns, name)) {
if ((mDoFormat || forceFormat) && !mDoRaw && !PreLevel() &&
LineBreakAfterOpen(ns, name)) {
AppendNewLineToString(aStr);
}
@ -312,18 +312,18 @@ nsHTMLContentSerializer::AppendElementEnd(Element* aElement,
bool forceFormat = !(mFlags & nsIDocumentEncoder::OutputIgnoreMozDirty) &&
content->HasAttr(kNameSpaceID_None, nsGkAtoms::mozdirty);
if ((mDoFormat || forceFormat) && !mPreLevel && !mDoRaw) {
if ((mDoFormat || forceFormat) && !mDoRaw && !PreLevel()) {
DecrIndentation(name);
}
if (name == nsGkAtoms::script) {
nsCOMPtr<nsIScriptElement> script = do_QueryInterface(aElement);
if (script && script->IsMalformed()) {
if (ShouldMaintainPreLevel() && script && script->IsMalformed()) {
// We're looking at a malformed script tag. This means that the end tag
// was missing in the source. Imitate that here by not serializing the end
// tag.
--mPreLevel;
--PreLevel();
return NS_OK;
}
}
@ -351,7 +351,7 @@ nsHTMLContentSerializer::AppendElementEnd(Element* aElement,
}
}
if ((mDoFormat || forceFormat) && !mPreLevel && !mDoRaw) {
if ((mDoFormat || forceFormat) && !mDoRaw && !PreLevel()) {
bool lineBreakBeforeClose = LineBreakBeforeClose(ns, name);
@ -377,8 +377,8 @@ nsHTMLContentSerializer::AppendElementEnd(Element* aElement,
MaybeLeaveFromPreContent(content);
if ((mDoFormat || forceFormat) && !mPreLevel
&& !mDoRaw && LineBreakAfterClose(ns, name)) {
if ((mDoFormat || forceFormat)&& !mDoRaw && !PreLevel()
&& LineBreakAfterClose(ns, name)) {
AppendNewLineToString(aStr);
}
else {

View File

@ -133,7 +133,7 @@ nsXHTMLContentSerializer::AppendText(nsIContent* aText,
if (NS_FAILED(rv))
return NS_ERROR_FAILURE;
if (mPreLevel > 0 || mDoRaw) {
if (mDoRaw || PreLevel() > 0) {
AppendToStringConvertLF(data, aStr);
}
else if (mDoFormat) {
@ -537,8 +537,9 @@ nsXHTMLContentSerializer::CheckElementStart(nsIContent * aContent,
int32_t namespaceID = aContent->GetNameSpaceID();
if (namespaceID == kNameSpaceID_XHTML) {
if (name == nsGkAtoms::br && mPreLevel > 0 &&
(mFlags & nsIDocumentEncoder::OutputNoFormattingInPre)) {
if (name == nsGkAtoms::br &&
(mFlags & nsIDocumentEncoder::OutputNoFormattingInPre) &&
PreLevel() > 0) {
AppendNewLineToString(aStr);
return false;
}
@ -845,8 +846,8 @@ nsXHTMLContentSerializer::LineBreakAfterClose(int32_t aNamespaceID, nsIAtom* aNa
void
nsXHTMLContentSerializer::MaybeEnterInPreContent(nsIContent* aNode)
{
if (aNode->GetNameSpaceID() != kNameSpaceID_XHTML) {
if (!ShouldMaintainPreLevel() ||
aNode->GetNameSpaceID() != kNameSpaceID_XHTML) {
return;
}
@ -858,14 +859,15 @@ nsXHTMLContentSerializer::MaybeEnterInPreContent(nsIContent* aNode)
name == nsGkAtoms::noscript ||
name == nsGkAtoms::noframes
) {
mPreLevel++;
PreLevel()++;
}
}
void
nsXHTMLContentSerializer::MaybeLeaveFromPreContent(nsIContent* aNode)
{
if (aNode->GetNameSpaceID() != kNameSpaceID_XHTML) {
if (!ShouldMaintainPreLevel() ||
aNode->GetNameSpaceID() != kNameSpaceID_XHTML) {
return;
}
@ -876,13 +878,15 @@ nsXHTMLContentSerializer::MaybeLeaveFromPreContent(nsIContent* aNode)
name == nsGkAtoms::noscript ||
name == nsGkAtoms::noframes
) {
--mPreLevel;
--PreLevel();
}
}
bool
nsXHTMLContentSerializer::IsElementPreformatted(nsIContent* aNode)
{
MOZ_ASSERT(ShouldMaintainPreLevel(), "We should not be calling this needlessly");
if (!aNode->IsElement()) {
return false;
}

View File

@ -187,7 +187,7 @@ nsXMLContentSerializer::AppendText(nsIContent* aText,
if (NS_FAILED(rv))
return NS_ERROR_FAILURE;
if (mPreLevel > 0 || mDoRaw) {
if (mDoRaw || PreLevel() > 0) {
AppendToStringConvertLF(data, aStr);
}
else if (mDoFormat) {
@ -214,7 +214,7 @@ nsXMLContentSerializer::AppendCDATASection(nsIContent* aCDATASection,
NS_NAMED_LITERAL_STRING(cdata , "<![CDATA[");
if (mPreLevel > 0 || mDoRaw) {
if (mDoRaw || PreLevel() > 0) {
AppendToString(cdata, aStr);
}
else if (mDoFormat) {
@ -260,7 +260,7 @@ nsXMLContentSerializer::AppendProcessingInstruction(nsIContent* aPI,
start.AppendLiteral("<?");
start.Append(target);
if (mPreLevel > 0 || mDoRaw) {
if (mDoRaw || PreLevel() > 0) {
AppendToString(start, aStr);
}
else if (mDoFormat) {
@ -318,7 +318,7 @@ nsXMLContentSerializer::AppendComment(nsIContent* aComment,
NS_NAMED_LITERAL_STRING(startComment, "<!--");
if (mPreLevel > 0 || mDoRaw) {
if (mDoRaw || PreLevel() > 0) {
AppendToString(startComment, aStr);
}
else if (mDoFormat) {
@ -693,7 +693,7 @@ nsXMLContentSerializer::SerializeAttr(const nsAString& aPrefix,
attrString.Append(sValue);
attrString.Append(cDelimiter);
}
if (mPreLevel > 0 || mDoRaw) {
if (mDoRaw || PreLevel() > 0) {
AppendToStringConvertLF(attrString, aStr);
}
else if (mDoFormat) {
@ -898,7 +898,7 @@ nsXMLContentSerializer::AppendElementStart(Element* aElement,
nsIAtom *name = content->Tag();
bool lineBreakBeforeOpen = LineBreakBeforeOpen(content->GetNameSpaceID(), name);
if ((mDoFormat || forceFormat) && !mPreLevel && !mDoRaw) {
if ((mDoFormat || forceFormat) && !mDoRaw && !PreLevel()) {
if (mColPos && lineBreakBeforeOpen) {
AppendNewLineToString(aStr);
}
@ -939,7 +939,7 @@ nsXMLContentSerializer::AppendElementStart(Element* aElement,
MaybeEnterInPreContent(content);
if ((mDoFormat || forceFormat) && !mPreLevel && !mDoRaw) {
if ((mDoFormat || forceFormat) && !mDoRaw && !PreLevel()) {
IncrIndentation(name);
}
@ -949,8 +949,8 @@ nsXMLContentSerializer::AppendElementStart(Element* aElement,
AppendEndOfElementStart(aOriginalElement, name, content->GetNameSpaceID(),
aStr);
if ((mDoFormat || forceFormat) && !mPreLevel
&& !mDoRaw && LineBreakAfterOpen(content->GetNameSpaceID(), name)) {
if ((mDoFormat || forceFormat) && !mDoRaw && !PreLevel()
&& LineBreakAfterOpen(content->GetNameSpaceID(), name)) {
AppendNewLineToString(aStr);
}
@ -987,7 +987,7 @@ nsXMLContentSerializer::AppendElementEnd(Element* aElement,
nsIAtom *name = content->Tag();
if ((mDoFormat || forceFormat) && !mPreLevel && !mDoRaw) {
if ((mDoFormat || forceFormat) && !mDoRaw && !PreLevel()) {
DecrIndentation(name);
}
@ -1009,7 +1009,7 @@ nsXMLContentSerializer::AppendElementEnd(Element* aElement,
ConfirmPrefix(tagPrefix, tagNamespaceURI, aElement, false);
NS_ASSERTION(!debugNeedToPushNamespace, "Can't push namespaces in closing tag!");
if ((mDoFormat || forceFormat) && !mPreLevel && !mDoRaw) {
if ((mDoFormat || forceFormat) && !mDoRaw && !PreLevel()) {
bool lineBreakBeforeClose = LineBreakBeforeClose(content->GetNameSpaceID(), name);
@ -1041,8 +1041,8 @@ nsXMLContentSerializer::AppendElementEnd(Element* aElement,
MaybeLeaveFromPreContent(content);
if ((mDoFormat || forceFormat) && !mPreLevel
&& !mDoRaw && LineBreakAfterClose(content->GetNameSpaceID(), name)) {
if ((mDoFormat || forceFormat) && !mDoRaw && !PreLevel()
&& LineBreakAfterClose(content->GetNameSpaceID(), name)) {
AppendNewLineToString(aStr);
}
else {
@ -1217,11 +1217,12 @@ void
nsXMLContentSerializer::MaybeEnterInPreContent(nsIContent* aNode)
{
// support of the xml:space attribute
if (aNode->HasAttr(kNameSpaceID_XML, nsGkAtoms::space)) {
if (ShouldMaintainPreLevel() &&
aNode->HasAttr(kNameSpaceID_XML, nsGkAtoms::space)) {
nsAutoString space;
aNode->GetAttr(kNameSpaceID_XML, nsGkAtoms::space, space);
if (space.EqualsLiteral("preserve"))
++mPreLevel;
++PreLevel();
}
}
@ -1229,11 +1230,12 @@ void
nsXMLContentSerializer::MaybeLeaveFromPreContent(nsIContent* aNode)
{
// support of the xml:space attribute
if (aNode->HasAttr(kNameSpaceID_XML, nsGkAtoms::space)) {
if (ShouldMaintainPreLevel() &&
aNode->HasAttr(kNameSpaceID_XML, nsGkAtoms::space)) {
nsAutoString space;
aNode->GetAttr(kNameSpaceID_XML, nsGkAtoms::space, space);
if (space.EqualsLiteral("preserve"))
--mPreLevel;
--PreLevel();
}
}
@ -1442,7 +1444,7 @@ nsXMLContentSerializer::AppendWrapped_NonWhitespaceSequence(
colPos = mColPos;
}
else {
if (mDoFormat && !mPreLevel && !onceAgainBecauseWeAddedBreakInFront) {
if (mDoFormat && !mDoRaw && !PreLevel() && !onceAgainBecauseWeAddedBreakInFront) {
colPos = mIndent.Length();
}
else
@ -1711,3 +1713,10 @@ nsXMLContentSerializer::AppendToStringWrapped(const nsASingleFragmentString& aSt
}
}
}
bool
nsXMLContentSerializer::ShouldMaintainPreLevel() const
{
// Only attempt to maintain the pre level for consumers who care about it.
return !mDoRaw || (mFlags & nsIDocumentEncoder::OutputNoFormattingInPre);
}

View File

@ -294,6 +294,16 @@ class nsXMLContentSerializer : public nsIContentSerializer {
virtual void MaybeEnterInPreContent(nsIContent* aNode);
virtual void MaybeLeaveFromPreContent(nsIContent* aNode);
bool ShouldMaintainPreLevel() const;
int32_t PreLevel() const {
MOZ_ASSERT(ShouldMaintainPreLevel());
return mPreLevel;
}
int32_t& PreLevel() {
MOZ_ASSERT(ShouldMaintainPreLevel());
return mPreLevel;
}
int32_t mPrefixIndex;
struct NameSpaceDecl {
@ -361,6 +371,7 @@ class nsXMLContentSerializer : public nsIContentSerializer {
bool mBodyOnly;
int32_t mInBody;
private:
// number of nested elements which have preformated content
int32_t mPreLevel;
};