Author: lluis
Date: 2006-11-22 12:38:12 -0500 (Wed, 22 Nov 2006)
New Revision: 68356

Modified:
   trunk/heap-shot/ChangeLog
   trunk/heap-shot/HeapShot.Gui.Widgets/ReferenceTreeViewer.cs
   trunk/heap-shot/HeapShot.Gui.Widgets/gtk-gui/gui.stetic
   trunk/heap-shot/HeapShot.Reader/ObjectMapFileReader.cs
   trunk/heap-shot/HeapShot.Reader/ReferenceNode.cs
   trunk/heap-shot/profiler/heap-shot.c
   trunk/heap-shot/profiler/outfile-writer.c
Log:
* profiler/outfile-writer.c, profiler/heap-shot.c: Scan the whole type
  hierarchy of a type when looking for references.
* HeapShot.Gui.Widgets/ReferenceTreeViewer.cs,
  HeapShot.Reader/ReferenceNode.cs: Added column which shows the
  reference count to the root type being inspected.
* HeapShot.Gui.Widgets/gtk-gui/gui.stetic: Updated.
* HeapShot.Reader/ObjectMapFileReader.cs: Added GetRoots method, not
  used right now.

Modified: trunk/heap-shot/ChangeLog
===================================================================
--- trunk/heap-shot/ChangeLog   2006-11-22 17:16:43 UTC (rev 68355)
+++ trunk/heap-shot/ChangeLog   2006-11-22 17:38:12 UTC (rev 68356)
@@ -1,3 +1,14 @@
+2006-11-22  Lluis Sanchez Gual <[EMAIL PROTECTED]> 
+
+       * profiler/outfile-writer.c, profiler/heap-shot.c: Scan the whole type
+         hierarchy of a type when looking for references.
+       * HeapShot.Gui.Widgets/ReferenceTreeViewer.cs,
+         HeapShot.Reader/ReferenceNode.cs: Added column which shows the
+         reference count to the root type being inspected.
+       * HeapShot.Gui.Widgets/gtk-gui/gui.stetic: Updated.
+       * HeapShot.Reader/ObjectMapFileReader.cs: Added GetRoots method, not
+         used right now.
+
 2006-11-15  Lluis Sanchez Gual  <[EMAIL PROTECTED]> 
 
        * HeapShot.Gui.Widgets/ReferenceTreeViewer.cs: Removed debug code.

Modified: trunk/heap-shot/HeapShot.Gui.Widgets/ReferenceTreeViewer.cs
===================================================================
--- trunk/heap-shot/HeapShot.Gui.Widgets/ReferenceTreeViewer.cs 2006-11-22 
17:16:43 UTC (rev 68355)
+++ trunk/heap-shot/HeapShot.Gui.Widgets/ReferenceTreeViewer.cs 2006-11-22 
17:38:12 UTC (rev 68356)
@@ -22,6 +22,7 @@
                const int AvgSizeCol = 5;
                const int InstancesCol = 6;
                const int RefsCol = 7;
+               const int RootRefsCol = 8;
                int TreeColRefs;
                bool reloadRequested;
                bool loading;
