sysperfana/heapanalyser/Libraries/Engine/MemAnalysisLib/MemoryOperations/Functions/Kernel/MemOpFnReallocations.cs
author Matti Laitinen <matti.t.laitinen@nokia.com>
Tue, 15 Jun 2010 12:47:20 +0300
changeset 8 15296fd0af4a
permissions -rw-r--r--
HeapAnalyser 1.1.0

/*
* 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.Text;
using System.Collections;
using System.Collections.Generic;
using MemAnalysisLib.Parser.Prefixes;
using MemAnalysisLib.MemoryOperations.Functions;
using MemAnalysisLib.MemoryOperations.Class;
using MemAnalysisLib.MemoryOperations.Operations;
using MemAnalysisLib.Interfaces;
using SymbianUtils;

namespace MemAnalysisLib.MemoryOperations.Functions.Kernel
{
    internal abstract class MemOpFnKReallocBase : MemOpFnKAllocBase
    {
		#region Constructors & destructor
        protected MemOpFnKReallocBase()
		{
		}
		#endregion

		#region From MemOpFnBase
        public override MemAnalysisLib.MemoryOperations.Class.TClass Class
        {
            get { return TClass.EReallocation; } 
        }

        public override MemOpBase Parse( ref string aLine, MemAnalysisParserPrefixesBase aPrefixes )
        {
            MemOpReallocation ret = new MemOpReallocation();

            // Parse fields
            base.ParseCommonKernel( ret, ref aLine, aPrefixes );
            base.ParseCommonAlloc( ret, ref aLine, aPrefixes );
            ParseCommonRealloc( ret, ref aLine, aPrefixes );

            // Set type
            ret.Function = this;

            return ret;
        }
        #endregion

        #region Internal methods
        protected void ParseCommonRealloc( MemOpReallocation aOperation, ref string aLine, MemAnalysisParserPrefixesBase aPrefixes )
        {
            if ( aLine.IndexOf( aPrefixes.ReallocMode ) >= 0 )
            {
                PrefixParser.SkipPrefix( aPrefixes.ReallocMode, ref aLine );
                aOperation.ReallocationMode = (byte) PrefixParser.ReadLong( ref aLine );
            }
            if ( aLine.IndexOf( aPrefixes.OriginalCellAddress ) >= 0 )
            {
                PrefixParser.SkipPrefix( aPrefixes.OriginalCellAddress, ref aLine );
                aOperation.OriginalAddress = PrefixParser.ReadUint( ref aLine );
            }
            if ( aLine.IndexOf( aPrefixes.OriginalCellSize ) >= 0 )
            {
                PrefixParser.SkipPrefix( aPrefixes.OriginalCellSize, ref aLine );
                aOperation.OriginalAllocationSize = PrefixParser.ReadUint( ref aLine );
            }
            if ( aLine.IndexOf( aPrefixes.OriginalCellAllocNumber ) >= 0 )
            {
                PrefixParser.SkipPrefix( aPrefixes.OriginalCellAllocNumber, ref aLine );
                aOperation.OriginalAllocationNumber = PrefixParser.ReadUint( ref aLine );
            }
        }
        #endregion
    }

    internal class MemOpFnKernReAlloc : MemOpFnKReallocBase
	{
		#region Constructors & destructor
        public MemOpFnKernReAlloc()
		{
		}
		#endregion

		#region From MemOpFnBase
        public override string ToString()
        {
            return base.ToString() + "Kern::ReAlloc";
        }
		#endregion
	}

    internal class MemOpFnKernSafeReAlloc : MemOpFnKReallocBase
	{
		#region Constructors & destructor
        public MemOpFnKernSafeReAlloc()
		{
		}
		#endregion

		#region From MemOpFnBase
        public override string ToString()
        {
            return base.ToString() + "Kern::SafeReAlloc";
        }

        public override void Process( MemOpBase aItem, CollectionManager aCollectionManager )
        {
            if ( aItem.CellAddress == 0xc8099f8c )
            {
                int x = 0;
                x++;
            }

            // (1) Alloc, SafeRealloc
            // 
            // [KMEM] OKA     - C: 0xc801a65c, HS:    29096, HCS:    53128, LR: 0x800b82f4, CS:        4, AS:        4, AN:       93
            // [KMEM] OKSR    - C: 0xc801a65c, HS:    29096, HCS:    53128, LR: 0x800aebdc, AS:        4, AN:       93, OC: 0x00000000, OCS:        0, OCAN:        0, VT: 0x00000000
            // 
            // 
            // (2) Realloc, SafeRealloc
            // [KMEM] OKR     - C: 0xc801ae1c, HS:    33656, HCS:    53128, LR: 0x800b82d4, AS:       12, AN:      106, MD: 1, OC: 0xc801ae1c, OCS:       12, OCAN:      106, VT: 0xc801a688
            // [KMEM] OKSR    - C: 0xc801ae1c, HS:    33656, HCS:    53128, LR: 0x800aebdc, AS:       12, AN:      106, OC: 0xc801ae1c, OCS:       12, OCAN:      106, VT: 0xc801a688
            // ...
            // [KMEM] OKR     - C: 0xc822ee8c, HS:  1672036, HCS:  2236296, LR: 0x800b83c8 [ Kern::SafeReAlloc(void*&, int, int) ], CS:      660, AS:      652, AN:    99936, MD: 0, OC: 0xc822ee8c, OCS:      660, OCAN:    99936, VT: 0xc80131e8
            // [KMEM] OKSR    - C: 0xc822ee8c, HS:  1672036, HCS:  2236296, LR: 0x800adc7c [ DObjectCon::Remove(DObject*) ], CS:      660, AS:      652, AN:    99936, OC: 0xc822ee8c, OCS:      660, OCAN:    99936, VT: 0xc80131e8
            // 
            //
            // (3) Alloc, Free, SafeRealloc
            //
            // [KMEM] OKA     - C: 0xc801a744, HS:    29268, HCS:    53128, LR: 0x800b82f4, CS:        4, AS:        4, AN:       98
            // [KMEM] OKSR    - C: 0xc801a744, HS:    29268, HCS:    53128, LR: 0x800aebdc, AS:        4, AN:       98, OC: 0x00000000, OCS:        0, OCAN:        0, VT: 0x00000000
            // ...
            // [KMEM] OKA     - C: 0xc801ae1c, HS:    30932, HCS:    53128, LR: 0x800b82f4, CS:       12, AS:        8, AN:      106
            // [KMEM] OKF     - C: 0xc801a744, HS:    30928, HCS:    53128, LR: 0x800b836c, CS:        4, AN:       98, VT: 0xc801a688
            // [KMEM] OKSR    - C: 0xc801ae1c, HS:    30928, HCS:    53128, LR: 0x800aebdc, AS:        8, AN:      106, OC: 0xc801a744, OCS:        4, OCAN:       98, VT: 0xc801a688

            MemOpBase lastOpByAllocNumber = aCollectionManager.PriorOperationByAllocationNumber( aItem.AllocationNumber );
            MemOpReallocation op = (MemOpReallocation) aItem;

            if ( lastOpByAllocNumber != null )
            {
                if ( lastOpByAllocNumber.CellAddress == op.CellAddress &&
                     lastOpByAllocNumber.Class == TClass.EAllocation &&
                     op.OriginalAddress == 0 )
                {
                    // 1) Alloc, SafeRealloc => dump alloc
                    aCollectionManager.RemoveFromCollection( lastOpByAllocNumber );
                    aCollectionManager.RemovePriorOperation( lastOpByAllocNumber );
                    aCollectionManager.AddToCollection( op, op.LinkRegisterSymbol, op.LinkRegisterAddress );
                    aCollectionManager.AddNewPriorOperation( op );
                }
                else if ( lastOpByAllocNumber.Class == TClass.EReallocation && lastOpByAllocNumber.CellAddress == op.CellAddress )
                {
                    // 2) Realloc, SafeRealloc => dump realloc
                    aCollectionManager.RemoveFromCollection( lastOpByAllocNumber );
                    aCollectionManager.RemovePriorOperation( lastOpByAllocNumber );

                    // Also, it's possible that this is just a no-op. For example, this pattern can occur when removing
                    // an object from a DObjectCon, in which case the DObjectCon code requests that the cell be shrunk in size.
                    //
                    // If there is no cell growth, then we shouldn't bother saving the operation.
                    int impact = (int) op.AllocationSize - (int) op.OriginalAllocationSize;
                    if ( impact > 0 )
                    {
                        aCollectionManager.AddToCollection( op, op.LinkRegisterSymbol, op.LinkRegisterAddress );
                        aCollectionManager.AddNewPriorOperation( op );
                    }
                }
                else
                {
                    // Checking for scenario (3)
                    //
                    // lastOpByAllocNumber will correspond to the 'alloc' operation. 
                    if ( lastOpByAllocNumber.Class == TClass.EAllocation &&
                         lastOpByAllocNumber.CellAddress == op.CellAddress ) // Satisfies linkage between OKSR and OKA
                    {
                        // We need to find out what the prior op was for the original cell allocation number. 
                        // This should point to the 'free' operation.
                        MemOpBase freeOp = aCollectionManager.PriorOperationByAllocationNumber( op.OriginalAllocationNumber );

                        // If we're throwing away matching allocated & subsequently freed cells, then freeOp will be null...
                        if ( freeOp == null || ( freeOp.Class == TClass.EDeallocation && freeOp.CellAddress == op.OriginalAddress ) )
                        {
                            // (3) Alloc, Free, SafeRealloc => dump alloc and free!

                            // Remove alloc, which is replaced by our new SafeRealloc entry
                            aCollectionManager.RemovePriorOperation( lastOpByAllocNumber );
                            aCollectionManager.RemoveFromCollection( lastOpByAllocNumber );

                            // Remove free for the old SafeRealloc heap cell
                            if ( freeOp != null )
                            {
                                aCollectionManager.RemovePriorOperation( freeOp );
                                aCollectionManager.RemoveFromCollection( freeOp );

                                // We may also need to remove a prior SafeRealloc that uses the same heap cell
                                MemOpBase safeReallocForDeletedCell = aCollectionManager.PriorOperationByAllocationNumber( freeOp.AllocationNumber );
                                if ( safeReallocForDeletedCell.Class == TClass.EReallocation && safeReallocForDeletedCell.CellAddress == freeOp.CellAddress )
                                {
                                    // Remove prior realloc associated with the old heap cell
                                    aCollectionManager.RemovePriorOperation( safeReallocForDeletedCell );
                                    aCollectionManager.RemoveFromCollection( safeReallocForDeletedCell );
                                }
                            }
                            
                            // Now add our new SafeRealloc entry to the master list
                            aCollectionManager.AddToCollection( op, op.LinkRegisterSymbol, op.LinkRegisterAddress );
                            aCollectionManager.AddNewPriorOperation( op );
                        }
                    }
                }
            }
        }
        #endregion
	}
}