src/sys/dotnet/perwapi/PERWAPI.cs
/// <summary>
/// Returns the maximum stack depth required by these CIL instructions.
/// </summary>
/// <returns>The integer value of the stck depth.</returns>
Returns the maximum stack depth required by these CIL instructions.
Returns the maximum stack depth required by these CIL instructions .
public int GetMaxStackDepthRequired() {
            if (tide == 0) return 0;
            SCG.List<CodeBlock> codeBlocks = new SCG.List<CodeBlock>();
            SCG.Dictionary<CILLabel, CodeBlock> cbTable = new SCG.Dictionary<CILLabel, CodeBlock>();
            SCG.List<CodeBlock> extraStartingBlocks = new SCG.List<CodeBlock>();
            CodeBlock codeBlock = new CodeBlock(this);
            codeBlock.StartIndex = 0;
             Identify the code blocks
            for (int i = 0; i < tide; i++) {
                 If we reach a branch instruction or a switch instruction
                 then end the current code block inclusive of the instruction.
                if ((buffer[i] is BranchInstr) || (buffer[i] is SwitchInstr)) {
                     Close the old block
                    codeBlock.EndIndex = i;
                    if (codeBlock.EndIndex >= codeBlock.StartIndex)  Don't add empty blocks
                        codeBlocks.Add(codeBlock);
                     Open a new block
                    codeBlock = new CodeBlock(this);
                    codeBlock.StartIndex = i + 1;
                     If we reach a label then we need to start a new
                     code block as the label is an entry point.
                } else if (buffer[i] is CILLabel) {
                     Close the old block
                    codeBlock.EndIndex = i - 1;
                    if (codeBlock.EndIndex >= codeBlock.StartIndex)  Don't add empty blocks
                        codeBlocks.Add(codeBlock);
                     Open a new block
                    codeBlock = new CodeBlock(this);
                    codeBlock.StartIndex = i;
                     Set this label as the entry point for the code block
                    codeBlock.EntryLabel = (CILLabel)buffer[i];
                     AND ... list in the dictionary.
                    cbTable.Add(codeBlock.EntryLabel, codeBlock);
                     Check for the ret, throw, rethrow, or jmp instruction as they also end a block
                } else if (buffer[i] is Instr) {
                    if (
                        (((Instr)buffer[i]).GetOp() == Op.ret) ||
                        (((Instr)buffer[i]).GetOp() == Op.throwOp) ||
                        (((Instr)buffer[i]).GetOp() == Op.rethrow) ||
                        ((buffer[i] is MethInstr) && (((MethInstr)buffer[i]).GetMethodOp() == MethodOp.jmp))
                       ) {
                         Close the old block
                        codeBlock.EndIndex = i;
                        if (codeBlock.EndIndex >= codeBlock.StartIndex)  Don't add empty blocks
                            codeBlocks.Add(codeBlock);
                         Open a new block
                         In theory this should never happen but just in case
                         someone feels like adding dead code it is supported.
                        codeBlock = new CodeBlock(this);
                        codeBlock.StartIndex = i + 1;
                    }
                }
            }
             Close the last block
            codeBlock.EndIndex = tide - 1;
            if (codeBlock.EndIndex >= codeBlock.StartIndex)  Don't add empty blocks
                codeBlocks.Add(codeBlock);
            codeBlock = null;
             Check how many code blocks there are.  If an blocks return 0.
            if (codeBlocks.Count == 0) return 0;
             Loop through each code block and calculate the delta distance
            for (int j = 0; j < codeBlocks.Count; j++) {
                CodeBlock block = codeBlocks[j];
                int maxDepth = 0;
                int currentDepth = 0;
                 Loop through each instruction to work out the max depth
                for (int i = block.StartIndex; i <= block.EndIndex; i++) {
                     Get the depth after the next instruction
                    currentDepth += buffer[i].GetDeltaDistance();
                     If the new current depth is greater then the maxDepth adjust the maxDepth to reflect
                    if (currentDepth > maxDepth)
                        maxDepth = currentDepth;
                }
                 Set the depth of the block
                block.MaxDepth = maxDepth;
                block.DeltaDistance = currentDepth;
                 Link up the next blocks
                 If the block ends with a branch statement set the jump and fall through.
                if (buffer[block.EndIndex] is BranchInstr) {
                    BranchInstr branchInst = (BranchInstr)buffer[block.EndIndex];
                     If this is not a "br" or "br.s" then set the fall through code block
                    if ((branchInst.GetBranchOp() != BranchOp.br) &&
                        (branchInst.GetBranchOp() != BranchOp.br_s))
                         If there is a following code block set it as the fall through
                        if (j < (codeBlocks.Count - 1))
                            block.NextBlocks.Add(codeBlocks[j + 1]);
                     Set the code block we are jumping to
                    CodeBlock cb = null;
                    cbTable.TryGetValue(branchInst.GetDest(), out cb);
                    if (cb == null)
                        throw new Exception("Missing Branch Label");
                    block.NextBlocks.Add(cb);
                     If the block ends in a switch instruction work out the possible next blocks
                } else if (buffer[block.EndIndex] is SwitchInstr) {
                    SwitchInstr switchInstr = (SwitchInstr)buffer[block.EndIndex];
                     If there is a following code block set it as the fall through
                    if (j < (codeBlocks.Count - 1))
                        block.NextBlocks.Add(codeBlocks[j + 1]);
                     Add each destination block
                    foreach (CILLabel label in switchInstr.GetDests()) {
                         Check all of the code blocks to find the jump destination
                        CodeBlock cb = null;
                        cbTable.TryGetValue(label, out cb);
                        if (cb == null) throw new Exception("Missing Case Label");
                        block.NextBlocks.Add(cb);
                    }
                     So long as the block doesn't end with a terminating instruction like ret or throw, just fall through to the next block
                } else if (!IsTerminatingInstruction(buffer[block.EndIndex])) {
                     If there is a following code block set it as the fall through
                    if (j < (codeBlocks.Count - 1))
                        block.NextBlocks.Add(codeBlocks[j + 1]);
                }
            }
             Join up any exception blocks
            if (exceptions != null) {
                foreach (TryBlock tryBlock in exceptions) {
                     Try to find the code block where this try block starts
                    CodeBlock tryCodeBlock;
                    cbTable.TryGetValue(tryBlock.Start, out tryCodeBlock);
                     Declare that the entry to this code block must be empty
                    tryCodeBlock.RequireEmptyEntry = true;
                     Work with each of the handlers
                    foreach (HandlerBlock hb in tryBlock.GetHandlers()) {
                         Find the code block where this handler block starts.
                        CodeBlock handlerCodeBlock;
                        cbTable.TryGetValue(hb.Start, out handlerCodeBlock);
                         If the code block is a catch or filter block increment the delta
                         distance by 1. This is to factor in the exception object that will
                         be secretly placed on the stack by the runtime engine.
                         However, this also means that the MaxDepth is up by one also!
                        if (hb is Catch || hb is Filter)
                        {
                            handlerCodeBlock.DeltaDistance++;
                            handlerCodeBlock.MaxDepth++;
                        }
                         If the code block is a filter block increment the delta distance by 1
                         This is to factor in the exception object that will be placed on the stack.
                         if (hb is Filter) handlerCodeBlock.DeltaDistance++;
                         Add this handler to the list of starting places
                        extraStartingBlocks.Add(handlerCodeBlock);
                    }
                }
            }
             Traverse the code blocks and get the depth
             Get the max depth at the starting entry point
            int finalMaxDepth = this.TraverseMaxDepth(codeBlocks[0]);
             Check the additional entry points
             If the additional points have a greater depth update the max depth
            foreach (CodeBlock cb in extraStartingBlocks) {
                 int tmpMaxDepth = cb.TraverseMaxDepth();
                int tmpMaxDepth = this.TraverseMaxDepth(cb);
                if (tmpMaxDepth > finalMaxDepth) finalMaxDepth = tmpMaxDepth;
            }
             Return the max depth we have found
            return finalMaxDepth;
        }