@@ -35,7 +36,7 @@
                public ReferenceTreeViewer()
                {
                        Stetic.Gui.Build(this, 
typeof(HeapShot.Gui.Widgets.ReferenceTreeViewer));
-                       store = new Gtk.TreeStore (typeof(object), 
typeof(string), typeof(string), typeof(bool), typeof(string), typeof(string), 
typeof(string), typeof(string));
+                       store = new Gtk.TreeStore (typeof(object), 
typeof(string), typeof(string), typeof(bool), typeof(string), typeof(string), 
typeof(string), typeof(string), typeof(string));
                        treeview.Model = store;
                        treeview.HeadersClickable = true;
                        
@@ -55,17 +56,20 @@
                        treeview.AppendColumn (complete_column);
                        CellRendererText crt = new CellRendererText ();
                        crt.Xalign = 1;
-                       treeview.AppendColumn ("Instances", crt, "text", 
InstancesCol).Clickable = true;
+                       treeview.AppendColumn ("Instances", crt, "text", 
InstancesCol);
                        crt = new CellRendererText ();
                        crt.Xalign = 1;
                        TreeColRefs = treeview.Columns.Length;
-                       treeview.AppendColumn ("References", crt, "text", 
RefsCol).Clickable = true;
+                       treeview.AppendColumn ("References", crt, "text", 
RefsCol);
                        crt = new CellRendererText ();
                        crt.Xalign = 1;
-                       treeview.AppendColumn ("Memory Size", crt, "text", 
SizeCol).Clickable = true;
+                       treeview.AppendColumn ("Root Refs", crt, "text", 
RootRefsCol);
                        crt = new CellRendererText ();
                        crt.Xalign = 1;
-                       treeview.AppendColumn ("Avg. Size", crt, "text", 
AvgSizeCol).Clickable = true;
+                       treeview.AppendColumn ("Memory Size", crt, "text", 
SizeCol);
+                       crt = new CellRendererText ();
+                       crt.Xalign = 1;
+                       treeview.AppendColumn ("Avg. Size", crt, "text", 
AvgSizeCol);
                        
                        treeview.TestExpandRow += new Gtk.TestExpandRowHandler 
(OnTestExpandRow);
                        treeview.RowActivated += new Gtk.RowActivatedHandler 
(OnNodeActivated);
@@ -114,6 +118,7 @@
                        this.typeName = null;
                        boxFilter.Visible = true;
                        treeview.Columns [TreeColRefs].Visible = 
InverseReferences;
+                       treeview.Columns [TreeColRefs+1].Visible = 
InverseReferences;
                        
                        if (loading) {
                                // If the tree is already being loaded, notify 
that loading
@@ -153,6 +158,7 @@
                        store.Clear ();
                        boxFilter.Visible = false;
                        treeview.Columns [TreeColRefs].Visible = 
InverseReferences;
+                       treeview.Columns [TreeColRefs+1].Visible = 
InverseReferences;
                        TreeIter iter = InternalFillType (file, 
file.GetTypeFromName (typeName));
                        treeview.ExpandRow (store.GetPath (iter), false);
                }
@@ -178,15 +184,16 @@
                        
                        TreeIter iter;
                        if (parent.Equals (TreeIter.Zero)) {
-                               iter = store.AppendValues (node, "class", 
node.TypeName, !node.HasReferences, node.TotalMemory.ToString("n0"), 
node.AverageSize.ToString("n0"), node.RefCount.ToString ("n0"), "");
+                               iter = store.AppendValues (node, "class", 
node.TypeName, !node.HasReferences, node.TotalMemory.ToString("n0"), 
node.AverageSize.ToString("n0"), node.RefCount.ToString ("n0"), "", "");
                        } else {
                                string refs = (InverseReferences ? 
node.RefsToParent.ToString ("n0") : "");
-                               iter = store.AppendValues (parent, node, 
"class", node.TypeName, !node.HasReferences, node.TotalMemory.ToString("n0"), 
node.AverageSize.ToString("n0"), node.RefCount.ToString ("n0"), refs);
+                               string rootRefs = (InverseReferences ? 
node.RefsToRoot.ToString ("n0") : "");
+                               iter = store.AppendValues (parent, node, 
"class", node.TypeName, !node.HasReferences, node.TotalMemory.ToString("n0"), 
node.AverageSize.ToString("n0"), node.RefCount.ToString ("n0"), refs, rootRefs);
                        }
 
                        if (node.HasReferences) {
                                // Add a dummy element to make the expansion 
icon visible
-                               store.AppendValues (iter, null, "", "", true, 
"", "", "", "");
+                               store.AppendValues (iter, null, "", "", true, 
"", "", "", "", "");
                        }
                        return iter;
                }
@@ -194,9 +201,9 @@
                TreeIter AddNode (TreeIter parent, FieldReference node)
                {
                        if (parent.Equals (TreeIter.Zero))
-                               return store.AppendValues (node, "field", 
node.FiledName, true, "", "", node.RefCount.ToString ("n0"), "");
+                               return store.AppendValues (node, "field", 
node.FiledName, true, "", "", node.RefCount.ToString ("n0"), "", "");
                        else
-                               return store.AppendValues (parent, node, 
"field", node.FiledName, true, "", "", node.RefCount.ToString ("n0"), "");
+                               return store.AppendValues (parent, node, 
"field", node.FiledName, true, "", "", node.RefCount.ToString ("n0"), "", "");
                }
 
                private void OnTestExpandRow (object sender, 
Gtk.TestExpandRowArgs args)
@@ -264,20 +271,21 @@
                                        case 2:
                                                return 
