From d8bbc7858622b6d9c278469aab701ca0b609cddf Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 15 May 2024 05:35:49 +0200 Subject: Merging upstream version 126.0. Signed-off-by: Daniel Baumann --- parser/html/javasrc/Tokenizer.java | 24 +++++++++++++++++++-- parser/html/javasrc/TreeBuilder.java | 23 ++++++++++++++++++-- parser/html/nsHtml5StreamParser.cpp | 24 +++++++-------------- parser/html/nsHtml5StringParser.cpp | 31 ++++++++++++++++++++++++++- parser/html/nsHtml5StringParser.h | 21 ++++++++++++++++++ parser/html/nsHtml5Tokenizer.cpp | 21 ++++++++++++++++-- parser/html/nsHtml5Tokenizer.h | 3 +++ parser/html/nsHtml5TreeBuilder.cpp | 20 +++++++++++++++-- parser/html/nsHtml5TreeBuilder.h | 3 +++ parser/html/nsHtml5TreeBuilderCppSupplement.h | 2 ++ 10 files changed, 147 insertions(+), 25 deletions(-) (limited to 'parser') diff --git a/parser/html/javasrc/Tokenizer.java b/parser/html/javasrc/Tokenizer.java index 0357cd0155..6d7c349155 100644 --- a/parser/html/javasrc/Tokenizer.java +++ b/parser/html/javasrc/Tokenizer.java @@ -511,6 +511,8 @@ public class Tokenizer implements Locator, Locator2 { private boolean shouldSuspend; + private boolean keepBuffer; + protected boolean confident; private int line; @@ -570,6 +572,7 @@ public class Tokenizer implements Locator, Locator2 { this.systemIdentifier = null; this.attributes = null; this.shouldSuspend = false; + this.keepBuffer = false; this.confident = false; this.line = 0; // CPPONLY: this.attributeLine = 0; @@ -632,6 +635,7 @@ public class Tokenizer implements Locator, Locator2 { // CPPONLY: this.attributes = tokenHandler.HasBuilder() ? new HtmlAttributes(mappingLangToXmlLang) : null; // CPPONLY: this.newAttributesEachTime = !tokenHandler.HasBuilder(); this.shouldSuspend = false; + this.keepBuffer = false; this.confident = false; this.line = 0; // CPPONLY: this.attributeLine = 0; @@ -653,6 +657,18 @@ public class Tokenizer implements Locator, Locator2 { // CPPONLY: return viewingXmlSource; // CPPONLY: } + public void setKeepBuffer(boolean keepBuffer) { + this.keepBuffer = keepBuffer; + } + + public boolean dropBufferIfLongerThan(int length) { + if (strBuf.length > length) { + strBuf = null; + return true; + } + return false; + } + // [NOCPP[ /** @@ -7225,7 +7241,9 @@ public class Tokenizer implements Locator, Locator2 { } public void end() throws SAXException { - strBuf = null; + if (!keepBuffer) { + strBuf = null; + } doctypeName = null; if (systemIdentifier != null) { Portability.releaseString(systemIdentifier); @@ -7415,7 +7433,9 @@ public class Tokenizer implements Locator, Locator2 { public void initializeWithoutStarting() throws SAXException { confident = false; - strBuf = null; + if (!keepBuffer) { + strBuf = null; + } line = 1; // CPPONLY: attributeLine = 1; // [NOCPP[ diff --git a/parser/html/javasrc/TreeBuilder.java b/parser/html/javasrc/TreeBuilder.java index f7b70ee0da..c190b7fd20 100644 --- a/parser/html/javasrc/TreeBuilder.java +++ b/parser/html/javasrc/TreeBuilder.java @@ -436,6 +436,8 @@ public abstract class TreeBuilder implements TokenHandler, private boolean allowDeclarativeShadowRoots = false; + private boolean keepBuffer = false; + // [NOCPP[ private boolean reportingDoctype = true; @@ -577,6 +579,18 @@ public abstract class TreeBuilder implements TokenHandler, // ]NOCPP] + public void setKeepBuffer(boolean keepBuffer) { + this.keepBuffer = keepBuffer; + } + + public boolean dropBufferIfLongerThan(int length) { + if (charBuffer.length > length) { + charBuffer = null; + return true; + } + return false; + } + @SuppressWarnings("unchecked") public final void startTokenization(Tokenizer self) throws SAXException { tokenizer = self; stackNodes = new StackNode[64]; @@ -598,7 +612,9 @@ public abstract class TreeBuilder implements TokenHandler, // ]NOCPP] start(fragment); charBufferLen = 0; - charBuffer = null; + if (!keepBuffer) { + charBuffer = null; + } framesetOk = true; if (fragment) { T elt; @@ -1451,7 +1467,10 @@ public abstract class TreeBuilder implements TokenHandler, // [NOCPP[ idLocations.clear(); // ]NOCPP] - charBuffer = null; + + if (!keepBuffer) { + charBuffer = null; + } end(); } diff --git a/parser/html/nsHtml5StreamParser.cpp b/parser/html/nsHtml5StreamParser.cpp index 82344cfa87..6286087d2a 100644 --- a/parser/html/nsHtml5StreamParser.cpp +++ b/parser/html/nsHtml5StreamParser.cpp @@ -1385,27 +1385,25 @@ nsresult nsHtml5StreamParser::OnStopRequest( const mozilla::ReentrantMonitorAutoEnter& aProofOfLock) { MOZ_ASSERT_IF(aRequest, mRequest == aRequest); if (mOnStopCalled) { + // OnStopRequest already executed (probably OMT). + MOZ_ASSERT(NS_IsMainThread(), "Expected to run on main thread"); if (mOnDataFinishedTime) { mOnStopRequestTime = TimeStamp::Now(); - } else { - mOnDataFinishedTime = TimeStamp::Now(); } } else { mOnStopCalled = true; if (MOZ_UNLIKELY(NS_IsMainThread())) { - mOnStopRequestTime = TimeStamp::Now(); + MOZ_ASSERT(mOnDataFinishedTime.IsNull(), "stale mOnDataFinishedTime"); nsCOMPtr stopper = new nsHtml5RequestStopper(this); if (NS_FAILED( mEventTarget->Dispatch(stopper, nsIThread::DISPATCH_NORMAL))) { NS_WARNING("Dispatching StopRequest event failed."); } } else { - mOnDataFinishedTime = TimeStamp::Now(); - if (StaticPrefs::network_send_OnDataFinished_html5parser()) { MOZ_ASSERT(IsParserThread(), "Wrong thread!"); - + mOnDataFinishedTime = TimeStamp::Now(); mozilla::MutexAutoLock autoLock(mTokenizerMutex); DoStopRequest(); PostLoadFlusher(); @@ -1421,16 +1419,10 @@ nsresult nsHtml5StreamParser::OnStopRequest( } if (!mOnStopRequestTime.IsNull() && !mOnDataFinishedTime.IsNull()) { TimeDuration delta = (mOnStopRequestTime - mOnDataFinishedTime); - if (delta.ToMilliseconds() < 0) { - // Because Telemetry can't handle negatives - delta = -delta; - glean::networking:: - http_content_html5parser_ondatafinished_to_onstop_delay_negative - .AccumulateRawDuration(delta); - } else { - glean::networking::http_content_html5parser_ondatafinished_to_onstop_delay - .AccumulateRawDuration(delta); - } + MOZ_ASSERT((delta.ToMilliseconds() >= 0), + "OnDataFinished after OnStopRequest"); + glean::networking::http_content_html5parser_ondatafinished_to_onstop_delay + .AccumulateRawDuration(delta); } return NS_OK; } diff --git a/parser/html/nsHtml5StringParser.cpp b/parser/html/nsHtml5StringParser.cpp index 5fe2b2e323..69e2806ce5 100644 --- a/parser/html/nsHtml5StringParser.cpp +++ b/parser/html/nsHtml5StringParser.cpp @@ -20,9 +20,11 @@ nsHtml5StringParser::nsHtml5StringParser() mTreeBuilder(new nsHtml5TreeBuilder(mBuilder)), mTokenizer(new nsHtml5Tokenizer(mTreeBuilder.get(), false)) { mTokenizer->setInterner(&mAtomTable); + mTokenizer->setKeepBuffer(true); + mTreeBuilder->setKeepBuffer(true); } -nsHtml5StringParser::~nsHtml5StringParser() {} +nsHtml5StringParser::~nsHtml5StringParser() { ClearCaches(); } nsresult nsHtml5StringParser::ParseFragment( const nsAString& aSourceBuffer, nsIContent* aTargetNode, @@ -69,6 +71,31 @@ nsresult nsHtml5StringParser::ParseDocument( aTargetDoc->AllowsDeclarativeShadowRoots()); } +void nsHtml5StringParser::ClearCaches() { + mTokenizer->dropBufferIfLongerThan(0); + mTreeBuilder->dropBufferIfLongerThan(0); + if (mCacheClearer) { + mCacheClearer->Disconnect(); + mCacheClearer = nullptr; + } +} + +void nsHtml5StringParser::TryCache() { + const int32_t kMaxBuffer = 1024 * 1024; + bool didDrop = mTokenizer->dropBufferIfLongerThan(kMaxBuffer); + didDrop |= mTreeBuilder->dropBufferIfLongerThan(kMaxBuffer); + if (didDrop) { + return; + } + + if (!mCacheClearer) { + mCacheClearer = new CacheClearer(this); + nsCOMPtr runnable = mCacheClearer.get(); + NS_DispatchToMainThreadQueue(runnable.forget(), + mozilla::EventQueuePriority::Idle); + } +} + nsresult nsHtml5StringParser::Tokenize(const nsAString& aSourceBuffer, Document* aDocument, bool aScriptingEnabledForNoscriptParsing, @@ -109,8 +136,10 @@ nsresult nsHtml5StringParser::Tokenize(const nsAString& aSourceBuffer, if (NS_SUCCEEDED(rv)) { mTokenizer->eof(); } + mTokenizer->end(); mBuilder->Finish(); mAtomTable.Clear(); + TryCache(); return rv; } diff --git a/parser/html/nsHtml5StringParser.h b/parser/html/nsHtml5StringParser.h index 1d41404841..8b0203301d 100644 --- a/parser/html/nsHtml5StringParser.h +++ b/parser/html/nsHtml5StringParser.h @@ -67,6 +67,9 @@ class nsHtml5StringParser : public nsParserBase { bool aScriptingEnabledForNoscriptParsing, bool aDeclarativeShadowRootsAllowed); + void TryCache(); + void ClearCaches(); + /** * The tree operation executor */ @@ -86,6 +89,24 @@ class nsHtml5StringParser : public nsParserBase { * The scoped atom table */ nsHtml5AtomTable mAtomTable; + + class CacheClearer : public mozilla::Runnable { + public: + explicit CacheClearer(nsHtml5StringParser* aParser) + : Runnable("CacheClearer"), mParser(aParser) {} + NS_IMETHOD Run() { + if (mParser) { + mParser->ClearCaches(); + } + return NS_OK; + } + void Disconnect() { mParser = nullptr; } + + private: + nsHtml5StringParser* mParser; + }; + + RefPtr mCacheClearer; }; #endif // nsHtml5StringParser_h diff --git a/parser/html/nsHtml5Tokenizer.cpp b/parser/html/nsHtml5Tokenizer.cpp index 5092bf4bf6..127c0a77fc 100644 --- a/parser/html/nsHtml5Tokenizer.cpp +++ b/parser/html/nsHtml5Tokenizer.cpp @@ -126,6 +126,7 @@ nsHtml5Tokenizer::nsHtml5Tokenizer(nsHtml5TreeBuilder* tokenHandler, : nullptr), newAttributesEachTime(!tokenHandler->HasBuilder()), shouldSuspend(false), + keepBuffer(false), confident(false), line(0), attributeLine(0), @@ -146,6 +147,18 @@ void nsHtml5Tokenizer::initLocation(nsHtml5String newPublicId, bool nsHtml5Tokenizer::isViewingXmlSource() { return viewingXmlSource; } +void nsHtml5Tokenizer::setKeepBuffer(bool keepBuffer) { + this->keepBuffer = keepBuffer; +} + +bool nsHtml5Tokenizer::dropBufferIfLongerThan(int32_t length) { + if (strBuf.length > length) { + strBuf = nullptr; + return true; + } + return false; +} + void nsHtml5Tokenizer::setState(int32_t specialTokenizerState) { this->stateSave = specialTokenizerState; this->endTagExpectation = nullptr; @@ -5022,7 +5035,9 @@ void nsHtml5Tokenizer::emitOrAppendOne(const char16_t* val, } void nsHtml5Tokenizer::end() { - strBuf = nullptr; + if (!keepBuffer) { + strBuf = nullptr; + } doctypeName = nullptr; if (systemIdentifier) { systemIdentifier.Release(); @@ -5148,7 +5163,9 @@ void nsHtml5Tokenizer::loadState(nsHtml5Tokenizer* other) { void nsHtml5Tokenizer::initializeWithoutStarting() { confident = false; - strBuf = nullptr; + if (!keepBuffer) { + strBuf = nullptr; + } line = 1; attributeLine = 1; resetToDataState(); diff --git a/parser/html/nsHtml5Tokenizer.h b/parser/html/nsHtml5Tokenizer.h index 91c70fc412..e19570ca3f 100644 --- a/parser/html/nsHtml5Tokenizer.h +++ b/parser/html/nsHtml5Tokenizer.h @@ -308,6 +308,7 @@ class nsHtml5Tokenizer { nsHtml5HtmlAttributes* attributes; bool newAttributesEachTime; bool shouldSuspend; + bool keepBuffer; protected: bool confident; @@ -323,6 +324,8 @@ class nsHtml5Tokenizer { void setInterner(nsHtml5AtomTable* interner); void initLocation(nsHtml5String newPublicId, nsHtml5String newSystemId); bool isViewingXmlSource(); + void setKeepBuffer(bool keepBuffer); + bool dropBufferIfLongerThan(int32_t length); void setState(int32_t specialTokenizerState); void setStateAndEndTagExpectation(int32_t specialTokenizerState, nsHtml5ElementName* endTagExpectation); diff --git a/parser/html/nsHtml5TreeBuilder.cpp b/parser/html/nsHtml5TreeBuilder.cpp index 26db77865f..9ef9a519f7 100644 --- a/parser/html/nsHtml5TreeBuilder.cpp +++ b/parser/html/nsHtml5TreeBuilder.cpp @@ -100,6 +100,18 @@ static const char* const QUIRKY_PUBLIC_IDS_DATA[] = { "-//webtechs//dtd mozilla html//"}; staticJArray nsHtml5TreeBuilder::QUIRKY_PUBLIC_IDS = { QUIRKY_PUBLIC_IDS_DATA, MOZ_ARRAY_LENGTH(QUIRKY_PUBLIC_IDS_DATA)}; +void nsHtml5TreeBuilder::setKeepBuffer(bool keepBuffer) { + this->keepBuffer = keepBuffer; +} + +bool nsHtml5TreeBuilder::dropBufferIfLongerThan(int32_t length) { + if (charBuffer.length > length) { + charBuffer = nullptr; + return true; + } + return false; +} + void nsHtml5TreeBuilder::startTokenization(nsHtml5Tokenizer* self) { tokenizer = self; stackNodes = jArray::newJArray(64); @@ -118,7 +130,9 @@ void nsHtml5TreeBuilder::startTokenization(nsHtml5Tokenizer* self) { headPointer = nullptr; start(fragment); charBufferLen = 0; - charBuffer = nullptr; + if (!keepBuffer) { + charBuffer = nullptr; + } framesetOk = true; if (fragment) { nsIContentHandle* elt; @@ -652,7 +666,9 @@ void nsHtml5TreeBuilder::endTokenization() { stackNodesIdx = 0; stackNodes = nullptr; } - charBuffer = nullptr; + if (!keepBuffer) { + charBuffer = nullptr; + } end(); } diff --git a/parser/html/nsHtml5TreeBuilder.h b/parser/html/nsHtml5TreeBuilder.h index d6c4828e7c..b48902df35 100644 --- a/parser/html/nsHtml5TreeBuilder.h +++ b/parser/html/nsHtml5TreeBuilder.h @@ -315,6 +315,7 @@ class nsHtml5TreeBuilder : public nsAHtml5TreeBuilderState { bool quirks; bool forceNoQuirks; bool allowDeclarativeShadowRoots; + bool keepBuffer; inline nsHtml5ContentCreatorFunction htmlCreator( mozilla::dom::HTMLContentCreatorFunction htmlCreator) { nsHtml5ContentCreatorFunction creator; @@ -330,6 +331,8 @@ class nsHtml5TreeBuilder : public nsAHtml5TreeBuilderState { } public: + void setKeepBuffer(bool keepBuffer); + bool dropBufferIfLongerThan(int32_t length); void startTokenization(nsHtml5Tokenizer* self); void doctype(nsAtom* name, nsHtml5String publicIdentifier, nsHtml5String systemIdentifier, bool forceQuirks); diff --git a/parser/html/nsHtml5TreeBuilderCppSupplement.h b/parser/html/nsHtml5TreeBuilderCppSupplement.h index 59df6937e2..23a0b587d9 100644 --- a/parser/html/nsHtml5TreeBuilderCppSupplement.h +++ b/parser/html/nsHtml5TreeBuilderCppSupplement.h @@ -42,6 +42,7 @@ nsHtml5TreeBuilder::nsHtml5TreeBuilder(nsHtml5OplessBuilder* aBuilder) quirks(false), forceNoQuirks(false), allowDeclarativeShadowRoots(false), + keepBuffer(false), mBuilder(aBuilder), mViewSource(nullptr), mOpSink(nullptr), @@ -85,6 +86,7 @@ nsHtml5TreeBuilder::nsHtml5TreeBuilder(nsAHtml5TreeOpSink* aOpSink, quirks(false), forceNoQuirks(false), allowDeclarativeShadowRoots(false), + keepBuffer(false), mBuilder(nullptr), mViewSource(nullptr), mOpSink(aOpSink), -- cgit v1.2.3