public int GetMaxStackDepthRequired ( ) { if ( tide == 0 ) return 0 ; SCG . List < CodeBlock > codeBlocks = new SCG . List < CodeBlock > ( ) ; SCG . Dictionary < CILLabel , CodeBlock > cbTable = new SCG . Dictionary < CILLabel , CodeBlock > ( ) ; SCG . List < CodeBlock > extraStartingBlocks = new SCG . List < CodeBlock > ( ) ; CodeBlock codeBlock = new CodeBlock ( this ) ; codeBlock . StartIndex = 0 ; for ( int i = 0 ; i < tide ; i ++ ) { if ( ( buffer [ i ] is BranchInstr ) || ( buffer [ i ] is SwitchInstr ) ) { codeBlock . EndIndex = i ; if ( codeBlock . EndIndex >= codeBlock . StartIndex ) codeBlocks . Add ( codeBlock ) ; codeBlock = new CodeBlock ( this ) ; codeBlock . StartIndex = i + 1 ; } else if ( buffer [ i ] is CILLabel ) { codeBlock . EndIndex = i - 1 ; if ( codeBlock . EndIndex >= codeBlock . StartIndex ) codeBlocks . Add ( codeBlock ) ; codeBlock = new CodeBlock ( this ) ; codeBlock . StartIndex = i ; codeBlock . EntryLabel = ( CILLabel ) buffer [ i ] ; cbTable . Add ( codeBlock . EntryLabel , codeBlock ) ; } else if ( buffer [ i ] is Instr ) { if ( ( ( ( Instr ) buffer [ i ] ) . GetOp ( ) == Op . ret ) || ( ( ( Instr ) buffer [ i ] ) . GetOp ( ) == Op . throwOp ) || ( ( ( Instr ) buffer [ i ] ) . GetOp ( ) == Op . rethrow ) || ( ( buffer [ i ] is MethInstr ) && ( ( ( MethInstr ) buffer [ i ] ) . GetMethodOp ( ) == MethodOp . jmp ) ) ) { codeBlock . EndIndex = i ; if ( codeBlock . EndIndex >= codeBlock . StartIndex ) codeBlocks . Add ( codeBlock ) ; codeBlock = new CodeBlock ( this ) ; codeBlock . StartIndex = i + 1 ; } } } codeBlock . EndIndex = tide - 1 ; if ( codeBlock . EndIndex >= codeBlock . StartIndex ) codeBlocks . Add ( codeBlock ) ; codeBlock = null ; if ( codeBlocks . Count == 0 ) return 0 ; for ( int j = 0 ; j < codeBlocks . Count ; j ++ ) { CodeBlock block = codeBlocks [ j ] ; int maxDepth = 0 ; int currentDepth = 0 ; for ( int i = block . StartIndex ; i <= block . EndIndex ; i ++ ) { currentDepth += buffer [ i ] . GetDeltaDistance ( ) ; if ( currentDepth > maxDepth ) maxDepth = currentDepth ; } block . MaxDepth = maxDepth ; block . DeltaDistance = currentDepth ; if ( buffer [ block . EndIndex ] is BranchInstr ) { BranchInstr branchInst = ( BranchInstr ) buffer [ block . EndIndex ] ; if ( ( branchInst . GetBranchOp ( ) != BranchOp . br ) && ( branchInst . GetBranchOp ( ) != BranchOp . br_s ) ) if ( j < ( codeBlocks . Count - 1 ) ) block . NextBlocks . Add ( codeBlocks [ j + 1 ] ) ; CodeBlock cb = null ; cbTable . TryGetValue ( branchInst . GetDest ( ) , out cb ) ; if ( cb == null ) throw new Exception ( " " ) ; block . NextBlocks . Add ( cb ) ; } else if ( buffer [ block . EndIndex ] is SwitchInstr ) { SwitchInstr switchInstr = ( SwitchInstr ) buffer [ block . EndIndex ] ; if ( j < ( codeBlocks . Count - 1 ) ) block . NextBlocks . Add ( codeBlocks [ j + 1 ] ) ; foreach ( CILLabel label in switchInstr . GetDests ( ) ) { CodeBlock cb = null ; cbTable . TryGetValue ( label , out cb ) ; if ( cb == null ) throw new Exception ( " " ) ; block . NextBlocks . Add ( cb ) ; } } else if ( ! IsTerminatingInstruction ( buffer [ block . EndIndex ] ) ) { if ( j < ( codeBlocks . Count - 1 ) ) block . NextBlocks . Add ( codeBlocks [ j + 1 ] ) ; } } if ( exceptions != null ) { foreach ( TryBlock tryBlock in exceptions ) { CodeBlock tryCodeBlock ; cbTable . TryGetValue ( tryBlock . Start , out tryCodeBlock ) ; tryCodeBlock . RequireEmptyEntry = true ; foreach ( HandlerBlock hb in tryBlock . GetHandlers ( ) ) { CodeBlock handlerCodeBlock ; cbTable . TryGetValue ( hb . Start , out handlerCodeBlock ) ; if ( hb is Catch || hb is Filter ) { handlerCodeBlock . DeltaDistance ++ ; handlerCodeBlock . MaxDepth ++ ; } extraStartingBlocks . Add ( handlerCodeBlock ) ; } } } int finalMaxDepth = this . TraverseMaxDepth ( codeBlocks [ 0 ] ) ; foreach ( CodeBlock cb in extraStartingBlocks ) { int tmpMaxDepth = this . TraverseMaxDepth ( cb ) ; if ( tmpMaxDepth > finalMaxDepth ) finalMaxDepth = tmpMaxDepth ; } return finalMaxDepth ; }
Returns the maximum stack depth required by these CIL instructions.
Returns the maximum stack depth required by these CIL instructions .
// Store the code blocks we find // Start a default code block // // Identify the code blocks // /* Handling the tail instruction:
                 * The tail instruction has not been handled even though
                 * it indicates the end of a code block is coming.  The
                 * reason for this is because any valid tail instruction
                 * must be followed by a call* instruction and then a ret
                 * instruction.  Given a ret instruction must be the second
                 * next instruction anyway it has been decided to just let
                 * the end block be caught then.
                 */ // If we reach a branch instruction or a switch instruction // then end the current code block inclusive of the instruction. // Close the old block // Don't add empty blocks // Open a new block // If we reach a label then we need to start a new // code block as the label is an entry point. // Close the old block // Don't add empty blocks // Open a new block // Set this label as the entry point for the code block // AND ... list in the dictionary. // Check for the ret, throw, rethrow, or jmp instruction as they also end a block // Close the old block // Don't add empty blocks // Open a new block // In theory this should never happen but just in case // someone feels like adding dead code it is supported. // Close the last block // Don't add empty blocks // Check how many code blocks there are.  If an blocks return 0. // // Loop through each code block and calculate the delta distance // // Loop through each instruction to work out the max depth // Get the depth after the next instruction // If the new current depth is greater then the maxDepth adjust the maxDepth to reflect // Set the depth of the block // // Link up the next blocks // // If the block ends with a branch statement set the jump and fall through. // If this is not a "br" or "br.s" then set the fall through code block // If there is a following code block set it as the fall through // Set the code block we are jumping to // If the block ends in a switch instruction work out the possible next blocks // If there is a following code block set it as the fall through // Add each destination block // Check all of the code blocks to find the jump destination // So long as the block doesn't end with a terminating instruction like ret or throw, just fall through to the next block // If there is a following code block set it as the fall through // // Join up any exception blocks // // Try to find the code block where this try block starts // Declare that the entry to this code block must be empty // Work with each of the handlers // Find the code block where this handler block starts. // If the code block is a catch or filter block increment the delta // distance by 1. This is to factor in the exception object that will // be secretly placed on the stack by the runtime engine. // However, this also means that the MaxDepth is up by one also! // If the code block is a filter block increment the delta distance by 1 // This is to factor in the exception object that will be placed on the stack. // if (hb is Filter) handlerCodeBlock.DeltaDistance++; // Add this handler to the list of starting places // // Traverse the code blocks and get the depth // // Get the max depth at the starting entry point // Check the additional entry points // If the additional points have a greater depth update the max depth // int tmpMaxDepth = cb.TraverseMaxDepth(); // Return the max depth we have found
The integer value of the stck depth.
The integer value of the stck depth .