nod1.RefsToParent.CompareTo (nod2.RefsToParent);
                                        case 3:
+                                               return 
nod1.RefsToRoot.CompareTo (nod2.RefsToRoot);
+                                       case 4:
                                                return 
nod1.TotalMemory.CompareTo (nod2.TotalMemory);
-                                       case 4:
+                                       case 5:
                                                return 
nod1.AverageSize.CompareTo (nod2.AverageSize);
                                        default:
-                                               Console.WriteLine ("PPP: " + 
col);
                                                return 1;
        //                                      throw new 
InvalidOperationException ();
                                }
                        } else if (o1 is FieldReference && o2 is 
FieldReference) {
                                return ((FieldReference)o1).FiledName.CompareTo 
(((FieldReference)o2).FiledName);
                        } else if (o1 is FieldReference) {
+                               return 1;
+                       } else {
                                return -1;
-                       } else {
-                               return 1;
                        }
                }
                

Modified: trunk/heap-shot/HeapShot.Gui.Widgets/gtk-gui/gui.stetic
===================================================================
--- trunk/heap-shot/HeapShot.Gui.Widgets/gtk-gui/gui.stetic     2006-11-22 
17:16:43 UTC (rev 68355)
+++ trunk/heap-shot/HeapShot.Gui.Widgets/gtk-gui/gui.stetic     2006-11-22 
17:38:12 UTC (rev 68356)
@@ -13,27 +13,27 @@
     </icon-set>
   </icon-factory>
   <widget class="Gtk.Bin" id="HeapShot.Gui.Widgets.ObjectMapViewer" 
design-size="556 300">
+    <property name="MemberName" />
     <property name="Events">ButtonPressMask</property>
-    <property name="MemberName" />
     <child>
       <widget class="Gtk.HBox" id="hbox3">
         <property name="Spacing">6</property>
+        <property name="MemberName" />
         <property name="Events">0</property>
-        <property name="MemberName" />
         <child>
           <widget class="Gtk.ScrolledWindow" id="scrolledwindow2">
             <property name="VscrollbarPolicy">Automatic</property>
             <property name="HscrollbarPolicy">Never</property>
             <property name="ShadowType">In</property>
+            <property name="MemberName" />
             <property name="CanFocus">True</property>
             <property name="Events">0</property>
-            <property name="MemberName" />
             <child>
               <widget class="Gtk.TreeView" id="fileList">
                 <property name="HeadersVisible">False</property>
+                <property name="MemberName">fileList</property>
                 <property name="CanFocus">True</property>
                 <property name="Events">0</property>
-                <property name="MemberName">fileList</property>
               </widget>
             </child>
           </widget>
@@ -47,9 +47,9 @@
         <child>
           <widget class="Gtk.Notebook" id="notebook">
             <property name="Scrollable">True</property>
+            <property name="MemberName">notebook</property>
             <property name="CanFocus">True</property>
             <property name="Events">0</property>
-            <property name="MemberName">notebook</property>
             <child>
               <widget class="Gtk.Table" id="table1">
                 <property name="NRows">3</property>
@@ -57,134 +57,134 @@
                 <property name="RowSpacing">6</property>
                 <property name="ColumnSpacing">6</property>
                 <property name="BorderWidth">12</property>
+                <property name="MemberName" />
                 <property name="Events">0</property>
-                <property name="MemberName" />
                 <child>
-                  <widget class="Gtk.Label" id="labelMemory">
-                    <property name="LabelProp" />
+                  <widget class="Gtk.Label" id="label3">
+                    <property name="LabelProp" translatable="yes" 
context="yes" comments="">|Name:</property>
                     <property name="Xalign">0</property>
+                    <property name="MemberName" />
                     <property name="Events">0</property>
-                    <property name="MemberName">labelMemory</property>
                   </widget>
                   <packing>
-                    <property name="BottomAttach">3</property>
-                    <property name="LeftAttach">1</property>
-                    <property name="YExpand">False</property>
-                    <property name="RightAttach">2</property>
                     <property name="AutoSize">True</property>
-                    <property name="YShrink">False</property>
-                    <property name="TopAttach">2</property>
+                    <property name="XOptions">Fill</property>
+                    <property name="YOptions">Fill</property>
+                    <property name="XExpand">False</property>
+                    <property name="XFill">True</property>
                     <property name="XShrink">False</property>
