Bug 1888535 Part 6 - Unhook display reflow debugging from nsLayoutStatics, and remove display reflow debugging. r=layout-reviewers,emilio

This final patch completely removes display reflow debugging mechanism.

Differential Revision: https://phabricator.services.mozilla.com/D206318
This commit is contained in:
Ting-Yu Lin 2024-04-02 19:03:06 +00:00
parent b518ef30fa
commit abf84fd282
3 changed files with 0 additions and 581 deletions

View file

@ -183,9 +183,6 @@ nsresult nsLayoutStatics::Initialize() {
nsMathMLOperators::AddRefTable();
#ifdef DEBUG
nsIFrame::DisplayReflowStartup();
#endif
Attr::Initialize();
PopupBlocker::Initialize();
@ -320,9 +317,6 @@ void nsLayoutStatics::Shutdown() {
HTMLDNSPrefetch::Shutdown();
nsCSSRendering::Shutdown();
StaticPresData::Shutdown();
#ifdef DEBUG
nsIFrame::DisplayReflowShutdown();
#endif
nsCellMap::Shutdown();
ActiveLayerTracker::Shutdown();

View file

@ -11673,577 +11673,6 @@ void nsIFrame::VerifyDirtyBitSet(const nsFrameList& aFrameList) {
}
}
// Start Display Reflow
struct DR_Rule;
struct DR_FrameTypeInfo {
DR_FrameTypeInfo(LayoutFrameType aFrameType, const char* aFrameNameAbbrev,
const char* aFrameName);
~DR_FrameTypeInfo();
LayoutFrameType mType;
char mNameAbbrev[16];
char mName[32];
nsTArray<DR_Rule*> mRules;
private:
DR_FrameTypeInfo& operator=(const DR_FrameTypeInfo&) = delete;
};
struct DR_FrameTreeNode;
struct DR_Rule;
struct DR_State {
DR_State();
~DR_State();
void Init();
void AddFrameTypeInfo(LayoutFrameType aFrameType,
const char* aFrameNameAbbrev, const char* aFrameName);
DR_FrameTypeInfo* GetFrameTypeInfo(LayoutFrameType aFrameType);
DR_FrameTypeInfo* GetFrameTypeInfo(char* aFrameName);
void InitFrameTypeTable();
DR_FrameTreeNode* CreateTreeNode(nsIFrame* aFrame,
const ReflowInput* aReflowInput);
void FindMatchingRule(DR_FrameTreeNode& aNode);
bool RuleMatches(DR_Rule& aRule, DR_FrameTreeNode& aNode);
bool GetToken(FILE* aFile, char* aBuf, size_t aBufSize);
DR_Rule* ParseRule(FILE* aFile);
void ParseRulesFile();
void AddRule(nsTArray<DR_Rule*>& aRules, DR_Rule& aRule);
bool IsWhiteSpace(int c);
bool GetNumber(char* aBuf, int32_t& aNumber);
void PrettyUC(nscoord aSize, char* aBuf, int aBufSize);
void PrintMargin(const char* tag, const nsMargin* aMargin);
void DisplayFrameTypeInfo(nsIFrame* aFrame, int32_t aIndent);
void DeleteTreeNode(DR_FrameTreeNode& aNode);
bool mInited;
bool mActive;
int32_t mCount;
int32_t mAssert;
int32_t mIndent;
bool mIndentUndisplayedFrames;
bool mDisplayPixelErrors;
nsTArray<DR_Rule*> mWildRules;
nsTArray<DR_FrameTypeInfo> mFrameTypeTable;
// reflow specific state
nsTArray<DR_FrameTreeNode*> mFrameTreeLeaves;
};
static DR_State* DR_state; // the one and only DR_State
struct DR_RulePart {
explicit DR_RulePart(LayoutFrameType aFrameType)
: mFrameType(aFrameType), mNext(0) {}
void Destroy();
LayoutFrameType mFrameType;
DR_RulePart* mNext;
};
void DR_RulePart::Destroy() {
if (mNext) {
mNext->Destroy();
}
delete this;
}
struct DR_Rule {
DR_Rule() : mLength(0), mTarget(nullptr), mDisplay(false) {
MOZ_COUNT_CTOR(DR_Rule);
}
~DR_Rule() {
if (mTarget) mTarget->Destroy();
MOZ_COUNT_DTOR(DR_Rule);
}
void AddPart(LayoutFrameType aFrameType);
uint32_t mLength;
DR_RulePart* mTarget;
bool mDisplay;
};
void DR_Rule::AddPart(LayoutFrameType aFrameType) {
DR_RulePart* newPart = new DR_RulePart(aFrameType);
newPart->mNext = mTarget;
mTarget = newPart;
mLength++;
}
DR_FrameTypeInfo::~DR_FrameTypeInfo() {
int32_t numElements;
numElements = mRules.Length();
for (int32_t i = numElements - 1; i >= 0; i--) {
delete mRules.ElementAt(i);
}
}
DR_FrameTypeInfo::DR_FrameTypeInfo(LayoutFrameType aFrameType,
const char* aFrameNameAbbrev,
const char* aFrameName) {
mType = aFrameType;
PL_strncpyz(mNameAbbrev, aFrameNameAbbrev, sizeof(mNameAbbrev));
PL_strncpyz(mName, aFrameName, sizeof(mName));
}
struct DR_FrameTreeNode {
DR_FrameTreeNode(nsIFrame* aFrame, DR_FrameTreeNode* aParent)
: mFrame(aFrame), mParent(aParent), mDisplay(0), mIndent(0) {
MOZ_COUNT_CTOR(DR_FrameTreeNode);
}
MOZ_COUNTED_DTOR(DR_FrameTreeNode)
nsIFrame* mFrame;
DR_FrameTreeNode* mParent;
bool mDisplay;
uint32_t mIndent;
};
// DR_State implementation
DR_State::DR_State()
: mInited(false),
mActive(false),
mCount(0),
mAssert(-1),
mIndent(0),
mIndentUndisplayedFrames(false),
mDisplayPixelErrors(false) {
MOZ_COUNT_CTOR(DR_State);
}
void DR_State::Init() {
char* env = PR_GetEnv("GECKO_DISPLAY_REFLOW_ASSERT");
int32_t num;
if (env) {
if (GetNumber(env, num))
mAssert = num;
else
printf("GECKO_DISPLAY_REFLOW_ASSERT - invalid value = %s", env);
}
env = PR_GetEnv("GECKO_DISPLAY_REFLOW_INDENT_START");
if (env) {
if (GetNumber(env, num))
mIndent = num;
else
printf("GECKO_DISPLAY_REFLOW_INDENT_START - invalid value = %s", env);
}
env = PR_GetEnv("GECKO_DISPLAY_REFLOW_INDENT_UNDISPLAYED_FRAMES");
if (env) {
if (GetNumber(env, num))
mIndentUndisplayedFrames = num;
else
printf(
"GECKO_DISPLAY_REFLOW_INDENT_UNDISPLAYED_FRAMES - invalid value = %s",
env);
}
env = PR_GetEnv("GECKO_DISPLAY_REFLOW_FLAG_PIXEL_ERRORS");
if (env) {
if (GetNumber(env, num))
mDisplayPixelErrors = num;
else
printf("GECKO_DISPLAY_REFLOW_FLAG_PIXEL_ERRORS - invalid value = %s",
env);
}
InitFrameTypeTable();
ParseRulesFile();
mInited = true;
}
DR_State::~DR_State() {
MOZ_COUNT_DTOR(DR_State);
int32_t numElements, i;
numElements = mWildRules.Length();
for (i = numElements - 1; i >= 0; i--) {
delete mWildRules.ElementAt(i);
}
numElements = mFrameTreeLeaves.Length();
for (i = numElements - 1; i >= 0; i--) {
delete mFrameTreeLeaves.ElementAt(i);
}
}
bool DR_State::GetNumber(char* aBuf, int32_t& aNumber) {
if (sscanf(aBuf, "%d", &aNumber) > 0)
return true;
else
return false;
}
bool DR_State::IsWhiteSpace(int c) {
return (c == ' ') || (c == '\t') || (c == '\n') || (c == '\r');
}
bool DR_State::GetToken(FILE* aFile, char* aBuf, size_t aBufSize) {
bool haveToken = false;
aBuf[0] = 0;
// get the 1st non whitespace char
int c = -1;
for (c = getc(aFile); (c > 0) && IsWhiteSpace(c); c = getc(aFile)) {
}
if (c > 0) {
haveToken = true;
aBuf[0] = c;
// get everything up to the next whitespace char
size_t cX;
for (cX = 1; cX + 1 < aBufSize; cX++) {
c = getc(aFile);
if (c < 0) { // EOF
ungetc(' ', aFile);
break;
} else {
if (IsWhiteSpace(c)) {
break;
} else {
aBuf[cX] = c;
}
}
}
aBuf[cX] = 0;
}
return haveToken;
}
DR_Rule* DR_State::ParseRule(FILE* aFile) {
char buf[128];
int32_t doDisplay;
DR_Rule* rule = nullptr;
while (GetToken(aFile, buf, sizeof(buf))) {
if (GetNumber(buf, doDisplay)) {
if (rule) {
rule->mDisplay = !!doDisplay;
break;
} else {
printf("unexpected token - %s \n", buf);
}
} else {
if (!rule) {
rule = new DR_Rule;
}
if (strcmp(buf, "*") == 0) {
rule->AddPart(LayoutFrameType::None);
} else {
DR_FrameTypeInfo* info = GetFrameTypeInfo(buf);
if (info) {
rule->AddPart(info->mType);
} else {
printf("invalid frame type - %s \n", buf);
}
}
}
}
return rule;
}
void DR_State::AddRule(nsTArray<DR_Rule*>& aRules, DR_Rule& aRule) {
int32_t numRules = aRules.Length();
for (int32_t ruleX = 0; ruleX < numRules; ruleX++) {
DR_Rule* rule = aRules.ElementAt(ruleX);
NS_ASSERTION(rule, "program error");
if (aRule.mLength > rule->mLength) {
aRules.InsertElementAt(ruleX, &aRule);
return;
}
}
aRules.AppendElement(&aRule);
}
static Maybe<bool> ShouldLogReflow(const char* processes) {
switch (processes[0]) {
case 'A':
case 'a':
return Some(true);
case 'P':
case 'p':
return Some(XRE_IsParentProcess());
case 'C':
case 'c':
return Some(XRE_IsContentProcess());
default:
return Nothing{};
}
}
void DR_State::ParseRulesFile() {
char* processes = PR_GetEnv("GECKO_DISPLAY_REFLOW_PROCESSES");
if (processes) {
Maybe<bool> enableLog = ShouldLogReflow(processes);
if (enableLog.isNothing()) {
MOZ_CRASH("GECKO_DISPLAY_REFLOW_PROCESSES: [a]ll [p]arent [c]ontent");
} else if (enableLog.value()) {
DR_Rule* rule = new DR_Rule;
rule->AddPart(LayoutFrameType::None);
rule->mDisplay = true;
AddRule(mWildRules, *rule);
mActive = true;
}
return;
}
char* path = PR_GetEnv("GECKO_DISPLAY_REFLOW_RULES_FILE");
if (path) {
FILE* inFile = fopen(path, "r");
if (!inFile) {
MOZ_CRASH(
"Failed to open the specified rules file; Try `--setpref "
"security.sandbox.content.level=2` if the sandbox is at cause");
}
for (DR_Rule* rule = ParseRule(inFile); rule; rule = ParseRule(inFile)) {
if (rule->mTarget) {
LayoutFrameType fType = rule->mTarget->mFrameType;
if (fType != LayoutFrameType::None) {
DR_FrameTypeInfo* info = GetFrameTypeInfo(fType);
AddRule(info->mRules, *rule);
} else {
AddRule(mWildRules, *rule);
}
mActive = true;
}
}
fclose(inFile);
}
}
void DR_State::AddFrameTypeInfo(LayoutFrameType aFrameType,
const char* aFrameNameAbbrev,
const char* aFrameName) {
mFrameTypeTable.EmplaceBack(aFrameType, aFrameNameAbbrev, aFrameName);
}
DR_FrameTypeInfo* DR_State::GetFrameTypeInfo(LayoutFrameType aFrameType) {
int32_t numEntries = mFrameTypeTable.Length();
NS_ASSERTION(numEntries != 0, "empty FrameTypeTable");
for (int32_t i = 0; i < numEntries; i++) {
DR_FrameTypeInfo& info = mFrameTypeTable.ElementAt(i);
if (info.mType == aFrameType) {
return &info;
}
}
return &mFrameTypeTable.ElementAt(numEntries -
1); // return unknown frame type
}
DR_FrameTypeInfo* DR_State::GetFrameTypeInfo(char* aFrameName) {
int32_t numEntries = mFrameTypeTable.Length();
NS_ASSERTION(numEntries != 0, "empty FrameTypeTable");
for (int32_t i = 0; i < numEntries; i++) {
DR_FrameTypeInfo& info = mFrameTypeTable.ElementAt(i);
if ((strcmp(aFrameName, info.mName) == 0) ||
(strcmp(aFrameName, info.mNameAbbrev) == 0)) {
return &info;
}
}
return &mFrameTypeTable.ElementAt(numEntries -
1); // return unknown frame type
}
void DR_State::InitFrameTypeTable() {
AddFrameTypeInfo(LayoutFrameType::Block, "block", "block");
AddFrameTypeInfo(LayoutFrameType::Br, "br", "br");
AddFrameTypeInfo(LayoutFrameType::ColorControl, "color", "colorControl");
AddFrameTypeInfo(LayoutFrameType::GfxButtonControl, "button",
"gfxButtonControl");
AddFrameTypeInfo(LayoutFrameType::HTMLButtonControl, "HTMLbutton",
"HTMLButtonControl");
AddFrameTypeInfo(LayoutFrameType::HTMLCanvas, "HTMLCanvas", "HTMLCanvas");
AddFrameTypeInfo(LayoutFrameType::SubDocument, "subdoc", "subDocument");
AddFrameTypeInfo(LayoutFrameType::Image, "img", "image");
AddFrameTypeInfo(LayoutFrameType::Inline, "inline", "inline");
AddFrameTypeInfo(LayoutFrameType::Letter, "letter", "letter");
AddFrameTypeInfo(LayoutFrameType::Line, "line", "line");
AddFrameTypeInfo(LayoutFrameType::ListControl, "select", "select");
AddFrameTypeInfo(LayoutFrameType::Page, "page", "page");
AddFrameTypeInfo(LayoutFrameType::Placeholder, "place", "placeholder");
AddFrameTypeInfo(LayoutFrameType::Canvas, "canvas", "canvas");
AddFrameTypeInfo(LayoutFrameType::Scroll, "scroll", "scroll");
AddFrameTypeInfo(LayoutFrameType::TableCell, "cell", "tableCell");
AddFrameTypeInfo(LayoutFrameType::TableCol, "col", "tableCol");
AddFrameTypeInfo(LayoutFrameType::TableColGroup, "colG", "tableColGroup");
AddFrameTypeInfo(LayoutFrameType::Table, "tbl", "table");
AddFrameTypeInfo(LayoutFrameType::TableWrapper, "tblW", "tableWrapper");
AddFrameTypeInfo(LayoutFrameType::TableRowGroup, "rowG", "tableRowGroup");
AddFrameTypeInfo(LayoutFrameType::TableRow, "row", "tableRow");
AddFrameTypeInfo(LayoutFrameType::TextInput, "textCtl", "textInput");
AddFrameTypeInfo(LayoutFrameType::Text, "text", "text");
AddFrameTypeInfo(LayoutFrameType::Viewport, "VP", "viewport");
AddFrameTypeInfo(LayoutFrameType::Slider, "Slider", "Slider");
AddFrameTypeInfo(LayoutFrameType::None, "unknown", "unknown");
}
void DR_State::DisplayFrameTypeInfo(nsIFrame* aFrame, int32_t aIndent) {
DR_FrameTypeInfo* frameTypeInfo = GetFrameTypeInfo(aFrame->Type());
if (frameTypeInfo) {
for (int32_t i = 0; i < aIndent; i++) {
printf(" ");
}
if (!strcmp(frameTypeInfo->mNameAbbrev, "unknown")) {
if (aFrame) {
nsAutoString name;
aFrame->GetFrameName(name);
printf("%s %p ", NS_LossyConvertUTF16toASCII(name).get(),
(void*)aFrame);
} else {
printf("%s %p ", frameTypeInfo->mNameAbbrev, (void*)aFrame);
}
} else {
printf("%s %p ", frameTypeInfo->mNameAbbrev, (void*)aFrame);
}
}
}
bool DR_State::RuleMatches(DR_Rule& aRule, DR_FrameTreeNode& aNode) {
NS_ASSERTION(aRule.mTarget, "program error");
DR_RulePart* rulePart;
DR_FrameTreeNode* parentNode;
for (rulePart = aRule.mTarget->mNext, parentNode = aNode.mParent;
rulePart && parentNode;
rulePart = rulePart->mNext, parentNode = parentNode->mParent) {
if (rulePart->mFrameType != LayoutFrameType::None) {
if (parentNode->mFrame) {
if (rulePart->mFrameType != parentNode->mFrame->Type()) {
return false;
}
} else
NS_ASSERTION(false, "program error");
}
// else wild card match
}
return true;
}
void DR_State::FindMatchingRule(DR_FrameTreeNode& aNode) {
if (!aNode.mFrame) {
NS_ASSERTION(false, "invalid DR_FrameTreeNode \n");
return;
}
bool matchingRule = false;
DR_FrameTypeInfo* info = GetFrameTypeInfo(aNode.mFrame->Type());
NS_ASSERTION(info, "program error");
int32_t numRules = info->mRules.Length();
for (int32_t ruleX = 0; ruleX < numRules; ruleX++) {
DR_Rule* rule = info->mRules.ElementAt(ruleX);
if (rule && RuleMatches(*rule, aNode)) {
aNode.mDisplay = rule->mDisplay;
matchingRule = true;
break;
}
}
if (!matchingRule) {
int32_t numWildRules = mWildRules.Length();
for (int32_t ruleX = 0; ruleX < numWildRules; ruleX++) {
DR_Rule* rule = mWildRules.ElementAt(ruleX);
if (rule && RuleMatches(*rule, aNode)) {
aNode.mDisplay = rule->mDisplay;
break;
}
}
}
}
DR_FrameTreeNode* DR_State::CreateTreeNode(nsIFrame* aFrame,
const ReflowInput* aReflowInput) {
// find the frame of the parent reflow input (usually just the parent of
// aFrame)
nsIFrame* parentFrame;
if (aReflowInput) {
const ReflowInput* parentRI = aReflowInput->mParentReflowInput;
parentFrame = (parentRI) ? parentRI->mFrame : nullptr;
} else {
parentFrame = aFrame->GetParent();
}
// find the parent tree node leaf
DR_FrameTreeNode* parentNode = nullptr;
DR_FrameTreeNode* lastLeaf = nullptr;
if (mFrameTreeLeaves.Length())
lastLeaf = mFrameTreeLeaves.ElementAt(mFrameTreeLeaves.Length() - 1);
if (lastLeaf) {
for (parentNode = lastLeaf;
parentNode && (parentNode->mFrame != parentFrame);
parentNode = parentNode->mParent) {
}
}
DR_FrameTreeNode* newNode = new DR_FrameTreeNode(aFrame, parentNode);
FindMatchingRule(*newNode);
newNode->mIndent = mIndent;
if (newNode->mDisplay || mIndentUndisplayedFrames) {
++mIndent;
}
if (lastLeaf && (lastLeaf == parentNode)) {
mFrameTreeLeaves.RemoveLastElement();
}
mFrameTreeLeaves.AppendElement(newNode);
mCount++;
return newNode;
}
void DR_State::PrettyUC(nscoord aSize, char* aBuf, int aBufSize) {
if (NS_UNCONSTRAINEDSIZE == aSize) {
strcpy(aBuf, "UC");
} else {
if ((nscoord)0xdeadbeefU == aSize) {
strcpy(aBuf, "deadbeef");
} else {
snprintf(aBuf, aBufSize, "%d", aSize);
}
}
}
void DR_State::PrintMargin(const char* tag, const nsMargin* aMargin) {
if (aMargin) {
char t[16], r[16], b[16], l[16];
PrettyUC(aMargin->top, t, 16);
PrettyUC(aMargin->right, r, 16);
PrettyUC(aMargin->bottom, b, 16);
PrettyUC(aMargin->left, l, 16);
printf(" %s=%s,%s,%s,%s", tag, t, r, b, l);
} else {
// use %p here for consistency with other null-pointer printouts
printf(" %s=%p", tag, (void*)aMargin);
}
}
void DR_State::DeleteTreeNode(DR_FrameTreeNode& aNode) {
mFrameTreeLeaves.RemoveElement(&aNode);
int32_t numLeaves = mFrameTreeLeaves.Length();
if ((0 == numLeaves) ||
(aNode.mParent != mFrameTreeLeaves.ElementAt(numLeaves - 1))) {
mFrameTreeLeaves.AppendElement(aNode.mParent);
}
if (aNode.mDisplay || mIndentUndisplayedFrames) {
--mIndent;
}
// delete the tree node
delete &aNode;
}
/* static */
void nsIFrame::DisplayReflowStartup() { DR_state = new DR_State(); }
/* static */
void nsIFrame::DisplayReflowShutdown() {
delete DR_state;
DR_state = nullptr;
}
// End Display Reflow
// Validation of SideIsVertical.
# define CASE(side, result) \
static_assert(SideIsVertical(side) == result, "SideIsVertical is wrong")

View file

@ -5489,10 +5489,6 @@ class nsIFrame : public nsQueryFrame {
// NS_FRAME_IS_DIRTY bit set
static void VerifyDirtyBitSet(const nsFrameList& aFrameList);
// Display Reflow Debugging
static void DisplayReflowStartup();
static void DisplayReflowShutdown();
static mozilla::LazyLogModule sFrameLogModule;
#endif
};