Bug 1998923 - Make better inline and never-inline decisions around EnsureBufferSpace in the tokenizer. r=farre

Differential Revision: https://phabricator.services.mozilla.com/D271752
This commit is contained in:
Henri Sivonen
2025-11-07 14:19:42 +00:00
committed by hsivonen@mozilla.com
parent 3772b212b9
commit 44a2cdba0c
8 changed files with 39 additions and 45 deletions
+2
View File
@@ -31,6 +31,7 @@ import nu.validator.htmlparser.common.Interner;
public final class Portability {
// [NOCPP[
public static int checkedAdd(int a, int b) throws SAXException {
// This can't be translated code, because in C++ signed integer overflow is UB, so the below code would be wrong.
assert a >= 0;
@@ -41,6 +42,7 @@ public final class Portability {
}
return sum;
}
// ]NOCPP]
// Allocating methods
+7 -11
View File
@@ -982,12 +982,9 @@ public class Tokenizer implements Locator, Locator2 {
* @param c
* the UTF-16 code unit to append
*/
private void appendStrBuf(char c) {
// CPPONLY: assert strBufLen < strBuf.length: "Previous buffer length insufficient.";
@Inline private void appendStrBuf(char c) {
// CPPONLY: if (strBufLen == strBuf.length) {
// CPPONLY: if (!EnsureBufferSpace(1)) {
// CPPONLY: assert false: "RELEASE: Unable to recover from buffer reallocation failure";
// CPPONLY: } // TODO: Add telemetry when outer if fires but inner does not
// CPPONLY: EnsureBufferSpaceShouldNeverHappen(1);
// CPPONLY: }
strBuf[strBufLen++] = c;
}
@@ -1094,13 +1091,12 @@ public class Tokenizer implements Locator, Locator2 {
// ]NOCPP]
}
private void appendStrBuf(@NoLength char[] buffer, int offset, int length) throws SAXException {
int newLen = Portability.checkedAdd(strBufLen, length);
// CPPONLY: assert newLen <= strBuf.length: "Previous buffer length insufficient.";
@Inline private void appendStrBuf(@NoLength char[] buffer, int offset, int length) throws SAXException {
// Years of crash stats have shown that the this addition doesn't overflow, as it logically
// shouldn't.
int newLen = strBufLen + length;
// CPPONLY: if (strBuf.length < newLen) {
// CPPONLY: if (!EnsureBufferSpace(length)) {
// CPPONLY: assert false: "RELEASE: Unable to recover from buffer reallocation failure";
// CPPONLY: } // TODO: Add telemetry when outer if fires but inner does not
// CPPONLY: EnsureBufferSpaceShouldNeverHappen(length);
// CPPONLY: }
System.arraycopy(buffer, offset, strBuf, strBufLen, length);
strBufLen = newLen;
-8
View File
@@ -9,14 +9,6 @@
#include "nsString.h"
#include "mozilla/CheckedInt.h"
int32_t nsHtml5Portability::checkedAdd(int32_t a, int32_t b) {
mozilla::CheckedInt<int32_t> sum(a);
sum += b;
MOZ_RELEASE_ASSERT(sum.isValid(),
"HTML input too large for signed 32-bit integer.");
return sum.value();
}
nsAtom* nsHtml5Portability::newLocalNameFromBuffer(char16_t* buf,
int32_t length,
nsHtml5AtomTable* interner) {
-1
View File
@@ -54,7 +54,6 @@ class nsHtml5StateSnapshot;
class nsHtml5Portability {
public:
static int32_t checkedAdd(int32_t a, int32_t b);
static nsAtom* newLocalNameFromBuffer(char16_t* buf, int32_t length,
nsHtml5AtomTable* interner);
static nsHtml5String newStringFromBuffer(char16_t* buf, int32_t offset,
-23
View File
@@ -241,29 +241,6 @@ void nsHtml5Tokenizer::emitOrAppendCharRefBuf(int32_t returnState) {
}
}
void nsHtml5Tokenizer::appendStrBuf(char16_t c) {
MOZ_ASSERT(strBufLen < strBuf.length, "Previous buffer length insufficient.");
if (MOZ_UNLIKELY(strBufLen == strBuf.length)) {
if (MOZ_UNLIKELY(!EnsureBufferSpace(1))) {
MOZ_CRASH("Unable to recover from buffer reallocation failure");
}
}
strBuf[strBufLen++] = c;
}
void nsHtml5Tokenizer::appendStrBuf(char16_t* buffer, int32_t offset,
int32_t length) {
int32_t newLen = nsHtml5Portability::checkedAdd(strBufLen, length);
MOZ_ASSERT(newLen <= strBuf.length, "Previous buffer length insufficient.");
if (MOZ_UNLIKELY(strBuf.length < newLen)) {
if (MOZ_UNLIKELY(!EnsureBufferSpace(length))) {
MOZ_CRASH("Unable to recover from buffer reallocation failure");
}
}
nsHtml5ArrayCopy::arraycopy(buffer, offset, strBuf, strBufLen, length);
strBufLen = newLen;
}
void nsHtml5Tokenizer::emitComment(int32_t provisionalHyphens, int32_t pos) {
RememberGt(pos);
tokenHandler->comment(strBuf, 0, strBufLen - provisionalHyphens);
+15 -2
View File
@@ -359,7 +359,12 @@ class nsHtml5Tokenizer {
strBufLen = 0;
}
void appendStrBuf(char16_t c);
inline void appendStrBuf(char16_t c) {
if (MOZ_UNLIKELY(strBufLen == strBuf.length)) {
EnsureBufferSpaceShouldNeverHappen(1);
}
strBuf[strBufLen++] = c;
}
protected:
inline nsHtml5String strBufToString() {
@@ -392,7 +397,15 @@ class nsHtml5Tokenizer {
appendStrBuf(c);
}
void appendStrBuf(char16_t* buffer, int32_t offset, int32_t length);
inline void appendStrBuf(char16_t* buffer, int32_t offset, int32_t length) {
int32_t newLen = strBufLen + length;
if (MOZ_UNLIKELY(strBuf.length < newLen)) {
EnsureBufferSpaceShouldNeverHappen(length);
}
nsHtml5ArrayCopy::arraycopy(buffer, offset, strBuf, strBufLen, length);
strBufLen = newLen;
}
inline void appendCharRefBufToStrBuf() {
appendStrBuf(charRefBuf, 0, charRefBufLen);
charRefBufLen = 0;
@@ -61,6 +61,18 @@ bool nsHtml5Tokenizer::EnsureBufferSpace(int32_t aLength) {
return true;
}
MOZ_COLD MOZ_NEVER_INLINE void
nsHtml5Tokenizer::EnsureBufferSpaceShouldNeverHappen(int32_t aLength) {
MOZ_DIAGNOSTIC_ASSERT(false,
"This is never supposed to happen. Please file a bug "
"with steps to reproduce!");
if (!EnsureBufferSpace(aLength)) {
MOZ_CRASH(
"Unrecovable allocation failure in situation that should never happen. "
"Please file a bug with steps to reproduce!");
}
}
bool nsHtml5Tokenizer::TemplatePushedOrHeadPopped() {
if (encodingDeclarationHandler) {
return encodingDeclarationHandler->TemplatePushedOrHeadPopped();
@@ -67,6 +67,9 @@ inline nsHtml5HtmlAttributes* GetAttributes() { return attributes; }
*/
bool EnsureBufferSpace(int32_t aLength);
MOZ_COLD MOZ_NEVER_INLINE void EnsureBufferSpaceShouldNeverHappen(
int32_t aLength);
bool TemplatePushedOrHeadPopped();
void RememberGt(int32_t aPos);