-                    <property name="XExpand">False</property>
+                    <property name="YExpand">False</property>
                     <property name="YFill">True</property>
-                    <property name="XFill">True</property>
-                    <property name="YOptions">Fill</property>
-                    <property name="XOptions">Fill</property>
+                    <property name="YShrink">False</property>
                   </packing>
                 </child>
                 <child>
-                  <widget class="Gtk.Label" id="labelCount">
-                    <property name="LabelProp" />
+                  <widget class="Gtk.Label" id="label4">
+                    <property name="LabelProp" translatable="yes" 
context="yes" comments="">|Object count:</property>
                     <property name="Xalign">0</property>
+                    <property name="MemberName" />
                     <property name="Events">0</property>
-                    <property name="MemberName">labelCount</property>
                   </widget>
                   <packing>
+                    <property name="TopAttach">1</property>
                     <property name="BottomAttach">2</property>
-                    <property name="LeftAttach">1</property>
-                    <property name="YExpand">False</property>
-                    <property name="RightAttach">2</property>
                     <property name="AutoSize">True</property>
-                    <property name="YShrink">False</property>
-                    <property name="TopAttach">1</property>
+                    <property name="XOptions">Fill</property>
+                    <property name="YOptions">Fill</property>
+                    <property name="XExpand">False</property>
+                    <property name="XFill">True</property>
                     <property name="XShrink">False</property>
-                    <property name="XExpand">False</property>
+                    <property name="YExpand">False</property>
                     <property name="YFill">True</property>
-                    <property name="XFill">True</property>
-                    <property name="YOptions">Fill</property>
-                    <property name="XOptions">Fill</property>
+                    <property name="YShrink">False</property>
                   </packing>
                 </child>
                 <child>
-                  <widget class="Gtk.Label" id="labelName">
-                    <property name="LabelProp" />
+                  <widget class="Gtk.Label" id="label5">
+                    <property name="LabelProp" translatable="yes" 
context="yes" comments="">|Total memory:</property>
                     <property name="Xalign">0</property>
+                    <property name="MemberName" />
                     <property name="Events">0</property>
-                    <property name="MemberName">labelName</property>
                   </widget>
                   <packing>
-                    <property name="LeftAttach">1</property>
-                    <property name="YExpand">False</property>
-                    <property name="RightAttach">2</property>
+                    <property name="TopAttach">2</property>
+                    <property name="BottomAttach">3</property>
                     <property name="AutoSize">True</property>
-                    <property name="YShrink">False</property>
+                    <property name="XOptions">Fill</property>
+                    <property name="YOptions">Fill</property>
+                    <property name="XExpand">False</property>
+                    <property name="XFill">True</property>
                     <property name="XShrink">False</property>
-                    <property name="XExpand">False</property>
+                    <property name="YExpand">False</property>
                     <property name="YFill">True</property>
-                    <property name="XFill">True</property>
-                    <property name="YOptions">Fill</property>
-                    <property name="XOptions">Fill</property>
+                    <property name="YShrink">False</property>
                   </packing>
                 </child>
                 <child>
-                  <widget class="Gtk.Label" id="label5">
-                    <property name="LabelProp" translatable="yes" 
context="yes" comments="">|Total memory:</property>
+                  <widget class="Gtk.Label" id="labelName">
+                    <property name="LabelProp" />
                     <property name="Xalign">0</property>
+                    <property name="MemberName">labelName</property>
                     <property name="Events">0</property>
-                    <property name="MemberName" />
                   </widget>
                   <packing>
-                    <property name="BottomAttach">3</property>
-                    <property name="YExpand">False</property>
+                    <property name="LeftAttach">1</property>
+                    <property name="RightAttach">2</property>
                     <property name="AutoSize">True</property>
-                    <property name="YShrink">False</property>
-                    <property name="TopAttach">2</property>
+                    <property name="XOptions">Fill</property>
+                    <property name="YOptions">Fill</property>
+                    <property name="XExpand">False</property>
+                    <property name="XFill">True</property>
                     <property name="XShrink">False</property>
-                    <property name="XExpand">False</property>
+                    <property name="YExpand">False</property>
                     <property name="YFill">True</property>
-                    <property name="XFill">True</property>
-                    <property name="YOptions">Fill</property>
-                    <property name="XOptions">Fill</property>
+                    <property name="YShrink">False</property>
                   </packing>
                 </child>
                 <child>
