Example #1
0
        void PrintMap(TypeDefinition type)
        {
            if (!type.HasMethods)
            {
                return;
            }

            Console.WriteLine("Type {0} map", type);

            foreach (MethodDefinition method in type.Methods)
            {
                if (!method.IsVirtual)
                {
                    continue;
                }

                Console.WriteLine("  Method {0} map", method);

                IEnumerable <MethodDefinition> overrides = Annotations.GetOverrides(method);
                foreach (var @override in overrides ?? new MethodDefinition[0])
                {
                    Console.WriteLine("    HasOverride {0}", @override);
                }

                IEnumerable <MethodDefinition> bases = Annotations.GetBaseMethods(method);
                foreach (var @base in bases ?? new MethodDefinition[0])
                {
                    Console.WriteLine("    Base {0}", @base);
                }
            }
        }
Example #2
0
        void ProcessVirtualMethod(MethodDefinition method)
        {
            IList overrides = Annotations.GetOverrides(method);

            if (overrides == null)
            {
                return;
            }

            foreach (MethodDefinition @override in overrides)
            {
                ProcessOverride(@override);
            }
        }
Example #3
0
        bool IsOverridenInUserCode(MethodDefinition method)
        {
            if (!method.IsVirtual)
            {
                return(false);
            }

            var overrides = Annotations.GetOverrides(method);

            if (overrides == null || overrides.Count == 0)
            {
                return(false);
            }

            foreach (MethodDefinition @override in overrides)
            {
                if (!IsProductMethod(@override))
                {
                    return(true);
                }
            }

            return(false);
        }
Example #4
0
        void ProcessDispose(MethodDefinition bd, MethodDefinition cd)
        {
            bool skip = false;

            // did we detect some fields that could be removed ?
            if (dispose_methods.Contains(cd))
            {
                // removed unmarked fields
                skip = FilterDispose(cd);
                // return value tells us if the Dispose method is now "empty" and could be skipped to the next
                // (non-empty) base.Dispose
                if (skip)
                {
                    // if it does nothing then it should not be part of the final binary
                    //cd.DeclaringType.Methods.Remove (cd);
                }
            }

            var overrides = Annotations.GetOverrides(cd);

            if (overrides == null)
            {
                return;
            }

            // every subclass-Dispose should be calling base-Dispose
            foreach (MethodDefinition od in overrides)
            {
                // we do not need to process unmarked code (it won't be part of the final binary)
                if (!Annotations.IsMarked(od))
                {
                    continue;
                }
                // we do NOT process non-generated code - we could break user code
                if (!od.IsGeneratedCode(LinkContext))
                {
                    continue;
                }

                ProcessDispose(skip ? bd : cd, od);

                // check if we need to replace the base.Dipose call
                if (bd == cd)
                {
                    continue;
                }

                // replace "base.Dispose". In C# this always looks fine - but in IL it's the base type that's
                // used (and needs to change to remove the "empty" Dispose methods)
                foreach (Instruction ins in od.Body.Instructions)
                {
                    if (ins.OpCode.Code != Code.Call)
                    {
                        continue;
                    }

                    // we can cross the assembly borders and the Dispose method might not be
                    // part of the existing member references so we import it in such cases
                    if (od.Module != bd.Module)
                    {
                        ins.Operand = od.Module.ImportReference(bd);
                    }
                    else
                    {
                        ins.Operand = bd;
                    }
                    break;
                }
            }
        }
Example #5
0
        void ProcessType(TypeDefinition type)
        {
            if (type.HasNestedTypes)
            {
                foreach (var nt in type.NestedTypes)
                {
                    ProcessType(nt);
                }
            }

            //
            // interface members are virtual (and we cannot change this)
            //
            if (type.IsInterface)
            {
                return;
            }

            //
            // the code does not include any subclass for this type
            //
            if (!type.IsAbstract && !type.IsSealed && !IsSubclassed(type))
            {
                SealType(type);
            }

            if (!type.HasMethods)
            {
                return;
            }

            // process methods to see if we can seal or devirtualize them
            foreach (var method in type.Methods)
            {
                if (method.IsFinal || !method.IsVirtual || method.IsAbstract || method.IsRuntime)
                {
                    continue;
                }

                Debug.Assert(Annotations.IsMarked(method));
                if (!Annotations.IsMarked(method))
                {
                    continue;
                }

                var overrides = Annotations.GetOverrides(method);

                //
                // cannot de-virtualize nor seal methods if something overrides them
                //
                if (IsAnyMarked(overrides))
                {
                    continue;
                }

                SealMethod(method);

                // subclasses might need this method to satisfy an interface requirement
                // and requires dispatch/virtual support
                if (!type.IsSealed)
                {
                    continue;
                }

                var bases = Annotations.GetBaseMethods(method);
                // Devirtualize if a method is not override to existing marked methods
                if (!IsAnyMarked(bases))
                {
                    method.IsVirtual = method.IsFinal = method.IsNewSlot = false;
                }
            }
        }
Example #6
0
        protected override void Process(TypeDefinition type)
        {
            // interface members are virtual (and we cannot change this)
            // we cannot seal interfaces either
            if (type.IsInterface)
            {
                return;
            }

            // only optimize code that was marked earlier (the rest will be swept away)
            if (!Annotations.IsMarked(type))
            {
                return;
            }

            // if we do not include any subclass for this type
            if (!type.IsAbstract && !type.IsSealed && !IsSubclassed(type))
            {
                type.IsSealed = true;
#if DEBUG
                Console.WriteLine("Seal {0} ({1})", type, ++seal);
#endif
            }

            if (!type.HasMethods)
            {
                return;
            }

            // process virtual methods to see if we can "seal" or devirtualize them
            foreach (var method in type.Methods)
            {
                if (method.IsFinal || !method.IsVirtual || method.IsAbstract || method.IsRuntime)
                {
                    continue;
                }
                if (!Annotations.IsMarked(method))
                {
                    continue;
                }

                var overrides = Annotations.GetOverrides(method);
                // we cannot de-virtualize nor seal methods if something overrides them
                if (overrides != null)
                {
                    // sanity (disable IsSealed == true above)
                    //if (type.IsSealed)
                    //	Console.WriteLine ();
                    continue;
                }

                // we can seal the method (final in IL / !virtual in C#)
                method.IsFinal = true;
#if DEBUG
                Console.WriteLine("Final {0} ({1})", method, ++final);
#endif
                // subclasses might need this method to satisfy an interface requirement
                // and requires dispatch/virtual support
                if (!type.IsSealed)
                {
                    continue;
                }

                var bases = Annotations.GetBaseMethods(method);
                // look if this method is an override to existing _marked_ methods
                if (!AreMarked(bases))
                {
                    method.IsVirtual = false;
#if DEBUG
                    Console.WriteLine("Devirtualize {0} ({1})", method, ++devirtualize);
#endif
                }
            }
        }