mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 12:51:06 +00:00
Bug 1807017 - Consider to reuse the memory when nsHtml5Tokenizer::end() is called, r=hsivonen
Differential Revision: https://phabricator.services.mozilla.com/D201982
This commit is contained in:
parent
a38bf0da3c
commit
6d652d37f5
@ -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[
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -42,6 +42,7 @@ nsHtml5TreeBuilder::nsHtml5TreeBuilder(nsHtml5OplessBuilder* aBuilder)
|
||||
quirks(false),
|
||||
forceNoQuirks(false),
|
||||
allowDeclarativeShadowRoots(false),
|
||||
keepBuffer(false),
|
||||
mBuilder(aBuilder),
|
||||
mViewSource(nullptr),
|
||||
mOpSink(nullptr),
|
||||
|
Loading…
Reference in New Issue
Block a user