-                  <widget class="Gtk.Label" id="label4">
-                    <property name="LabelProp" translatable="yes" 
context="yes" comments="">|Object count:</property>
+                  <widget class="Gtk.Label" id="labelCount">
+                    <property name="LabelProp" />
                     <property name="Xalign">0</property>
+                    <property name="MemberName">labelCount</property>
                     <property name="Events">0</property>
-                    <property name="MemberName" />
                   </widget>
                   <packing>
+                    <property name="TopAttach">1</property>
                     <property name="BottomAttach">2</property>
-                    <property name="YExpand">False</property>
+                    <property name="LeftAttach">1</property>
+                    <property name="RightAttach">2</property>
                     <property name="AutoSize">True</property>
-                    <property name="YShrink">False</property>
-                    <property name="TopAttach">1</property>
+                    <property name="XOptions">Fill</property>
+                    <property name="YOptions">Fill</property>
+                    <property name="XExpand">False</property>
+                    <property name="XFill">True</property>
                     <property name="XShrink">False</property>
-                    <property name="XExpand">False</property>
+                    <property name="YExpand">False</property>
                     <property name="YFill">True</property>
-                    <property name="XFill">True</property>
-                    <property name="YOptions">Fill</property>
-                    <property name="XOptions">Fill</property>
+                    <property name="YShrink">False</property>
                   </packing>
                 </child>
                 <child>
-                  <widget class="Gtk.Label" id="label3">
-                    <property name="LabelProp" translatable="yes" 
context="yes" comments="">|Name:</property>
+                  <widget class="Gtk.Label" id="labelMemory">
+                    <property name="LabelProp" />
                     <property name="Xalign">0</property>
+                    <property name="MemberName">labelMemory</property>
                     <property name="Events">0</property>
-                    <property name="MemberName" />
                   </widget>
                   <packing>
-                    <property name="YExpand">False</property>
+                    <property name="TopAttach">2</property>
+                    <property name="BottomAttach">3</property>
+                    <property name="LeftAttach">1</property>
+                    <property name="RightAttach">2</property>
                     <property name="AutoSize">True</property>
-                    <property name="YShrink">False</property>
+                    <property name="XOptions">Fill</property>
+                    <property name="YOptions">Fill</property>
+                    <property name="XExpand">False</property>
+                    <property name="XFill">True</property>
                     <property name="XShrink">False</property>
-                    <property name="XExpand">False</property>
+                    <property name="YExpand">False</property>
                     <property name="YFill">True</property>
-                    <property name="XFill">True</property>
-                    <property name="YOptions">Fill</property>
-                    <property name="XOptions">Fill</property>
+                    <property name="YShrink">False</property>
                   </packing>
                 </child>
               </widget>
@@ -195,8 +195,8 @@
             <child>
               <widget class="Gtk.Label" id="label9">
                 <property name="LabelProp">Summary</property>
+                <property name="MemberName" />
                 <property name="Events">0</property>
-                <property name="MemberName" />
               </widget>
               <packing>
                 <property name="type">tab</property>
@@ -216,8 +216,8 @@
             <child>
               <widget class="Gtk.Label" id="label2">
                 <property name="LabelProp">All objects</property>
+                <property name="MemberName" />
                 <property name="Events">0</property>
-                <property name="MemberName" />
               </widget>
               <packing>
                 <property name="type">tab</property>
@@ -233,27 +233,27 @@
     </child>
   </widget>
   <widget class="Gtk.Bin" id="HeapShot.Gui.Widgets.ReferenceTreeViewer" 
design-size="480 300">
+    <property name="MemberName" />
     <property name="Events">ButtonPressMask</property>
-    <property name="MemberName" />
     <child>
       <widget class="Gtk.VBox" id="vbox1">
         <property name="Spacing">6</property>
         <property name="BorderWidth">6</property>
+        <property name="MemberName" />
         <property name="Events">0</property>
-        <property name="MemberName" />
         <child>
           <widget class="Gtk.ScrolledWindow" id="scrolledwindow1">
             <property name="VscrollbarPolicy">Automatic</property>
             <property name="HscrollbarPolicy">Automatic</property>
             <property name="ShadowType">In</property>
+            <property name="MemberName" />
             <property name="CanFocus">True</property>
             <property name="Events">0</property>
-            <property name="MemberName" />
             <child>
               <widget class="Gtk.TreeView" id="treeview">
