コード例 #1
0
        void DetectNullSafeArrayToPointer(BlockContainer container)
        {
            // Detect the following pattern:
            //   ...
            //   stloc V(ldloc S)
            //   if (comp(ldloc S == ldnull)) br B_null_or_empty
            //   br B_not_null
            // }
            // Block B_not_null {
            //   if (conv i->i4 (ldlen(ldloc V))) br B_not_null_and_not_empty
            //   br B_null_or_empty
            // }
            // Block B_not_null_and_not_empty {
            //   stloc P(ldelema(ldloc V, ldc.i4 0, ...))
            //   br B_target
            // }
            // Block B_null_or_empty {
            //   stloc P(conv i4->u(ldc.i4 0))
            //   br B_target
            // }
            // And convert the whole thing into:
            //   ...
            //   stloc P(array.to.pointer(V))
            //   br B_target
            bool modified = false;

            for (int i = 0; i < container.Blocks.Count; i++)
            {
                var block = container.Blocks[i];
                if (IsNullSafeArrayToPointerPattern(block, out ILVariable v, out ILVariable p, out Block targetBlock))
                {
                    context.Step("NullSafeArrayToPointerPattern", block);
                    ILInstruction arrayToPointer = new GetPinnableReference(new LdLoc(v), null);
                    if (p.StackType != StackType.Ref)
                    {
                        arrayToPointer = new Conv(arrayToPointer, p.StackType.ToPrimitiveType(), false, Sign.None);
                    }
                    block.Instructions[block.Instructions.Count - 2] = new StLoc(p, arrayToPointer)
                                                                       .WithILRange(block.Instructions[block.Instructions.Count - 2]);
                    ((Branch)block.Instructions.Last()).TargetBlock = targetBlock;
                    modified = true;
                }
            }
            if (modified)
            {
                container.Blocks.RemoveAll(b => b.IncomingEdgeCount == 0);                 // remove blocks made unreachable
            }
        }
コード例 #2
0
ファイル: DetectPinnedRegions.cs プロジェクト: zz110/ILSpy
        void DetectNullSafeArrayToPointerOrCustomRefPin(BlockContainer container)
        {
            bool modified = false;

            for (int i = 0; i < container.Blocks.Count; i++)
            {
                var block = container.Blocks[i];
                if (IsNullSafeArrayToPointerPattern(block, out ILVariable v, out ILVariable p, out Block targetBlock))
                {
                    context.Step("NullSafeArrayToPointerPattern", block);
                    ILInstruction arrayToPointer = new GetPinnableReference(new LdLoc(v), null);
                    if (p.StackType != StackType.Ref)
                    {
                        arrayToPointer = new Conv(arrayToPointer, p.StackType.ToPrimitiveType(), false, Sign.None);
                    }
                    block.Instructions[block.Instructions.Count - 2] = new StLoc(p, arrayToPointer)
                                                                       .WithILRange(block.Instructions[block.Instructions.Count - 2]);
                    ((Branch)block.Instructions.Last()).TargetBlock = targetBlock;
                    modified = true;
                }