Bug 960899 - Add debug function and lldb command to print frame state symbolically. r=dbaron
☠☠ backed out by ec60c69dafc2 ☠ ☠
authorCameron McCormack <cam@mcc.id.au>
Sat, 18 Jan 2014 18:08:22 +1100
changeset 166856 191a71ff02bf9bb10fb82506435862c1a285e7d3
parent 166855 ba2c4b5ff7d878041c2ce1cc061145aaeecec233
child 166857 e6a7d3372dee5c654943324e8faff3f5a82e43f9
push id39312
push usercmccormack@mozilla.com
push dateWed, 05 Feb 2014 03:37:34 +0000
treeherdermozilla-inbound@191a71ff02bf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdbaron
bugs960899
milestone30.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 960899 - Add debug function and lldb command to print frame state symbolically. r=dbaron
layout/generic/moz.build
layout/generic/nsBulletFrame.cpp
layout/generic/nsBulletFrame.h
layout/generic/nsFrameState.cpp
layout/generic/nsFrameState.h
layout/generic/nsFrameStateBits.h
layout/generic/nsPlaceholderFrame.cpp
layout/generic/nsPlaceholderFrame.h
layout/xul/nsBoxFrame.cpp
layout/xul/nsBoxFrame.h
python/lldbutils/README.txt
python/lldbutils/lldbutils/layout.py
--- a/layout/generic/moz.build
+++ b/layout/generic/moz.build
@@ -58,16 +58,17 @@ UNIFIED_SOURCES += [
     'nsContainerFrame.cpp',
     'nsFirstLetterFrame.cpp',
     'nsFlexContainerFrame.cpp',
     'nsFloatManager.cpp',
     'nsFontInflationData.cpp',
     'nsFrame.cpp',
     'nsFrameList.cpp',
     'nsFrameSetFrame.cpp',
+    'nsFrameState.cpp',
     'nsFrameUtil.cpp',
     'nsGfxScrollFrame.cpp',
     'nsHTMLCanvasFrame.cpp',
     'nsHTMLReflowMetrics.cpp',
     'nsHTMLReflowState.cpp',
     'nsImageFrame.cpp',
     'nsImageMap.cpp',
     'nsInlineFrame.cpp',
--- a/layout/generic/nsBulletFrame.cpp
+++ b/layout/generic/nsBulletFrame.cpp
@@ -31,16 +31,22 @@
 #endif
 
 using namespace mozilla;
 
 NS_DECLARE_FRAME_PROPERTY(FontSizeInflationProperty, nullptr)
 
 NS_IMPL_FRAMEARENA_HELPERS(nsBulletFrame)
 
+#ifdef DEBUG
+NS_QUERYFRAME_HEAD(nsBulletFrame)
+  NS_QUERYFRAME_ENTRY(nsBulletFrame)
+NS_QUERYFRAME_TAIL_INHERITING(nsFrame)
+#endif
+
 nsBulletFrame::~nsBulletFrame()
 {
 }
 
 void
 nsBulletFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   // Stop image loading first
--- a/layout/generic/nsBulletFrame.h
+++ b/layout/generic/nsBulletFrame.h
@@ -35,16 +35,20 @@ private:
 
 /**
  * A simple class that manages the layout and rendering of html bullets.
  * This class also supports the CSS list-style properties.
  */
 class nsBulletFrame : public nsFrame {
 public:
   NS_DECL_FRAMEARENA_HELPERS
+#ifdef DEBUG
+  NS_DECL_QUERYFRAME_TARGET(nsBulletFrame)
+  NS_DECL_QUERYFRAME
+#endif
 
   nsBulletFrame(nsStyleContext* aContext)
     : nsFrame(aContext)
   {
   }
   virtual ~nsBulletFrame();
 
   NS_IMETHOD Notify(imgIRequest *aRequest, int32_t aType, const nsIntRect* aData);
new file mode 100644
--- /dev/null
+++ b/layout/generic/nsFrameState.cpp
@@ -0,0 +1,74 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* constants for frame state bits and a type to store them in a uint64_t */
+
+#include "nsFrameState.h"
+
+#include "nsBlockFrame.h"
+#include "nsBoxFrame.h"
+#include "nsBulletFrame.h"
+#include "nsGfxScrollFrame.h"
+#include "nsIFrame.h"
+#include "nsISVGChildFrame.h"
+#include "nsImageFrame.h"
+#include "nsInlineFrame.h"
+#include "nsPlaceholderFrame.h"
+#include "nsSVGContainerFrame.h"
+#include "nsTableCellFrame.h"
+#include "nsTableRowFrame.h"
+#include "nsTableRowGroupFrame.h"
+#include "nsTextFrame.h"
+
+namespace mozilla {
+
+#ifdef DEBUG
+nsCString
+GetFrameState(nsIFrame* aFrame)
+{
+  nsCString result;
+  nsAutoTArray<const char*,3> groups;
+
+  nsFrameState state = aFrame->GetStateBits();
+
+  if (state == nsFrameState(0)) {
+    result.AssignLiteral("0");
+    return result;
+  }
+
+#define FRAME_STATE_GROUP(name_, class_)                                      \
+  {                                                                           \
+    class_* frame = do_QueryFrame(aFrame);                                    \
+    if (frame && (groups.IsEmpty() || strcmp(groups.LastElement(), #name_))) {\
+      groups.AppendElement(#name_);                                           \
+    }                                                                         \
+  }
+#define FRAME_STATE_BIT(group_, value_, name_)                                \
+  if ((state & NS_FRAME_STATE_BIT(value_)) && groups.Contains(#group_)) {     \
+    if (!result.IsEmpty()) {                                                  \
+      result.Insert(" | ", 0);                                                \
+    }                                                                         \
+    result.Insert(#name_, 0);                                                 \
+    state = state & ~NS_FRAME_STATE_BIT(value_);                              \
+  }
+#include "nsFrameStateBits.h"
+#undef FRAME_STATE_GROUP
+#undef FRAME_STATE_BIT
+
+  if (state) {
+    result.AppendPrintf(" | 0x%0llx", state);
+  }
+
+  return result;
+}
+
+void
+PrintFrameState(nsIFrame* aFrame)
+{
+  printf("%s\n", GetFrameState(aFrame).get());
+}
+#endif
+
+} // namespace mozilla
--- a/layout/generic/nsFrameState.h
+++ b/layout/generic/nsFrameState.h
@@ -5,16 +5,18 @@
 
 /* constants for frame state bits and a type to store them in a uint64_t */
 
 #ifndef nsFrameState_h_
 #define nsFrameState_h_
 
 #include <stdint.h>
 
+class nsIFrame;
+
 typedef uint64_t nsFrameState_size_t;
 
 #define NS_FRAME_STATE_BIT(n_) (nsFrameState(nsFrameState_size_t(1) << (n_)))
 
 #if (_MSC_VER == 1600)
 /*
  * Visual Studio 2010 has trouble with the sized enum.  Although sized enums
  * are supported, two problems arise:
@@ -84,9 +86,16 @@ inline nsFrameState& operator^=(nsFrameS
 }
 
 #endif
 
 // Bits 20-31 and 60-63 of the frame state are reserved for implementations.
 #define NS_FRAME_IMPL_RESERVED                      nsFrameState(0xF0000000FFF00000)
 #define NS_FRAME_RESERVED                           ~NS_FRAME_IMPL_RESERVED
 
+namespace mozilla {
+#ifdef DEBUG
+nsCString GetFrameState(nsIFrame* aFrame);
+void PrintFrameState(nsIFrame* aFrame);
+#endif
+}
+
 #endif /* nsFrameState_h_ */ 
--- a/layout/generic/nsFrameStateBits.h
+++ b/layout/generic/nsFrameStateBits.h
@@ -25,16 +25,21 @@
     frame state bits -- bits 0..19 and 32..59 -- are in this group.
 
   FRAME_STATE_BIT(group_, value_, name_)
 
     This denotes the existence of a frame state bit.  group_ indicates
     which group the bit belongs to, value_ is the bit number (0..63),
     and name_ is the name of the frame state bit constant.
 
+  Note that if you add a new frame state group, you'll need to #include
+  the header for its frame classes in nsFrameState.cpp and, if they don't
+  already, add nsQueryFrame implementations (which can be DEBUG-only) to
+  the frame classes.
+
  ******/
 
 #ifndef FRAME_STATE_GROUP
 #define FRAME_STATE_GROUP(name_, class_) /* nothing */
 #define DEFINED_FRAME_STATE_GROUP
 #endif
 
 #ifndef FRAME_STATE_BIT
--- a/layout/generic/nsPlaceholderFrame.cpp
+++ b/layout/generic/nsPlaceholderFrame.cpp
@@ -21,16 +21,22 @@ nsIFrame*
 NS_NewPlaceholderFrame(nsIPresShell* aPresShell, nsStyleContext* aContext,
                        nsFrameState aTypeBit)
 {
   return new (aPresShell) nsPlaceholderFrame(aContext, aTypeBit);
 }
 
 NS_IMPL_FRAMEARENA_HELPERS(nsPlaceholderFrame)
 
+#ifdef DEBUG
+NS_QUERYFRAME_HEAD(nsPlaceholderFrame)
+  NS_QUERYFRAME_ENTRY(nsPlaceholderFrame)
+NS_QUERYFRAME_TAIL_INHERITING(nsFrame)
+#endif
+
 /* virtual */ nsSize
 nsPlaceholderFrame::GetMinSize(nsBoxLayoutState& aBoxLayoutState)
 {
   nsSize size(0, 0);
   DISPLAY_MIN_SIZE(this, size);
   return size;
 }
 
--- a/layout/generic/nsPlaceholderFrame.h
+++ b/layout/generic/nsPlaceholderFrame.h
@@ -49,16 +49,20 @@ nsIFrame* NS_NewPlaceholderFrame(nsIPres
 
 /**
  * Implementation of a frame that's used as a placeholder for a frame that
  * has been moved out of the flow.
  */
 class nsPlaceholderFrame MOZ_FINAL : public nsFrame {
 public:
   NS_DECL_FRAMEARENA_HELPERS
+#ifdef DEBUG
+  NS_DECL_QUERYFRAME_TARGET(nsPlaceholderFrame)
+  NS_DECL_QUERYFRAME
+#endif
 
   /**
    * Create a new placeholder frame.  aTypeBit must be one of the
    * PLACEHOLDER_FOR_* constants above.
    */
   friend nsIFrame* NS_NewPlaceholderFrame(nsIPresShell* aPresShell,
                                           nsStyleContext* aContext,
                                           nsFrameState aTypeBit);
--- a/layout/xul/nsBoxFrame.cpp
+++ b/layout/xul/nsBoxFrame.cpp
@@ -99,16 +99,22 @@ NS_NewBoxFrame(nsIPresShell* aPresShell,
 nsIFrame*
 NS_NewBoxFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 {
   return new (aPresShell) nsBoxFrame(aPresShell, aContext);
 }
 
 NS_IMPL_FRAMEARENA_HELPERS(nsBoxFrame)
 
+#ifdef DEBUG
+NS_QUERYFRAME_HEAD(nsBoxFrame)
+  NS_QUERYFRAME_ENTRY(nsBoxFrame)
+NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
+#endif
+
 nsBoxFrame::nsBoxFrame(nsIPresShell* aPresShell,
                        nsStyleContext* aContext,
                        bool aIsRoot,
                        nsBoxLayout* aLayoutManager) :
   nsContainerFrame(aContext)
 {
   mState |= NS_STATE_IS_HORIZONTAL;
   mState |= NS_STATE_AUTO_STRETCH;
--- a/layout/xul/nsBoxFrame.h
+++ b/layout/xul/nsBoxFrame.h
@@ -27,16 +27,20 @@ nsIFrame* NS_NewBoxFrame(nsIPresShell* a
                          nsBoxLayout* aLayoutManager);
 nsIFrame* NS_NewBoxFrame(nsIPresShell* aPresShell,
                          nsStyleContext* aContext);
 
 class nsBoxFrame : public nsContainerFrame
 {
 public:
   NS_DECL_FRAMEARENA_HELPERS
+#ifdef DEBUG
+  NS_DECL_QUERYFRAME_TARGET(nsBoxFrame)
+  NS_DECL_QUERYFRAME
+#endif
 
   friend nsIFrame* NS_NewBoxFrame(nsIPresShell* aPresShell, 
                                   nsStyleContext* aContext,
                                   bool aIsRoot,
                                   nsBoxLayout* aLayoutManager);
   friend nsIFrame* NS_NewBoxFrame(nsIPresShell* aPresShell,
                                   nsStyleContext* aContext);
 
--- a/python/lldbutils/README.txt
+++ b/python/lldbutils/README.txt
@@ -79,16 +79,29 @@ called with a smart pointer like nsRefPt
   (lldb) p mDocumentURI
   (nsCOMPtr<nsIURI>) $3 = {
     mRawPtr = 0x0000000117163e50
   }
   (lldb) prefcnt mDocumentURI
   11
 
 
+* pstate EXPR
+
+  Shows the frame state bits (using their symbolic names) of a given frame.
+  EXPR is an expression that is evaluated, and must be an nsIFrame*.
+
+  (lldb) p this
+  (nsTextFrame *) $1 = 0x000000011f470b10
+  (lldb) p/x mState
+  (nsFrameState) $2 = 0x0000004080604000
+  (lldb) pstate this
+  TEXT_HAS_NONCOLLAPSED_CHARACTERS | TEXT_END_OF_LINE | TEXT_START_OF_LINE | NS_FRAME_PAINTED_THEBES | NS_FRAME_INDEPENDENT_SELECTION
+
+
 * ptag EXPR
 
   Shows the DOM tag name of a node.  EXPR is an expression that is
   evaluated, and can be either an nsINode pointer or a concrete DOM
   object.
 
   (lldb) p this
   (nsHTMLDocument *) $0 = 0x0000000116e9d800
--- a/python/lldbutils/lldbutils/layout.py
+++ b/python/lldbutils/lldbutils/layout.py
@@ -3,13 +3,18 @@ import lldb
 def frametree(debugger, command, result, dict):
     """Dumps the frame tree containing the given nsIFrame*."""
     debugger.HandleCommand('expr (' + command + ')->DumpFrameTree()')
 
 def frametreelimited(debugger, command, result, dict):
     """Dumps the subtree of a frame tree rooted at the given nsIFrame*."""
     debugger.HandleCommand('expr (' + command + ')->DumpFrameTreeLimited()')
 
+def pstate(debugger, command, result, dict):
+    """Displays a frame's state bits symbolically."""
+    debugger.HandleCommand('expr mozilla::PrintFrameState(' + command + ')')
+
 def init(debugger):
     debugger.HandleCommand('command script add -f lldbutils.layout.frametree frametree')
     debugger.HandleCommand('command script add -f lldbutils.layout.frametreelimited frametreelimited')
     debugger.HandleCommand('command alias ft frametree')
     debugger.HandleCommand('command alias ftl frametreelimited')
+    debugger.HandleCommand('command script add -f lldbutils.layout.pstate pstate');