+                <property name="MemberName">treeview</property>
                 <property name="CanFocus">True</property>
                 <property name="Events">0</property>
-                <property name="MemberName">treeview</property>
               </widget>
             </child>
           </widget>
@@ -265,20 +265,20 @@
         <child>
           <widget class="Gtk.HBox" id="hbox1">
             <property name="Spacing">6</property>
+            <property name="MemberName" />
             <property name="Events">0</property>
-            <property name="MemberName" />
             <child>
               <widget class="Gtk.HBox" id="boxFilter">
                 <property name="Spacing">3</property>
+                <property name="MemberName">boxFilter</property>
                 <property name="Events">0</property>
-                <property name="MemberName">boxFilter</property>
                 <child>
                   <widget class="Gtk.Entry" id="entryFilter">
                     <property name="IsEditable">True</property>
                     <property name="InvisibleChar">●</property>
+                    <property name="MemberName">entryFilter</property>
                     <property name="CanFocus">True</property>
                     <property name="Events">0</property>
-                    <property name="MemberName">entryFilter</property>
                     <signal name="Activated" handler="OnEntryFilterActivated" 
/>
                   </widget>
                   <packing>
@@ -291,9 +291,9 @@
                     <property name="Type">TextOnly</property>
                     <property name="Label">Filter</property>
                     <property name="IsDialogButton">False</property>
+                    <property name="MemberName" />
                     <property name="CanFocus">True</property>
                     <property name="Events">0</property>
-                    <property name="MemberName" />
                     <signal name="Clicked" handler="OnButtonFilterClicked" />
                   </widget>
                   <packing>
@@ -314,9 +314,9 @@
                 <property name="Label">Inverse references</property>
                 <property name="DrawIndicator">True</property>
                 <property name="HasLabel">True</property>
+                <property name="MemberName">checkInverse</property>
                 <property name="CanFocus">True</property>
                 <property name="Events">0</property>
-                <property name="MemberName">checkInverse</property>
                 <signal name="Clicked" handler="OnCheckInverseClicked" />
               </widget>
               <packing>

Modified: trunk/heap-shot/HeapShot.Reader/ObjectMapFileReader.cs
===================================================================
--- trunk/heap-shot/HeapShot.Reader/ObjectMapFileReader.cs      2006-11-22 
17:16:43 UTC (rev 68355)
+++ trunk/heap-shot/HeapShot.Reader/ObjectMapFileReader.cs      2006-11-22 
17:38:12 UTC (rev 68356)
@@ -423,6 +423,48 @@
                        return nod;
                }
                
+               public List<List<int>> GetRoots (int type)
+               {
+                       List<int> path = new List<int> ();
+                       Dictionary<int,List<int>> roots = new 
Dictionary<int,List<int>> ();
+                       Dictionary<int,int> visited = new Dictionary<int,int> 
();
+                       
+                       foreach (int obj in GetObjectsByType (type)) {
+                               FindRoot (visited, path, roots, obj);
+                               visited.Clear ();
+                       }
+                       
+                       List<List<int>> res = new List<List<int>> ();
+                       res.AddRange (roots.Values);
+                       return res;
+               }
+               
+               void FindRoot (Dictionary<int,int> visited, List<int> path, 
Dictionary<int,List<int>> roots, int obj)
+               {
+                       if (visited.ContainsKey (obj))
+                               return;
+                       visited [obj] = obj;
+                       path.Add (obj);
+                       
+                       bool hasrefs = false;
+                       foreach (int oref in GetReferencers (obj)) {
+                               hasrefs = true;
+                               FindRoot (visited, path, roots, oref);
+                       }
+                       
+                       if (!hasrefs) {
+                               // A root
+                               if (!roots.ContainsKey (obj)) {
+                                       roots [obj] = new List<int> (path);
+                               } else {
+                                       List<int> ep = roots [obj];
+                                       if (ep.Count > path.Count)
+                                               roots [obj] = new List<int> 
(path);
+                               }
+                       }
+                       path.RemoveAt (path.Count - 1);
+               }               
+               
                public int GetTypeCount ()
                {
                        return (int) numTypes;

Modified: trunk/heap-shot/HeapShot.Reader/ReferenceNode.cs
===================================================================
--- trunk/heap-shot/HeapShot.Reader/ReferenceNode.cs    2006-11-22 17:16:43 UTC 
(rev 68355)
+++ trunk/heap-shot/HeapShot.Reader/ReferenceNode.cs    2006-11-22 17:38:12 UTC 
(rev 68356)
@@ -36,6 +36,7 @@
                public string TypeName;
                public int RefCount;
                public int RefsToParent;
+               public int RefsToRoot;
                public uint TotalMemory;
                int type;
                bool globalRefs;
@@ -71,19 +72,15 @@
                
                public void AddReference (int obj)
                {
-                       AddReference (-1, obj, null);
+                       AddReference (-1, obj, 1, null);
                }
                
-               public void AddReference (int parentObject, int obj)
+               void AddReference (int parentObject, int obj, int refsToRoot, 
string fieldName)
                {
-                       AddReference (parentObject, obj, (string) null);
-               }
-               
-               void AddReference (int parentObject, int obj, string fieldName)
-               {
                        if (parentObject != -1 && !parentObjects.ContainsKey 
(parentObject)) {
                                parentObjects [parentObject] = parentObject;
                                RefsToParent++;
+                               RefsToRoot += refsToRoot;
                        }
 
                        if (fieldName != null) {
@@ -108,12 +105,14 @@
                                }
                        }
                        
-                       if (refObjects.ContainsKey (obj))
+                       if (refObjects.ContainsKey (obj)) {
+                               refObjects [obj] = refObjects [obj] + 
refsToRoot;
                                return;
+                       }
 
                        RefCount++;
                        
-                       refObjects.Add (obj, obj);
+                       refObjects.Add (obj, refsToRoot);
                        TotalMemory += map.GetObjectSize (obj);
                }
                
