Exemplo n.º 1
0
        public int optimizeLocals()
        {
            if (locals.Count == 0)
            {
                return(0);
            }

            var usedLocals = new Dictionary <Local, List <LocalVariableInfo> >();

            foreach (var block in methodBlocks.getAllBlocks())
            {
                for (int i = 0; i < block.Instructions.Count; i++)
                {
                    var   instr = block.Instructions[i];
                    Local local;
                    switch (instr.OpCode.Code)
                    {
                    case Code.Ldloc:
                    case Code.Ldloc_S:
                    case Code.Ldloc_0:
                    case Code.Ldloc_1:
                    case Code.Ldloc_2:
                    case Code.Ldloc_3:
                    case Code.Stloc:
                    case Code.Stloc_S:
                    case Code.Stloc_0:
                    case Code.Stloc_1:
                    case Code.Stloc_2:
                    case Code.Stloc_3:
                        local = Instr.getLocalVar(locals, instr);
                        break;

                    case Code.Ldloca_S:
                    case Code.Ldloca:
                        local = (Local)instr.Operand;
                        break;

                    default:
                        local = null;
                        break;
                    }
                    if (local == null)
                    {
                        continue;
                    }

                    List <LocalVariableInfo> list;
                    if (!usedLocals.TryGetValue(local, out list))
                    {
                        usedLocals[local] = list = new List <LocalVariableInfo>();
                    }
                    list.Add(new LocalVariableInfo(block, i));
                    if (usedLocals.Count == locals.Count)
                    {
                        return(0);
                    }
                }
            }

            int newIndex      = -1;
            var newLocals     = new List <Local>(usedLocals.Count);
            var newLocalsDict = new Dictionary <Local, bool>(usedLocals.Count);

            foreach (var local in usedLocals.Keys)
            {
                newIndex++;
                newLocals.Add(local);
                newLocalsDict[local] = true;
                foreach (var info in usedLocals[local])
                {
                    info.block.Instructions[info.index] = new Instr(optimizeLocalInstr(info.block.Instructions[info.index], local, (uint)newIndex));
                }
            }

            // We can't remove all locals. Locals that reference another assembly will
            // cause the CLR to load that assembly before the method is executed if it
            // hasn't been loaded yet. This is a side effect the program may depend on.
            // At least one program has this dependency and will crash if we remove the
            // unused local. This took a while to figure out...
            var keptAssemblies = new Dictionary <string, bool>(StringComparer.Ordinal);

            foreach (var local in locals)
            {
                if (newLocalsDict.ContainsKey(local))
                {
                    continue;
                }
                var defAsm = local.Type.DefinitionAssembly;
                if (defAsm == null)
                {
                    continue;                           // eg. fnptr
                }
                if (defAsm == method.DeclaringType.Module.Assembly)
                {
                    continue;                           // this assembly is always loaded
                }
                if (defAsm.IsCorLib())
                {
                    continue;                           // mscorlib is always loaded
                }
                var asmName = defAsm.FullName;
                if (keptAssemblies.ContainsKey(asmName))
                {
                    continue;
                }
                keptAssemblies[asmName] = true;
                newLocals.Add(local);
            }

            int numRemoved = locals.Count - newLocals.Count;

            locals.Clear();
            foreach (var local in newLocals)
            {
                locals.Add(local);
            }
            return(numRemoved);
        }
Exemplo n.º 2
0
        public int optimizeLocals()
        {
            if (locals.Count == 0)
            {
                return(0);
            }

            var usedLocals = new Dictionary <VariableDefinition, List <LocalVariableInfo> >();

            foreach (var block in methodBlocks.getAllBlocks())
            {
                for (int i = 0; i < block.Instructions.Count; i++)
                {
                    var instr = block.Instructions[i];
                    VariableDefinition local;
                    switch (instr.OpCode.Code)
                    {
                    case Code.Ldloc:
                    case Code.Ldloc_S:
                    case Code.Ldloc_0:
                    case Code.Ldloc_1:
                    case Code.Ldloc_2:
                    case Code.Ldloc_3:
                    case Code.Stloc:
                    case Code.Stloc_S:
                    case Code.Stloc_0:
                    case Code.Stloc_1:
                    case Code.Stloc_2:
                    case Code.Stloc_3:
                        local = Instr.getLocalVar(locals, instr);
                        break;

                    case Code.Ldloca_S:
                    case Code.Ldloca:
                        local = (VariableDefinition)instr.Operand;
                        break;

                    default:
                        local = null;
                        break;
                    }
                    if (local == null)
                    {
                        continue;
                    }

                    List <LocalVariableInfo> list;
                    if (!usedLocals.TryGetValue(local, out list))
                    {
                        usedLocals[local] = list = new List <LocalVariableInfo>();
                    }
                    list.Add(new LocalVariableInfo(block, i));
                    if (usedLocals.Count == locals.Count)
                    {
                        return(0);
                    }
                }
            }

            int newIndex  = -1;
            var newLocals = new List <VariableDefinition>(usedLocals.Count);

            foreach (var local in usedLocals.Keys)
            {
                newIndex++;
                newLocals.Add(local);
                foreach (var info in usedLocals[local])
                {
                    info.block.Instructions[info.index] = new Instr(optimizeLocalInstr(info.block.Instructions[info.index], local, (uint)newIndex));
                }
            }

            int numRemoved = locals.Count - newLocals.Count;

            locals.Clear();
            foreach (var local in newLocals)
            {
                locals.Add(local);
            }
            return(numRemoved);
        }