sysperfana/heapanalyser/Libraries/Engine/HeapLib/Relationships/RelationshipInspector.cs
changeset 8 15296fd0af4a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysperfana/heapanalyser/Libraries/Engine/HeapLib/Relationships/RelationshipInspector.cs	Tue Jun 15 12:47:20 2010 +0300
@@ -0,0 +1,180 @@
+/*
+* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*
+* - Redistributions of source code must retain the above copyright notice,
+*   this list of conditions and the following disclaimer.
+* - Redistributions in binary form must reproduce the above copyright notice,
+*   this list of conditions and the following disclaimer in the documentation
+*   and/or other materials provided with the distribution.
+* - Neither the name of Nokia Corporation nor the names of its contributors
+*   may be used to endorse or promote products derived from this software
+*   without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+* POSSIBILITY OF SUCH DAMAGE.
+* 
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+*
+*/
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using HeapLib.Cells;
+using HeapLib.Array;
+using HeapLib.Statistics;
+using SymbianUtils.RawItems;
+using SymbianUtils.TextUtilities.Readers.Types.Array;
+
+namespace HeapLib.Relationships
+{
+    internal class RelationshipInspector : AsyncEnumerableReader<HeapCell>
+	{
+		#region Constructors & destructor
+		public RelationshipInspector( HeapCellArray aEntries, HeapStatistics aStats )
+            : base( null )
+		{
+			iEntries = aEntries;
+            iStats = aStats;
+		}
+		#endregion
+
+		#region API
+		public void InspectLater( HeapCell aCell )
+		{
+            iDictionary.Add( aCell );
+		}
+
+		public void Inspect()
+		{
+            iResultCache.Clear();
+            base.Setup( iDictionary.Count, iDictionary.GetEnumerator() );
+            base.AsyncRead();
+		}
+		#endregion
+
+        #region From AsyncEnumerableReader
+        protected override void HandleObject( HeapCell aObject, long aIndex, long aCount )
+        {
+            CheckForCrossReferences( aObject );
+        }
+
+        protected override void HandleReadCompleted()
+        {
+            iResultCache.Clear();
+            iDictionary.Clear();
+            base.HandleReadCompleted();
+        }
+        #endregion
+
+        #region Internal methods
+        private void CheckForCrossReferences( HeapCell aCell )
+		{
+            // If we're dealing with a free cell, then set up the free cell 
+            // linked list.
+            if ( aCell.Type == HeapCell.TType.EFree && aCell.HeaderRawItems.Count == 2 )
+            {
+                uint length = aCell.HeaderRawItems[ 0 ].Data;
+                uint address = aCell.HeaderRawItems[ 1 ].Data;
+                //
+                LocateMatch( aCell, aCell.HeaderRawItems[ 1 ], 0 );
+            }
+
+            // For all other cells, identify other links
+			foreach( RawItem rawItem in aCell )
+			{
+                uint headerOffset = HeapCell.CellHeaderSize( aCell.Type );
+                LocateMatch( aCell, rawItem, headerOffset );
+			}
+        }
+
+        private void LocateMatch( HeapCell aCell, RawItem aItem, uint aHeaderOffset )
+        {
+            RelationshipManager linkManager = aCell.RelationshipManager;
+
+            // Now check if this address exactly matches a heap cell
+            if ( iStats.WithinHeapBounds( aItem.Data ) )
+            {
+                // The address of another object within the heap
+                // is always the address of the object within the payload
+                // section of a heap cell. Therefore in order to find the
+                // corresponding heap cell address, we must subtract the
+                // heap cell header length from the starting address.
+                //
+                // In other words, the rawItem.Data value points to a payload address.
+                // However, our cell search function (CellByExactAddress) works in 
+                // terms of a heap cell address. The heap cell includes [header + payload].
+                //
+                // In order to convert the object address into a heap cell address,
+                // we must subtract the allocated heap cell header size from the 
+                // raw address.
+                uint exactMatchAddress = aItem.Data - aHeaderOffset;
+
+                HeapCell cell = iEntries.CellByExactAddress( exactMatchAddress );
+                if ( cell != null && cell.Address != aCell.Address )
+                {
+                    linkManager.AddEmbeddedReferenceTo( aItem, cell );
+                }
+                else if ( cell == null )
+                {
+                    uint partialMatchAddress = aItem.Data;
+
+                    // Didn't find an exact match, but we might find that this address
+                    // points to part way through another heap cell.
+                    cell = Lookup( partialMatchAddress );
+                    if ( cell != null && cell.Address != aCell.Address )
+                    {
+                        // It also has to point to the payload
+                        HeapCell.TRegion region = cell.RegionForAddress( partialMatchAddress );
+                        if ( region == HeapCell.TRegion.EPayload )
+                        {
+                            linkManager.AddEmbeddedReferenceTo( aItem, cell );
+                        }
+                    }
+                }
+            }
+        }
+
+        private HeapCell Lookup( uint aAddress )
+        {
+            HeapCell ret = null;
+            //
+            if ( !iResultCache.TryGetValue( aAddress, out ret ) )
+            {
+                ret = iEntries.CellByAddress( aAddress );
+                if ( ret != null )
+                {
+                    iResultCache.Add( aAddress, ret );
+                }
+            }
+            //
+            return ret;
+        }
+		#endregion
+
+        #region Data members
+        private readonly HeapCellArray iEntries;
+        private readonly HeapStatistics iStats;
+        private RelationshipDictionary iDictionary = new RelationshipDictionary();
+        private Dictionary<uint, HeapCell> iResultCache = new Dictionary<uint, HeapCell>();
+		#endregion
+    }
+}