mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 19:35:51 +00:00
Bug 1072724 - Support showing more information about style structs in restyle logs. r=dbaron
The MOZ_DEBUG_RESTYLE_STRUCTS environment variable can be set to a comma- separated list of style struct names. When restyle logging is enabled, this will cause the style context tree -- showing cached style struct pointers for those structs specified -- to be logged before each individual restyle is processed. It will also show the struct pointer values involved when swapping structs between style contexts. For example, set MOZ_DEBUG_RESTYLE_STRUCTS=Font,UserInterface to show the cached nsStyleFont and nsStyleUserInterface pointers on the style contexts involved in the restyle process.
This commit is contained in:
parent
df48524a26
commit
c3dee3558d
@ -3069,6 +3069,16 @@ ElementRestyler::RestyleSelf(nsIFrame* aSelf,
|
||||
oldContext.get(), newContext.get());
|
||||
oldContext->SwapStyleData(newContext, equalStructs);
|
||||
*aSwappedStructs |= equalStructs;
|
||||
#ifdef RESTYLE_LOGGING
|
||||
uint32_t structs = RestyleManager::StructsToLog() & equalStructs;
|
||||
if (structs) {
|
||||
LOG_RESTYLE_INDENT();
|
||||
LOG_RESTYLE("old style context now has: %s",
|
||||
oldContext->GetCachedStyleDataAsString(structs).get());
|
||||
LOG_RESTYLE("new style context now has: %s",
|
||||
newContext->GetCachedStyleDataAsString(structs).get());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
LOG_RESTYLE("setting new style context");
|
||||
aSelf->SetStyleContext(newContext);
|
||||
@ -3636,6 +3646,39 @@ RestyleManager::ComputeStyleChangeFor(nsIFrame* aFrame,
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef RESTYLE_LOGGING
|
||||
uint32_t
|
||||
RestyleManager::StructsToLog()
|
||||
{
|
||||
static bool initialized = false;
|
||||
static uint32_t structs;
|
||||
if (!initialized) {
|
||||
structs = 0;
|
||||
const char* value = getenv("MOZ_DEBUG_RESTYLE_STRUCTS");
|
||||
if (value) {
|
||||
nsCString s(value);
|
||||
while (!s.IsEmpty()) {
|
||||
int32_t index = s.FindChar(',');
|
||||
nsStyleStructID sid;
|
||||
bool found;
|
||||
if (index == -1) {
|
||||
found = nsStyleContext::LookupStruct(s, sid);
|
||||
s.Truncate();
|
||||
} else {
|
||||
found = nsStyleContext::LookupStruct(Substring(s, 0, index), sid);
|
||||
s = Substring(s, index + 1);
|
||||
}
|
||||
if (found) {
|
||||
structs |= nsCachedStyleData::GetBitForSID(sid);
|
||||
}
|
||||
}
|
||||
}
|
||||
initialized = true;
|
||||
}
|
||||
return structs;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
/* static */ nsCString
|
||||
RestyleManager::RestyleHintToString(nsRestyleHint aHint)
|
||||
|
@ -386,6 +386,13 @@ public:
|
||||
return animations;
|
||||
}
|
||||
|
||||
// Set MOZ_DEBUG_RESTYLE_STRUCTS to a comma-separated string of
|
||||
// style struct names -- such as "Font,SVGReset" -- to log the style context
|
||||
// tree and those cached struct pointers before each restyle. This
|
||||
// function returns a bitfield of the structs named in the
|
||||
// environment variable.
|
||||
static uint32_t StructsToLog();
|
||||
|
||||
static nsCString StructNamesToString(uint32_t aSIDs);
|
||||
int32_t& LoggingDepth() { return mLoggingDepth; }
|
||||
#endif
|
||||
|
@ -162,7 +162,17 @@ RestyleTracker::ProcessOneRestyle(Element* aElement,
|
||||
RestyleManager::ChangeHintToString(aChangeHint).get());
|
||||
|
||||
nsIFrame* primaryFrame = aElement->GetPrimaryFrame();
|
||||
|
||||
if (aRestyleHint & ~eRestyle_LaterSiblings) {
|
||||
#ifdef RESTYLE_LOGGING
|
||||
if (ShouldLogRestyle() && primaryFrame &&
|
||||
RestyleManager::StructsToLog() != 0) {
|
||||
LOG_RESTYLE("style context tree before restyle:");
|
||||
LOG_RESTYLE_INDENT();
|
||||
primaryFrame->StyleContext()->LogStyleContextTree(
|
||||
LoggingDepth(), RestyleManager::StructsToLog());
|
||||
}
|
||||
#endif
|
||||
mRestyleManager->RestyleElement(aElement, primaryFrame, aChangeHint,
|
||||
*this, aRestyleHint);
|
||||
} else if (aChangeHint &&
|
||||
|
@ -1048,6 +1048,21 @@ nsStyleContext::StructName(nsStyleStructID aSID)
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
nsStyleContext::LookupStruct(const nsACString& aName, nsStyleStructID& aResult)
|
||||
{
|
||||
if (false)
|
||||
;
|
||||
#define STYLE_STRUCT(name_, checkdata_cb_) \
|
||||
else if (aName.EqualsLiteral(#name_)) \
|
||||
aResult = eStyleStruct_##name_;
|
||||
#include "nsStyleStructList.h"
|
||||
#undef STYLE_STRUCT
|
||||
else
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool
|
||||
@ -1162,3 +1177,96 @@ nsStyleContext::DoClearCachedInheritedStyleDataOnDescendants(uint32_t aStructs)
|
||||
|
||||
ClearCachedInheritedStyleDataOnDescendants(aStructs);
|
||||
}
|
||||
|
||||
#ifdef RESTYLE_LOGGING
|
||||
nsCString
|
||||
nsStyleContext::GetCachedStyleDataAsString(uint32_t aStructs)
|
||||
{
|
||||
nsCString structs;
|
||||
for (nsStyleStructID i = nsStyleStructID(0);
|
||||
i < nsStyleStructID_Length;
|
||||
i = nsStyleStructID(i + 1)) {
|
||||
if (aStructs & nsCachedStyleData::GetBitForSID(i)) {
|
||||
const void* data = GetCachedStyleData(i);
|
||||
if (!structs.IsEmpty()) {
|
||||
structs.Append(' ');
|
||||
}
|
||||
structs.AppendPrintf("%s=%p", StructName(i), data);
|
||||
if (HasCachedInheritedStyleData(i)) {
|
||||
structs.AppendLiteral("(dependent)");
|
||||
} else {
|
||||
structs.AppendLiteral("(owned)");
|
||||
}
|
||||
}
|
||||
}
|
||||
return structs;
|
||||
}
|
||||
|
||||
int32_t&
|
||||
nsStyleContext::LoggingDepth()
|
||||
{
|
||||
static int32_t depth = 0;
|
||||
return depth;
|
||||
}
|
||||
|
||||
void
|
||||
nsStyleContext::LogStyleContextTree(int32_t aLoggingDepth, uint32_t aStructs)
|
||||
{
|
||||
LoggingDepth() = aLoggingDepth;
|
||||
LogStyleContextTree(true, aStructs);
|
||||
}
|
||||
|
||||
void
|
||||
nsStyleContext::LogStyleContextTree(bool aFirst, uint32_t aStructs)
|
||||
{
|
||||
nsCString structs = GetCachedStyleDataAsString(aStructs);
|
||||
if (!structs.IsEmpty()) {
|
||||
structs.Append(' ');
|
||||
}
|
||||
|
||||
nsCString pseudo;
|
||||
if (mPseudoTag) {
|
||||
nsAutoString pseudoTag;
|
||||
mPseudoTag->ToString(pseudoTag);
|
||||
AppendUTF16toUTF8(pseudoTag, pseudo);
|
||||
pseudo.Append(' ');
|
||||
}
|
||||
|
||||
nsCString flags;
|
||||
if (IsStyleIfVisited()) {
|
||||
flags.AppendLiteral("IS_STYLE_IF_VISITED ");
|
||||
}
|
||||
if (UsesGrandancestorStyle()) {
|
||||
flags.AppendLiteral("USES_GRANDANCESTOR_STYLE ");
|
||||
}
|
||||
if (IsShared()) {
|
||||
flags.AppendLiteral("IS_SHARED ");
|
||||
}
|
||||
|
||||
nsCString parent;
|
||||
if (aFirst) {
|
||||
parent.AppendPrintf("parent=%p ", mParent);
|
||||
}
|
||||
|
||||
LOG_RESTYLE("%p(%d) %s%s%s%s",
|
||||
this, mRefCnt,
|
||||
structs.get(), pseudo.get(), flags.get(), parent.get());
|
||||
|
||||
LOG_RESTYLE_INDENT();
|
||||
|
||||
if (nullptr != mChild) {
|
||||
nsStyleContext* child = mChild;
|
||||
do {
|
||||
child->LogStyleContextTree(false, aStructs);
|
||||
child = child->mNextSibling;
|
||||
} while (mChild != child);
|
||||
}
|
||||
if (nullptr != mEmptyChild) {
|
||||
nsStyleContext* child = mEmptyChild;
|
||||
do {
|
||||
child->LogStyleContextTree(false, aStructs);
|
||||
child = child->mNextSibling;
|
||||
} while (mEmptyChild != child);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -8,6 +8,7 @@
|
||||
#ifndef _nsStyleContext_h_
|
||||
#define _nsStyleContext_h_
|
||||
|
||||
#include "mozilla/RestyleLogging.h"
|
||||
#include "nsRuleNode.h"
|
||||
#include "nsCSSPseudoElements.h"
|
||||
|
||||
@ -397,6 +398,13 @@ public:
|
||||
void List(FILE* out, int32_t aIndent);
|
||||
static void AssertStyleStructMaxDifferenceValid();
|
||||
static const char* StructName(nsStyleStructID aSID);
|
||||
static bool LookupStruct(const nsACString& aName, nsStyleStructID& aResult);
|
||||
#endif
|
||||
|
||||
#ifdef RESTYLE_LOGGING
|
||||
nsCString GetCachedStyleDataAsString(uint32_t aStructs);
|
||||
void LogStyleContextTree(int32_t aLoggingDepth, uint32_t aStructs);
|
||||
int32_t& LoggingDepth();
|
||||
#endif
|
||||
|
||||
private:
|
||||
@ -450,6 +458,15 @@ private:
|
||||
int32_t aLevels) const;
|
||||
#endif
|
||||
|
||||
#ifdef RESTYLE_LOGGING
|
||||
void LogStyleContextTree(bool aFirst, uint32_t aStructs);
|
||||
|
||||
// This only gets called under call trees where we've already checked
|
||||
// that PresContext()->RestyleManager()->ShouldLogRestyle() returned true.
|
||||
// It exists here just to satisfy LOG_RESTYLE's expectations.
|
||||
bool ShouldLogRestyle() { return true; }
|
||||
#endif
|
||||
|
||||
nsStyleContext* mParent; // STRONG
|
||||
|
||||
// Children are kept in two circularly-linked lists. The list anchor
|
||||
|
Loading…
Reference in New Issue
Block a user