summaryrefslogtreecommitdiffstats
path: root/parser
diff options
context:
space:
mode:
Diffstat (limited to 'parser')
-rw-r--r--parser/html/javasrc/Tokenizer.java24
-rw-r--r--parser/html/javasrc/TreeBuilder.java23
-rw-r--r--parser/html/nsHtml5StreamParser.cpp24
-rw-r--r--parser/html/nsHtml5StringParser.cpp31
-rw-r--r--parser/html/nsHtml5StringParser.h21
-rw-r--r--parser/html/nsHtml5Tokenizer.cpp21
-rw-r--r--parser/html/nsHtml5Tokenizer.h3
-rw-r--r--parser/html/nsHtml5TreeBuilder.cpp20
-rw-r--r--parser/html/nsHtml5TreeBuilder.h3
-rw-r--r--parser/html/nsHtml5TreeBuilderCppSupplement.h2
10 files changed, 147 insertions, 25 deletions
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<T> implements TokenHandler,
private boolean allowDeclarativeShadowRoots = false;
+ private boolean keepBuffer = false;
+
// [NOCPP[
private boolean reportingDoctype = true;
@@ -577,6 +579,18 @@ public abstract class TreeBuilder<T> 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<T> 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<T> 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<nsIRunnable> 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<nsIRunnable> 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<CacheClearer> 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<const char*, int32_t> 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<nsHtml5StackNode*, int32_t>::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),