@@ -138,18 +137,19 @@
                                }
                                
                                references = new ArrayList ();
-                               foreach (int obj in refObjects.Keys) {
+                               foreach (KeyValuePair<int,int> entry in 
refObjects) {
+                                       int obj = entry.Key;
                                        if (inverse) {
                                                foreach (int oref in 
map.GetReferencers (obj)) {
                                                        ReferenceNode cnode = 
GetReferenceNode (oref);
                                                        string fname = 
map.GetReferencerField (oref, obj);
-                                                       cnode.AddReference 
(obj, oref, fname);
+                                                       cnode.AddReference 
(obj, oref, entry.Value, fname);
                                                }
                                        } else {
                                                foreach (int oref in 
map.GetReferences (obj)) {
                                                        ReferenceNode cnode = 
GetReferenceNode (oref);
                                                        string fname = 
map.GetReferencerField (obj, oref);
-                                                       cnode.AddReference 
(obj, oref, fname);
+                                                       cnode.AddReference 
(obj, oref, 0, fname);
                                                }
                                        }
                                }

Modified: trunk/heap-shot/profiler/heap-shot.c
===================================================================
--- trunk/heap-shot/profiler/heap-shot.c        2006-11-22 17:16:43 UTC (rev 
68355)
+++ trunk/heap-shot/profiler/heap-shot.c        2006-11-22 17:38:12 UTC (rev 
68356)
@@ -123,43 +123,49 @@
 static gboolean
 heap_scan_object (MonoProfiler *p, MonoObject *obj, MonoClass *klass, 
MonoClassField *parent_field)
 {
-       gpointer iter = NULL;
+       gpointer iter;
        MonoClassField *field;
        gboolean has_refs = FALSE;
+       MonoClass *cur_klass = klass;
 
-       while ((field = mono_class_get_fields (klass, &iter)) != NULL) {
-               MonoType* field_type = mono_field_get_type (field);
-               // Skip static fields
-               if (mono_field_get_flags (field) & 0x0010 
/*FIELD_ATTRIBUTE_STATIC*/)
-                       continue;
+       do {
+               iter = NULL;
+               while ((field = mono_class_get_fields (cur_klass, &iter)) != 
NULL) {
+                       MonoType* field_type = mono_field_get_type (field);
+                       // Skip static fields
+                       if (mono_field_get_flags (field) & 0x0010 
/*FIELD_ATTRIBUTE_STATIC*/)
+                               continue;
 
-               if (MONO_TYPE_IS_REFERENCE (field_type)) {
-                       // Dump the object reference
-                       MonoObject* ref;
-                       has_refs = TRUE;
-                       mono_field_get_value (obj, field, &ref);
-                       if (ref && g_hash_table_lookup (p->work_objects_hash, 
ref))
-                               outfile_writer_dump_object_add_reference 
(p->dumpfile_writer, ref, parent_field);
-               }
-               else {
-                       MonoClass *fclass = mono_class_from_mono_type 
(field_type);
-                       if (fclass && mono_class_is_valuetype (fclass)) {
-                               if (g_hash_table_lookup (p->exclude_class_hash, 
fclass))
-                                       continue;
-                               // It's a value type. Check if the class is big 
enough to hold references
-                               int size = mono_class_value_size (fclass, NULL);
-                               if (size >= sizeof(gpointer) && fclass != 
klass) {
-                                       // Get the object value and scan it
-                                       char* vop = g_malloc (size);
-                                       mono_field_get_value (obj, field, vop);
-                                       // Recursively scan the object
-                                       if (heap_scan_object (p, 
(MonoObject*)(vop - sizeof(MonoObject)), fclass, parent_field))
-                                               has_refs = TRUE;
-                                       g_free (vop);
+                       if (MONO_TYPE_IS_REFERENCE (field_type)) {
+                               // Dump the object reference
+                               MonoObject* ref;
+                               has_refs = TRUE;
+                               mono_field_get_value (obj, field, &ref);
+                               if (ref && g_hash_table_lookup 
(p->work_objects_hash, ref))
+                                       
outfile_writer_dump_object_add_reference (p->dumpfile_writer, ref, parent_field 
? parent_field : field);
+                       }
+                       else {
+                               MonoClass *fclass = mono_class_from_mono_type 
(field_type);
+                               if (fclass && mono_class_is_valuetype (fclass)) 
{
+                                       if (g_hash_table_lookup 
(p->exclude_class_hash, fclass))
+                                               continue;
+                                       // It's a value type. Check if the 
class is big enough to hold references
+                                       int size = mono_class_value_size 
(fclass, NULL);
+                                       if (size >= sizeof(gpointer) && fclass 
!= cur_klass) {
+                                               // Get the object value and 
scan it
+                                               char* vop = g_malloc (size);
+                                               mono_field_get_value (obj, 
field, vop);
+                                               // Recursively scan the object
+                                               if (heap_scan_object (p, 
(MonoObject*)(vop - sizeof(MonoObject)), fclass, parent_field))
+                                                       has_refs = TRUE;
+                                               g_free (vop);
+                                       }
                                }
                        }
                }
-       }
+               cur_klass = mono_class_get_parent (cur_klass);
+       } while (cur_klass);
+       
        // If the class doesn't contain references, register in the 
exclude_class_hash table,
        // so it won't be scanned again.
        if (!has_refs && !g_hash_table_lookup (p->exclude_class_hash, klass))

Modified: trunk/heap-shot/profiler/outfile-writer.c
===================================================================
--- trunk/heap-shot/profiler/outfile-writer.c   2006-11-22 17:16:43 UTC (rev 
68355)
+++ trunk/heap-shot/profiler/outfile-writer.c   2006-11-22 17:38:12 UTC (rev 
68356)
@@ -131,7 +131,8 @@
         /* First, add this type if we haven't seen it before. */
         if (g_hash_table_lookup (ofw->seen_items, klass) == NULL) {
                                MonoClassField *field;
-                               gpointer iter = NULL;
+                       MonoClass *cur_klass = klass;
+                               gpointer iter;
                                
                 name = mono_type_full_name (mono_class_get_type (klass));
                 write_byte (ofw->out, TAG_TYPE);
@@ -142,11 +143,15 @@
                 ++ofw->type_count;
                 
                 // Write every field
-                               while ((field = mono_class_get_fields (klass, 
&iter)) != NULL) {
-                       write_pointer (ofw->out, field);
-                       write_string (ofw->out, mono_field_get_name (field));
-                       ofw->field_count++;
-                               }
+                do {
+                       iter = NULL;
+                                       while ((field = mono_class_get_fields 
(cur_klass, &iter)) != NULL) {
+                               write_pointer (ofw->out, field);
+                               write_string (ofw->out, mono_field_get_name 
(field));
+                               ofw->field_count++;
+                                       }
+                                       cur_klass = mono_class_get_parent 
(cur_klass);
+                               } while (cur_klass);
                 write_pointer (ofw->out, NULL);
         }
         write_byte (ofw->out, TAG_OBJECT);

_______________________________________________
Mono-patches maillist  -  [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches

Reply via email to