sysperfana/heapanalyser/Libraries/Engine/HeapLib/Cells/HeapCell.cs
changeset 8 15296fd0af4a
equal deleted inserted replaced
7:8e12a575a9b5 8:15296fd0af4a
       
     1 /*
       
     2 * Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 *
       
     5 * Redistribution and use in source and binary forms, with or without
       
     6 * modification, are permitted provided that the following conditions are met:
       
     7 *
       
     8 * - Redistributions of source code must retain the above copyright notice,
       
     9 *   this list of conditions and the following disclaimer.
       
    10 * - Redistributions in binary form must reproduce the above copyright notice,
       
    11 *   this list of conditions and the following disclaimer in the documentation
       
    12 *   and/or other materials provided with the distribution.
       
    13 * - Neither the name of Nokia Corporation nor the names of its contributors
       
    14 *   may be used to endorse or promote products derived from this software
       
    15 *   without specific prior written permission.
       
    16 *
       
    17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
       
    18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
       
    19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
       
    20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
       
    21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
       
    22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
       
    23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
       
    24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
       
    25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
       
    26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
       
    27 * POSSIBILITY OF SUCH DAMAGE.
       
    28 * 
       
    29 * Initial Contributors:
       
    30 * Nokia Corporation - initial contribution.
       
    31 *
       
    32 * Contributors:
       
    33 *
       
    34 * Description: 
       
    35 *
       
    36 */
       
    37 
       
    38 using System;
       
    39 using System.Collections;
       
    40 using System.Collections.Generic;
       
    41 using System.Text;
       
    42 using SymbianStructuresLib.Debug.Symbols;
       
    43 using SymbianUtils.RawItems;
       
    44 using SymbianUtils.Utilities;
       
    45 using HeapLib.Array;
       
    46 using HeapLib.Relationships;
       
    47 using HeapLib.Cells.Descriptors;
       
    48 
       
    49 namespace HeapLib.Cells
       
    50 {
       
    51     public class HeapCell : IEnumerable<RawItem>, IEquatable<HeapCell>
       
    52     {
       
    53         #region Enumerations
       
    54         public enum TRegion
       
    55         {
       
    56             EHeader = 0,
       
    57             EPayload,
       
    58             EBeforeCell,
       
    59             EAfterCell
       
    60         }
       
    61 
       
    62         public enum TType : byte
       
    63         {
       
    64             EAllocated = 0,
       
    65             EFree
       
    66         }
       
    67 
       
    68         public enum TBuildType
       
    69         {
       
    70             ERelease = 0,
       
    71             EDebug = 1
       
    72         }
       
    73 
       
    74         public enum TDescriptorType
       
    75         {
       
    76             // These are Symbian's descriptor types
       
    77             EBufC = 0,
       
    78             EPtrC,
       
    79             EPtr,
       
    80             EBuf,
       
    81             EBufCPtr,
       
    82 
       
    83             // This are specific to this app
       
    84             ENullTerminatedString,
       
    85             EUnknown,
       
    86         }
       
    87         #endregion
       
    88 
       
    89         #region Constructors & destructor
       
    90         public HeapCell()
       
    91         {
       
    92             iRelationshipManager = new RelationshipManager(this);
       
    93         }
       
    94 
       
    95         internal HeapCell(HeapCell aCell)
       
    96             : this()
       
    97         {
       
    98             iTag = aCell.Tag;
       
    99             iAddress = aCell.Address;
       
   100             iType = aCell.Type;
       
   101             iFlags = aCell.iFlags;
       
   102             iSymbol[0] = aCell.iSymbol[0];
       
   103             iSymbol[1] = aCell.iSymbol[1];
       
   104             iSymbol[2] = aCell.iSymbol[2];
       
   105             iRawItems = aCell.iRawItems;
       
   106             iDescriptorInfo = aCell.iDescriptorInfo;
       
   107             iHeaderRawItems = aCell.iHeaderRawItems;
       
   108             iLength = aCell.iLength;
       
   109             //
       
   110             iRelationshipManager = aCell.RelationshipManager;
       
   111             iChecksum = new CRC32Checksum(aCell.Checksum);
       
   112         }
       
   113 
       
   114         internal HeapCell(uint aAddress, uint aLength, TType aType)
       
   115             : this()
       
   116         {
       
   117             iAddress = aAddress;
       
   118             iType = aType;
       
   119             //
       
   120             iHeaderRawItems.Clear();
       
   121             AddRawItemHeader(new RawItem(aAddress, aLength));
       
   122         }
       
   123         #endregion
       
   124 
       
   125         #region Constants
       
   126         public const uint KHeapCellSizeAllocatedUREL = 4;   // Just length
       
   127         public const uint KHeapCellSizeAllocatedUDEB = 12;  // Length + Allocation Number + Nesting Level
       
   128         public const uint KHeapCellSizeFree = 8;            // Length + Pointer to next free cell
       
   129         #endregion
       
   130 
       
   131         #region API
       
   132         public void AddRawItem(RawItem aItem)
       
   133         {
       
   134             RawItems.Add(aItem);
       
   135             //
       
   136             byte[] dataArray = aItem.DataArray;
       
   137             iChecksum.Checksum(dataArray);
       
   138         }
       
   139 
       
   140         public void AddRawItemHeader(RawItem aItem)
       
   141         {
       
   142             // Not checksummed
       
   143             iHeaderRawItems.Add(aItem);
       
   144             if (iHeaderRawItems.Count == 1)
       
   145             {
       
   146                 iLength = iHeaderRawItems[0].Data;
       
   147             }
       
   148         }
       
   149 
       
   150         public uint Remainder(uint aAddress)
       
   151         {
       
   152             uint ret = (Address + Length) - aAddress;
       
   153             return ret;
       
   154         }
       
   155 
       
   156         public static uint CellHeaderSize(TType aType)
       
   157         {
       
   158             uint ret = AllocatedCellHeaderSize;
       
   159             if (aType == TType.EFree)
       
   160             {
       
   161                 ret = FreeCellHeaderSize;
       
   162             }
       
   163             return ret;
       
   164         }
       
   165 
       
   166         public static uint AllocatedCellSizeByBuildType(TBuildType aType)
       
   167         {
       
   168             uint size = 0;
       
   169             //
       
   170             switch (aType)
       
   171             {
       
   172                 case TBuildType.EDebug:
       
   173                     size = KHeapCellSizeAllocatedUDEB;
       
   174                     break;
       
   175                 case TBuildType.ERelease:
       
   176                     size = KHeapCellSizeAllocatedUREL;
       
   177                     break;
       
   178             }
       
   179             //
       
   180             return size;
       
   181         }
       
   182 
       
   183         public TRegion RegionForAddress(uint aAddress)
       
   184         {
       
   185             uint address = Address;
       
   186             //
       
   187             TRegion ret = TRegion.EBeforeCell;
       
   188             //
       
   189             if (aAddress < address)
       
   190             {
       
   191                 ret = TRegion.EBeforeCell;
       
   192             }
       
   193             else
       
   194             {
       
   195                 uint endAddress = EndAddress;
       
   196                 //
       
   197                 if (aAddress > endAddress)
       
   198                 {
       
   199                     ret = TRegion.EAfterCell;
       
   200                 }
       
   201                 else
       
   202                 {
       
   203                     uint startOfPayload = StartOfPayloadAddress;
       
   204                     //
       
   205                     if (aAddress >= startOfPayload)
       
   206                     {
       
   207                         ret = TRegion.EPayload;
       
   208                     }
       
   209                     else
       
   210                     {
       
   211                         ret = TRegion.EHeader;
       
   212                     }
       
   213                 }
       
   214             }
       
   215             //
       
   216             return ret;
       
   217         }
       
   218 
       
   219         public TRegion RegionForAddress(uint aAddress, out int aRemainingUntilNextBoundary)
       
   220         {
       
   221             TRegion region = RegionForAddress(aAddress);
       
   222             //
       
   223             switch (region)
       
   224             {
       
   225                 default:
       
   226                     aRemainingUntilNextBoundary = -1;
       
   227                     break;
       
   228                 case TRegion.EHeader:
       
   229                 case TRegion.EPayload:
       
   230                     if (region == TRegion.EHeader)
       
   231                     {
       
   232                         uint startOfPayload = StartOfPayloadAddress;
       
   233                         aRemainingUntilNextBoundary = (int)(startOfPayload - aAddress);
       
   234                     }
       
   235                     else
       
   236                     {
       
   237                         uint endAddress = EndAddress;
       
   238                         aRemainingUntilNextBoundary = (int)(endAddress - aAddress + 1);
       
   239                     }
       
   240                     break;
       
   241             }
       
   242             //
       
   243             return region;
       
   244         }
       
   245 
       
   246         public bool IsIdentical(HeapCell aCell)
       
   247         {
       
   248             bool identical = false;
       
   249             //
       
   250             if (aCell.Length == this.Length &&
       
   251                  aCell.PossibleVTableAddress == this.PossibleVTableAddress &&
       
   252                  aCell.AllocationNumber == this.AllocationNumber &&
       
   253                  aCell.NestingLevel == this.NestingLevel &&
       
   254                  aCell.RawItems.Count == this.RawItems.Count)
       
   255             {
       
   256                 identical = (aCell.Checksum == this.Checksum);
       
   257             }
       
   258             //
       
   259             return identical;
       
   260         }
       
   261 
       
   262         internal void ConstructionComplete(Statistics.HeapStatistics aStats)
       
   263         {
       
   264             if (Type == TType.EAllocated)
       
   265             {
       
   266                 iDescriptorInfo = Descriptors.DescriptorAlgorithmManager.DescriptorInfo(this, aStats);
       
   267             }
       
   268         }
       
   269         #endregion
       
   270 
       
   271         #region Properties
       
   272         public HeapCell.TType Type
       
   273         {
       
   274             get { return iType; }
       
   275             set { iType = value; }
       
   276         }
       
   277 
       
   278         public string TypeString
       
   279         {
       
   280             get
       
   281             {
       
   282                 string ret = string.Empty;
       
   283                 //
       
   284                 switch (Type)
       
   285                 {
       
   286                     case TType.EAllocated:
       
   287                         ret = "Allocated";
       
   288                         break;
       
   289                     case TType.EFree:
       
   290                         ret = "Free";
       
   291                         break;
       
   292                 }
       
   293                 //
       
   294                 return ret;
       
   295             }
       
   296         }
       
   297 
       
   298         // <summary>
       
   299         // The index is the unique number assigned to each cell as it is
       
   300         // added to the heap data for a given heap. This operation is 
       
   301         // performed by the reconstructor during parsing.
       
   302         // </summary>
       
   303         public uint Index
       
   304         {
       
   305             get { return iIndex; }
       
   306             set { iIndex = value; }
       
   307         }
       
   308 
       
   309         public uint Address
       
   310         {
       
   311             get { return iAddress; }
       
   312             set { iAddress = value; }
       
   313         }
       
   314 
       
   315         public uint StartOfPayloadAddress
       
   316         {
       
   317             get
       
   318             {
       
   319                 uint ret = Address;
       
   320                 //
       
   321                 if (Type == TType.EAllocated)
       
   322                 {
       
   323                     ret += HeaderSize;
       
   324                 }
       
   325                 else if (Type == TType.EFree)
       
   326                 {
       
   327                     ret += KHeapCellSizeFree;
       
   328                 }
       
   329                 else
       
   330                 {
       
   331                     System.Diagnostics.Debug.Assert(false);
       
   332                 }
       
   333                 //
       
   334                 return ret;
       
   335             }
       
   336         }
       
   337 
       
   338         public uint EndAddress
       
   339         {
       
   340             get { return iAddress + iLength - 1; }
       
   341         }
       
   342 
       
   343         public uint Length
       
   344         {
       
   345             // Optimisation: we cache the length when adding the first
       
   346             // header raw item to avoid having to repeatedly access
       
   347             // the raw items array during initial heap preparation.
       
   348             get { return iLength; }
       
   349         }
       
   350 
       
   351         public uint NestingLevel
       
   352         {
       
   353             get
       
   354             {
       
   355                 // Only applicable to allocated cells in debug builds
       
   356                 uint ret = 0;
       
   357                 //
       
   358                 if (Type == TType.EAllocated && IsDebugAllocator)
       
   359                 {
       
   360                     System.Diagnostics.Debug.Assert(HeaderRawItems.Count >= 2);
       
   361                     RawItem item = HeaderRawItems[1]; // Always 2nd raw item in header
       
   362                     ret = item.Data;
       
   363                 }
       
   364                 //
       
   365                 return ret;
       
   366             }
       
   367         }
       
   368 
       
   369         public uint AllocationNumber
       
   370         {
       
   371             get
       
   372             {
       
   373                 // Only applicable to allocated cells in debug builds
       
   374                 uint ret = 0;
       
   375                 //
       
   376                 if (Type == TType.EAllocated && IsDebugAllocator)
       
   377                 {
       
   378                     System.Diagnostics.Debug.Assert(HeaderRawItems.Count >= 3);
       
   379                     RawItem item = HeaderRawItems[2]; // Always 3rd raw item in header
       
   380                     ret = item.Data;
       
   381                 }
       
   382                 //
       
   383                 return ret;
       
   384             }
       
   385         }
       
   386 
       
   387         public uint PossibleVTableAddress
       
   388         {
       
   389             get
       
   390             {
       
   391                 // This is always the first raw item
       
   392                 uint ret = 0;
       
   393                 //
       
   394                 if (RawItems.Count > 0)
       
   395                 {
       
   396                     ret = RawItems[0].Data;
       
   397                 }
       
   398                 //
       
   399                 return ret;
       
   400             }
       
   401         }
       
   402 
       
   403         public Symbol Symbol
       
   404         {
       
   405             get { return iSymbol[0]; }
       
   406             set { iSymbol[0] = value; }
       
   407         }
       
   408 
       
   409         public Symbol Symbol2
       
   410         {
       
   411             get { return iSymbol[1]; }
       
   412             set { iSymbol[1] = value; }
       
   413         }
       
   414 
       
   415         public Symbol Symbol3
       
   416         {
       
   417             get { return iSymbol[2]; }
       
   418             set { iSymbol[2] = value; }
       
   419         }
       
   420 
       
   421         public string SymbolString
       
   422         {
       
   423             get
       
   424             {
       
   425                 return SymbolStringRef(false);
       
   426             }
       
   427         }
       
   428 
       
   429         private string SymbolStringRef(bool reference)
       
   430         {
       
   431             StringBuilder ret = new StringBuilder();
       
   432 
       
   433             if (Type == TType.EAllocated)
       
   434             {
       
   435                 if (Symbol != null)
       
   436                 {
       
   437                     ret.Append(Symbol.NameWithoutVTablePrefix);
       
   438                 }
       
   439                 else if (IsDescriptor)
       
   440                 {
       
   441                     ret.Append("[Descriptor] " + DescriptorTextBeautified);
       
   442                 }
       
   443             }
       
   444             else if (Type == TType.EFree)
       
   445             {
       
   446                 ret.Append("[Free]");
       
   447                 if (Symbol != null)
       
   448                 {
       
   449                     ret.Append(" ");
       
   450                     ret.Append(Symbol.NameWithoutVTablePrefix);
       
   451                 }
       
   452             }
       
   453 
       
   454             // If no text as yet identified, then return [Unknown], if there is not unique referrer.
       
   455             // If the referrer is unique, or if all referrers are of the same known type,
       
   456             // instead of [Unknown], you can see [Part of XXX], where XXX is the type of the referrer. 
       
   457             if (ret.Length == 0)
       
   458             {
       
   459                 if (!reference)
       
   460                 {
       
   461                     if (iRelationshipManager.ReferencedByUnique != null)
       
   462                     {
       
   463                         string symbolString = iRelationshipManager.ReferencedByUnique.SymbolStringRef(true);
       
   464 
       
   465                         if (!symbolString.Equals("[Unknown]"))
       
   466                         {
       
   467                             ret.Append("[Part of ");
       
   468                             ret.Append(symbolString);
       
   469                             ret.Append("]");
       
   470                         }
       
   471                         else
       
   472                         {
       
   473                             ret.Append("[Unknown]");
       
   474                         }
       
   475                     }
       
   476                     else
       
   477                     {
       
   478                         ret.Append("[Unknown]");
       
   479                     }
       
   480                 }
       
   481                 else
       
   482                 {
       
   483                     ret.Append("[Unknown]");
       
   484                 }
       
   485             }
       
   486             return ret.ToString();
       
   487         }
       
   488 
       
   489         public string SymbolStringWithoutDescriptorPrefix
       
   490         {
       
   491             get
       
   492             {
       
   493                 string ret = SymbolString;
       
   494                 //
       
   495                 if (IsDescriptor)
       
   496                 {
       
   497                     ret = "[" + DescriptorLength.ToString("d4") + "] " + DescriptorTextBeautifiedWithoutLength;
       
   498                 }
       
   499                 //
       
   500                 return ret;
       
   501             }
       
   502         }
       
   503 
       
   504         public uint HeaderSize
       
   505         {
       
   506             get
       
   507             {
       
   508                 uint size = 0;
       
   509                 //
       
   510                 switch (Type)
       
   511                 {
       
   512                     case TType.EAllocated:
       
   513                         size = HeapCell.AllocatedCellHeaderSize;
       
   514                         break;
       
   515                     case TType.EFree:
       
   516                         size = KHeapCellSizeFree;
       
   517                         break;
       
   518                 }
       
   519                 //
       
   520                 return size;
       
   521             }
       
   522         }
       
   523 
       
   524         public uint PayloadLength
       
   525         {
       
   526             get { return (EndAddress - StartOfPayloadAddress) + 1; }
       
   527         }
       
   528 
       
   529         public RawItem this[uint aAddress]
       
   530         {
       
   531             get
       
   532             {
       
   533                 RawItem ret = null;
       
   534                 //
       
   535                 TRegion region = RegionForAddress(aAddress);
       
   536                 if (region == TRegion.EPayload || region == TRegion.EHeader)
       
   537                 {
       
   538                     if (region == TRegion.EHeader)
       
   539                     {
       
   540                         uint offset = aAddress - Address;
       
   541                         int index = System.Convert.ToInt32(offset / RawItem.KSizeOfOneRawItemInBytes);
       
   542                         //
       
   543                         if (index < 0 || index >= HeaderRawItems.Count)
       
   544                         {
       
   545                             throw new ArgumentException("Address 0x" + aAddress.ToString("x8") + " is beyond this cell's header");
       
   546                         }
       
   547                         //
       
   548                         ret = HeaderRawItems[index];
       
   549                     }
       
   550                     else
       
   551                     {
       
   552                         // Payload
       
   553                         uint offset = aAddress - StartOfPayloadAddress;
       
   554                         int index = System.Convert.ToInt32(offset / RawItem.KSizeOfOneRawItemInBytes);
       
   555                         //
       
   556                         if (index < 0 || index >= RawItems.Count)
       
   557                         {
       
   558                             throw new ArgumentException("Address 0x" + aAddress.ToString("x8") + " is beyond this cell's payload");
       
   559                         }
       
   560                         //
       
   561                         ret = this[index];
       
   562                     }
       
   563                 }
       
   564                 else
       
   565                 {
       
   566                     throw new ArgumentException("Address 0x" + aAddress.ToString("x8") + " is not within this cell's extent");
       
   567                 }
       
   568                 return ret;
       
   569             }
       
   570         }
       
   571 
       
   572         public RawItem this[int aIndex]
       
   573         {
       
   574             get
       
   575             {
       
   576                 return iRawItems[aIndex];
       
   577             }
       
   578         }
       
   579 
       
   580         public RawItemCollection RawItems
       
   581         {
       
   582             get { return iRawItems; }
       
   583         }
       
   584 
       
   585         public RawItemCollection HeaderRawItems
       
   586         {
       
   587             get { return iHeaderRawItems; }
       
   588         }
       
   589 
       
   590         public long CombinedLinkedCellPayloadLengths
       
   591         {
       
   592             get
       
   593             {
       
   594                 int depth = 0;
       
   595                 long ret = DoGetCombinedLinkedCellPayloadLengths(ref depth);
       
   596                 return ret;
       
   597             }
       
   598         }
       
   599 
       
   600         public long PayloadLengthIncludingLinkedCells
       
   601         {
       
   602             get
       
   603             {
       
   604                 long ret = PayloadLength;
       
   605                 ret += RelationshipManager.PayloadLengthOfEmbeddedCells;
       
   606                 //
       
   607                 return ret;
       
   608             }
       
   609         }
       
   610 
       
   611         public object Tag
       
   612         {
       
   613             get { return iTag; }
       
   614             set { iTag = value; }
       
   615         }
       
   616 
       
   617         public uint Checksum
       
   618         {
       
   619             get { return iChecksum.Value; }
       
   620         }
       
   621 
       
   622         public bool IsUnknown
       
   623         {
       
   624             get { return Symbol == null && Type == TType.EAllocated; }
       
   625         }
       
   626         #endregion
       
   627 
       
   628         #region Descriptor related functionality
       
   629         public TDescriptorType DescriptorType
       
   630         {
       
   631             get
       
   632             {
       
   633                 TDescriptorType ret = TDescriptorType.EUnknown;
       
   634                 //
       
   635                 if (IsDescriptor && iDescriptorInfo != null)
       
   636                 {
       
   637                     ret = iDescriptorInfo.Type;
       
   638                 }
       
   639                 //
       
   640                 return ret;
       
   641             }
       
   642         }
       
   643 
       
   644         public bool IsDescriptorUnicode
       
   645         {
       
   646             get
       
   647             {
       
   648                 bool ret = false;
       
   649                 //
       
   650                 if (IsDescriptor && iDescriptorInfo != null)
       
   651                 {
       
   652                     ret = iDescriptorInfo.IsUnicode;
       
   653                 }
       
   654                 //
       
   655                 return ret;
       
   656             }
       
   657         }
       
   658 
       
   659         public bool IsDescriptor
       
   660         {
       
   661             get
       
   662             {
       
   663                 return (iDescriptorInfo != null);
       
   664             }
       
   665         }
       
   666 
       
   667         public int DescriptorLength
       
   668         {
       
   669             get
       
   670             {
       
   671                 int length = 0;
       
   672                 //
       
   673                 if (IsDescriptor && iDescriptorInfo != null)
       
   674                 {
       
   675                     length = iDescriptorInfo.Length;
       
   676                 }
       
   677                 //
       
   678                 return length;
       
   679             }
       
   680         }
       
   681 
       
   682         public string DescriptorText
       
   683         {
       
   684             get
       
   685             {
       
   686                 string ret = string.Empty;
       
   687                 //
       
   688                 if (IsDescriptor && iDescriptorInfo != null)
       
   689                 {
       
   690                     ret = iDescriptorInfo.Text;
       
   691                 }
       
   692                 //
       
   693                 return ret;
       
   694             }
       
   695         }
       
   696 
       
   697         public string DescriptorTextBeautifiedWithoutLength
       
   698         {
       
   699             get
       
   700             {
       
   701                 StringBuilder ret = new StringBuilder();
       
   702                 //
       
   703                 string des = DescriptorText;
       
   704                 if (des.Length > KMaxSymbolStringDescriptorLength)
       
   705                 {
       
   706                     ret.Append(" \"");
       
   707                     ret.Append(des.Substring(0, KMaxSymbolStringDescriptorLength));
       
   708                     ret.Append("...\"");
       
   709                 }
       
   710                 else
       
   711                 {
       
   712                     ret.Append(" \"");
       
   713                     ret.Append(des);
       
   714                     ret.Append("\"");
       
   715                 }
       
   716                 //
       
   717                 return ret.ToString();
       
   718             }
       
   719         }
       
   720 
       
   721         public string DescriptorTextBeautified
       
   722         {
       
   723             get
       
   724             {
       
   725                 StringBuilder ret = new StringBuilder();
       
   726                 //
       
   727                 ret.Append("{");
       
   728                 ret.Append(DescriptorLength.ToString("d4"));
       
   729                 ret.Append("}");
       
   730                 //
       
   731                 ret.Append(DescriptorTextBeautifiedWithoutLength);
       
   732                 //
       
   733                 return ret.ToString();
       
   734             }
       
   735         }
       
   736         #endregion
       
   737 
       
   738         #region Static properties
       
   739         public static bool IsDebugAllocator
       
   740         {
       
   741             get
       
   742             {
       
   743                 return AllocatedCellHeaderSize == AllocatedCellSizeByBuildType(TBuildType.EDebug);
       
   744             }
       
   745         }
       
   746 
       
   747         public static uint FreeCellHeaderSize
       
   748         {
       
   749             get { return KFreeCellHeaderSize; }
       
   750         }
       
   751 
       
   752         public static uint AllocatedCellHeaderSize
       
   753         {
       
   754             get { return iAllocatedCellHeaderSize; }
       
   755             set { iAllocatedCellHeaderSize = value; }
       
   756         }
       
   757         #endregion
       
   758 
       
   759         #region Relationships
       
   760         public RelationshipManager RelationshipManager
       
   761         {
       
   762             get { return iRelationshipManager; }
       
   763         }
       
   764         #endregion
       
   765 
       
   766         #region IEnumerable Members
       
   767         IEnumerator IEnumerable.GetEnumerator()
       
   768         {
       
   769             return new HeapCellRawItemEnumerator(this);
       
   770         }
       
   771 
       
   772         IEnumerator<RawItem> IEnumerable<RawItem>.GetEnumerator()
       
   773         {
       
   774             return new HeapCellRawItemEnumerator(this);
       
   775         }
       
   776         #endregion
       
   777 
       
   778         #region IEquatable<HeapCell> Members
       
   779         public bool Equals(HeapCell aOther)
       
   780         {
       
   781             bool ret = (aOther.Address == this.Address);
       
   782             return ret;
       
   783         }
       
   784         #endregion
       
   785 
       
   786         #region Operators
       
   787         public static bool operator ==(HeapCell aLeft, HeapCell aRight)
       
   788         {
       
   789             bool ret = false;
       
   790 
       
   791             // If both are null, or both are same instance, return true.
       
   792             if (System.Object.ReferenceEquals(aLeft, aRight))
       
   793             {
       
   794                 ret = true;
       
   795             }
       
   796             else if (((object)aLeft == null) || ((object)aRight == null))
       
   797             {
       
   798                 // If one is null, but not both, return false.
       
   799                 ret = false;
       
   800             }
       
   801             else
       
   802             {
       
   803                 // Return true if the fields match:
       
   804                 ret = (aLeft.Address == aRight.Address);
       
   805             }
       
   806             //
       
   807             return ret;
       
   808         }
       
   809 
       
   810         public static bool operator !=(HeapCell aLeft, HeapCell aRight)
       
   811         {
       
   812             return !(aLeft == aRight);
       
   813         }
       
   814         #endregion
       
   815 
       
   816         #region From System.Object
       
   817         public override int GetHashCode()
       
   818         {
       
   819             return Address.GetHashCode();
       
   820         }
       
   821 
       
   822         public override bool Equals(object aObject)
       
   823         {
       
   824             bool ret = false;
       
   825             //
       
   826             if (aObject is HeapCell)
       
   827             {
       
   828                 HeapCell otherCell = (HeapCell)aObject;
       
   829                 ret = Equals(otherCell);
       
   830             }
       
   831             //
       
   832             return ret;
       
   833         }
       
   834 
       
   835         public override string ToString()
       
   836         {
       
   837             string ret = "[0x" + Address.ToString("x8") + " " + TypeString + "]";
       
   838             return ret;
       
   839         }
       
   840 
       
   841         public string ToStringExtended()
       
   842         {
       
   843             StringBuilder ret = new StringBuilder();
       
   844 
       
   845             // Type
       
   846             if (Type == HeapCell.TType.EAllocated)
       
   847             {
       
   848                 if (IsDescriptor)
       
   849                 {
       
   850                     ret.Append("[D]");
       
   851                 }
       
   852                 else
       
   853                 {
       
   854                     ret.Append("[A]");
       
   855                 }
       
   856             }
       
   857             else
       
   858             {
       
   859                 ret.Append("[F]");
       
   860             }
       
   861 
       
   862             // Address
       
   863             ret.Append(" 0x" + Address.ToString("x8"));
       
   864 
       
   865             // Symbol (if present)
       
   866             if (Symbol != null)
       
   867             {
       
   868                 ret.Append(" - " + SymbolString);
       
   869             }
       
   870             else if (IsDescriptor)
       
   871             {
       
   872                 ret.Append(" - " + DescriptorTextBeautified);
       
   873             }
       
   874 
       
   875             return ret.ToString();
       
   876         }
       
   877         #endregion
       
   878 
       
   879         #region Internal flags
       
   880         [Flags]
       
   881         private enum TFlags
       
   882         {
       
   883             EFlagsNone = 0,
       
   884             EFlagsInCombiningCheck = 1
       
   885         }
       
   886         #endregion
       
   887 
       
   888         #region Internal constants
       
   889         private const int KMaxRecursiveLinkedCellDepth = 5; // levels
       
   890         private const int KMaxSymbolStringDescriptorLength = 128;
       
   891         private const int KFreeCellHeaderSize = 8; // always
       
   892         #endregion
       
   893 
       
   894         #region Internal methods
       
   895         private long DoGetCombinedLinkedCellPayloadLengths(ref int aDepth)
       
   896         {
       
   897             long ret = PayloadLength;
       
   898             //
       
   899             if (aDepth <= KMaxRecursiveLinkedCellDepth)
       
   900             {
       
   901                 iFlags |= TFlags.EFlagsInCombiningCheck;
       
   902                 //
       
   903                 foreach (RelationshipInfo relInfo in RelationshipManager.EmbeddedReferencesTo)
       
   904                 {
       
   905                     HeapCell linkedCell = relInfo.ToCell;
       
   906                     bool isInLinkCheck = ((linkedCell.iFlags & TFlags.EFlagsInCombiningCheck) == TFlags.EFlagsInCombiningCheck);
       
   907                     if (isInLinkCheck == false)
       
   908                     {
       
   909                         ++aDepth;
       
   910                         ret += linkedCell.DoGetCombinedLinkedCellPayloadLengths(ref aDepth);
       
   911                     }
       
   912                     else
       
   913                     {
       
   914                     }
       
   915                 }
       
   916                 //
       
   917                 iFlags &= ~TFlags.EFlagsInCombiningCheck;
       
   918             }
       
   919             //
       
   920             return ret;
       
   921         }
       
   922         #endregion
       
   923 
       
   924         #region Data members
       
   925         private static uint iAllocatedCellHeaderSize = 0;
       
   926         private object iTag;
       
   927         private uint iIndex;
       
   928         private uint iAddress;
       
   929         private uint iLength;
       
   930         private TType iType = TType.EAllocated;
       
   931         private TFlags iFlags = TFlags.EFlagsNone;
       
   932         private Symbol[] iSymbol = new Symbol[3] { null, null, null };
       
   933         private CRC32Checksum iChecksum = new CRC32Checksum();
       
   934         private DescriptorInfo iDescriptorInfo = null;
       
   935         private RawItemCollection iRawItems = new RawItemCollection();
       
   936         private RawItemCollection iHeaderRawItems = new RawItemCollection();
       
   937         private readonly RelationshipManager iRelationshipManager;
       
   938         #endregion
       
   939     }
       
   940 }