Exemple #1
0
        protected void Assemble()
        {
            foreach (var xItem in mItems)
            {
                if (xItem is MethodBase)
                {
                    var        xMethod        = (MethodBase)xItem;
                    var        xParams        = xMethod.GetParameters();
                    var        xParamTypes    = xParams.Select(q => q.ParameterType).ToArray();
                    var        xPlug          = mPlugManager.ResolvePlug(xMethod, xParamTypes);
                    var        xMethodType    = MethodInfo.TypeEnum.Normal;
                    Type       xPlugAssembler = null;
                    MethodInfo xPlugInfo      = null;
                    if (xPlug != null)
                    {
                        xMethodType = MethodInfo.TypeEnum.NeedsPlug;
                        PlugMethodAttribute xAttrib = null;
                        foreach (PlugMethodAttribute attrib in xPlug.GetCustomAttributes(typeof(PlugMethodAttribute), true))
                        {
                            xAttrib = attrib;
                        }
                        if (xAttrib != null)
                        {
                            xPlugAssembler = xAttrib.Assembler;
                            xPlugInfo      = new MethodInfo(xPlug, (uint)mItemsList.IndexOf(xPlug), MethodInfo.TypeEnum.Plug, null, xPlugAssembler);

                            var xMethodInfo = new MethodInfo(xMethod, (uint)mItemsList.IndexOf(xMethod), xMethodType, xPlugInfo /*, xPlugAssembler*/);
                            if (xAttrib != null && xAttrib.IsWildcard)
                            {
                                xPlugInfo.PluggedMethod = xMethodInfo;
                                var xInstructions = mReader.ProcessMethod(xPlug);
                                if (xInstructions != null)
                                {
                                    ProcessInstructions(xInstructions);
                                    mAsmblr.ProcessMethod(xPlugInfo, xInstructions);
                                }
                            }
                            mAsmblr.GenerateMethodForward(xMethodInfo, xPlugInfo);
                        }
                        else
                        {
                            InlineAttribute inl = null;
                            foreach (InlineAttribute inli in xPlug.GetCustomAttributes(typeof(InlineAttribute), false))
                            {
                                inl = inli;
                            }
                            if (inl != null)
                            {
                                xPlugInfo = new MethodInfo(xPlug, (uint)mItemsList.IndexOf(xItem), MethodInfo.TypeEnum.Plug, null, true);

                                var xMethodInfo = new MethodInfo(xMethod, (uint)mItemsList.IndexOf(xMethod), xMethodType, xPlugInfo /*, xPlugAssembler*/);

                                xPlugInfo.PluggedMethod = xMethodInfo;
                                var xInstructions = mReader.ProcessMethod(xPlug);
                                if (xInstructions != null)
                                {
                                    ProcessInstructions(xInstructions);
                                    mAsmblr.ProcessMethod(xPlugInfo, xInstructions);
                                }
                                mAsmblr.GenerateMethodForward(xMethodInfo, xPlugInfo);
                            }
                            else
                            {
                                xPlugInfo = new MethodInfo(xPlug, (uint)mItemsList.IndexOf(xPlug), MethodInfo.TypeEnum.Plug, null, xPlugAssembler);

                                var xMethodInfo = new MethodInfo(xMethod, (uint)mItemsList.IndexOf(xMethod), xMethodType, xPlugInfo /*, xPlugAssembler*/);
                                if (xAttrib != null && xAttrib.IsWildcard)
                                {
                                    xPlugInfo.PluggedMethod = xMethodInfo;
                                    var xInstructions = mReader.ProcessMethod(xPlug);
                                    if (xInstructions != null)
                                    {
                                        ProcessInstructions(xInstructions);
                                        mAsmblr.ProcessMethod(xPlugInfo, xInstructions);
                                    }
                                }
                                mAsmblr.GenerateMethodForward(xMethodInfo, xPlugInfo);
                            }
                        }
                    }
                    else
                    {
                        PlugMethodAttribute xAttrib = null;
                        foreach (PlugMethodAttribute attrib in xMethod.GetCustomAttributes(typeof(PlugMethodAttribute), true))
                        {
                            xAttrib = attrib;
                        }
                        if (xAttrib != null)
                        {
                            if (xAttrib.IsWildcard)
                            {
                                continue;
                            }
                            xPlugAssembler = xAttrib.Assembler;
                        }

                        var xMethodInfo   = new MethodInfo(xMethod, (uint)mItemsList.IndexOf(xMethod), xMethodType, xPlugInfo, xPlugAssembler);
                        var xInstructions = mReader.ProcessMethod(xMethod);
                        if (xInstructions != null)
                        {
                            ProcessInstructions(xInstructions);
                            mAsmblr.ProcessMethod(xMethodInfo, xInstructions);
                        }
                    }
                }
                else if (xItem is FieldInfo)
                {
                    mAsmblr.ProcessField((FieldInfo)xItem);
                }
            }

            var xTypes   = new HashSet <Type>();
            var xMethods = new HashSet <MethodBase>();

            foreach (var xItem in mItems)
            {
                if (xItem is MethodBase)
                {
                    xMethods.Add((MethodBase)xItem);
                }
                else if (xItem is Type)
                {
                    xTypes.Add((Type)xItem);
                }
            }
            mAsmblr.GenerateVMTCode(xTypes, xMethods, GetTypeUID, x => GetMethodUID(x, false));
        }
Exemple #2
0
        protected void Assemble()
        {
            foreach (var xItem in mItems)
            {
                if (xItem is MethodBase)
                {
                    var        xMethod        = (MethodBase)xItem;
                    var        xParams        = xMethod.GetParameters();
                    var        xParamTypes    = xParams.Select(q => q.ParameterType).ToArray();
                    var        xPlug          = mPlugManager.ResolvePlug(xMethod, xParamTypes);
                    var        xMethodType    = MethodInfo.TypeEnum.Normal;
                    Type       xPlugAssembler = null;
                    MethodInfo xPlugInfo      = null;
                    var        xMethodInline  = xMethod.GetCustomAttribute <InlineAttribute>();
                    if (xMethodInline != null)
                    {
                        // inline assembler, shouldn't come here..
                        continue;
                    }
                    var xMethodIdMethod = mItemsList.IndexOf(xMethod);
                    if (xMethodIdMethod == -1)
                    {
                        throw new Exception("Method not in scanner list!");
                    }
                    if (xPlug != null)
                    {
                        xMethodType = MethodInfo.TypeEnum.NeedsPlug;
                        var xAttrib       = xPlug.GetCustomAttribute <PlugMethodAttribute>();
                        var xInline       = xPlug.GetCustomAttribute <InlineAttribute>();
                        var xMethodIdPlug = mItemsList.IndexOf(xPlug);
                        if (xMethodIdPlug == -1 && xInline == null)
                        {
                            throw new Exception("Plug method not in scanner list!");
                        }
                        if (xAttrib != null && xInline == null)
                        {
                            xPlugAssembler = xAttrib.Assembler;
                            xPlugInfo      = new MethodInfo(xPlug, (uint)xMethodIdPlug, MethodInfo.TypeEnum.Plug, null, xPlugAssembler);

                            var xMethodInfo = new MethodInfo(xMethod, (uint)xMethodIdMethod, xMethodType, xPlugInfo /*, xPlugAssembler*/);
                            if (xAttrib != null && xAttrib.IsWildcard)
                            {
                                xPlugInfo.PluggedMethod = xMethodInfo;
                                var xInstructions = mReader.ProcessMethod(xPlug);
                                if (xInstructions != null)
                                {
                                    ProcessInstructions(xInstructions);
                                    mAsmblr.ProcessMethod(xPlugInfo, xInstructions);
                                }
                            }
                            mAsmblr.GenerateMethodForward(xMethodInfo, xPlugInfo);
                        }
                        else
                        {
                            if (xInline != null)
                            {
                                var xMethodID = mItemsList.IndexOf(xItem);
                                if (xMethodID == -1)
                                {
                                    throw new Exception("Method not in list!");
                                }
                                xPlugInfo = new MethodInfo(xPlug, (uint)xMethodID, MethodInfo.TypeEnum.Plug, null, true);

                                var xMethodInfo = new MethodInfo(xMethod, (uint)xMethodIdMethod, xMethodType, xPlugInfo /*, xPlugAssembler*/);

                                xPlugInfo.PluggedMethod = xMethodInfo;
                                var xInstructions = mReader.ProcessMethod(xPlug);
                                if (xInstructions != null)
                                {
                                    ProcessInstructions(xInstructions);
                                    mAsmblr.ProcessMethod(xPlugInfo, xInstructions);
                                }
                                mAsmblr.GenerateMethodForward(xMethodInfo, xPlugInfo);
                            }
                            else
                            {
                                xPlugInfo = new MethodInfo(xPlug, (uint)xMethodIdPlug, MethodInfo.TypeEnum.Plug, null, xPlugAssembler);

                                var xMethodInfo = new MethodInfo(xMethod, (uint)xMethodIdMethod, xMethodType, xPlugInfo /*, xPlugAssembler*/);
                                mAsmblr.GenerateMethodForward(xMethodInfo, xPlugInfo);
                            }
                        }
                    }
                    else
                    {
                        PlugMethodAttribute xAttrib = null;
                        foreach (PlugMethodAttribute attrib in xMethod.GetCustomAttributes(typeof(PlugMethodAttribute), true))
                        {
                            xAttrib = attrib;
                        }
                        if (xAttrib != null)
                        {
                            if (xAttrib.IsWildcard)
                            {
                                continue;
                            }
                            else if (xAttrib.PlugRequired)
                            {
                                throw new Exception(string.Format("Method {0} requires a plug, but none is implemented", xMethod.Name));
                            }
                            xPlugAssembler = xAttrib.Assembler;
                        }

                        var xMethodInfo   = new MethodInfo(xMethod, (uint)xMethodIdMethod, xMethodType, xPlugInfo, xPlugAssembler);
                        var xInstructions = mReader.ProcessMethod(xMethod);
                        if (xInstructions != null)
                        {
                            ProcessInstructions(xInstructions);
                            mAsmblr.ProcessMethod(xMethodInfo, xInstructions);
                        }
                    }
                }
                else if (xItem is FieldInfo)
                {
                    mAsmblr.ProcessField((FieldInfo)xItem);
                }
            }

            var xTypes   = new HashSet <Type>();
            var xMethods = new HashSet <MethodBase>();

            foreach (var xItem in mItems)
            {
                if (xItem is MethodBase)
                {
                    xMethods.Add((MethodBase)xItem);
                }
                else if (xItem is Type)
                {
                    xTypes.Add((Type)xItem);
                }
            }
            mAsmblr.GenerateVMTCode(xTypes, xMethods, GetTypeUID, x => GetMethodUID(x, false));
        }
Exemple #3
0
        public void Execute(MethodBase aStartMethod, IEnumerable <Assembly> plugsAssemblies)
        {
            if (aStartMethod == null)
            {
                throw new ArgumentNullException(nameof(aStartMethod));
            }
            // TODO: Investigate using MS CCI
            // Need to check license, as well as in profiler
            // http://cciast.codeplex.com/

            #region Description

            // Methodology
            //
            // Ok - we've done the scanner enough times to know it needs to be
            // documented super well so that future changes won't inadvertently
            // break undocumented and unseen requirements.
            //
            // We've tried many approaches including recursive and additive scanning.
            // They typically end up being inefficient, overly complex, or both.
            //
            // -We would like to scan all types/methods so we can plug them.
            // -But we can't scan them until we plug them, because we will scan things
            // that plugs would remove/change the paths of.
            // -Plugs may also call methods which are also plugged.
            // -We cannot resolve plugs ahead of time but must do on the fly during
            // scanning.
            // -TODO: Because we do on the fly resolution, we need to add explicit
            // checking of plug classes and err when public methods are found that
            // do not resolve. Maybe we can make a list and mark, or rescan. Can be done
            // later or as an optional auditing step.
            //
            // This why in the past we had repetitive scans.
            //
            // Now we focus on more passes, but simpler execution. In the end it should
            // be eaiser to optmize and yield overall better performance. Most of the
            // passes should be low overhead versus an integrated system which often
            // would need to reiterate over items multiple times. So we do more loops on
            // with less repetitive analysis, instead of fewer loops but more repetition.
            //
            // -Locate all plug classes
            // -Scan from entry point collecting all types and methods while checking
            // for and following plugs
            // -For each type
            //    -Include all ancestors
            //    -Include all static constructors
            // -For each virtual method
            //    -Scan overloads in descendants until IsFinal, IsSealed or end
            //    -Scan base in ancestors until top or IsAbstract
            // -Go to scan types again, until no new ones found.
            // -Because the virtual method scanning will add to the list as it goes, maintain
            //  2 lists.
            //    -Known Types and Methods
            //    -Types and Methods in Queue - to be scanned
            // -Finally, do compilation

            #endregion Description

            mPlugManager.FindPlugImpls(plugsAssemblies);
            // Now that we found all plugs, scan them.
            // We have to scan them after we find all plugs, because
            // plugs can use other plugs
            mPlugManager.ScanFoundPlugs();
            foreach (var xPlug in mPlugManager.PlugImpls)
            {
                CompilerHelpers.Debug($"Plug found: '{xPlug.Key.FullName}' in '{xPlug.Key.Assembly.FullName}'");
            }

            ILOp.PlugManager = mPlugManager;

            // Pull in extra implementations, GC etc.
            Queue(RuntimeEngineRefs.InitializeApplicationRef, null, "Explicit Entry");
            Queue(RuntimeEngineRefs.FinalizeApplicationRef, null, "Explicit Entry");
            Queue(VTablesImplRefs.IsInstanceRef, null, "Explicit Entry");
            Queue(VTablesImplRefs.SetTypeInfoRef, null, "Explicit Entry");
            Queue(VTablesImplRefs.SetInterfaceInfoRef, null, "Explicit Entry");
            Queue(VTablesImplRefs.SetMethodInfoRef, null, "Explicit Entry");
            Queue(VTablesImplRefs.SetInterfaceMethodInfoRef, null, "Explicit Entry");
            Queue(VTablesImplRefs.GetMethodAddressForTypeRef, null, "Explicit Entry");
            Queue(VTablesImplRefs.GetMethodAddressForInterfaceTypeRef, null, "Explicit Entry");
            Queue(GCImplementationRefs.IncRefCountRef, null, "Explicit Entry");
            Queue(GCImplementationRefs.DecRefCountRef, null, "Explicit Entry");
            Queue(GCImplementationRefs.AllocNewObjectRef, null, "Explicit Entry");
            // for now, to ease runtime exception throwing
            Queue(typeof(ExceptionHelper).GetMethod("ThrowNotImplemented", new Type[] { typeof(string) }, null), null, "Explicit Entry");
            Queue(typeof(ExceptionHelper).GetMethod("ThrowOverflow", Type.EmptyTypes, null), null, "Explicit Entry");
            Queue(typeof(ExceptionHelper).GetMethod("ThrowInvalidOperation", new Type[] { typeof(string) }, null), null, "Explicit Entry");
            Queue(typeof(ExceptionHelper).GetMethod("ThrowArgumentOutOfRange", new Type[] { typeof(string) }, null), null, "Explicit Entry");

            // register system types:
            Queue(typeof(Array), null, "Explicit Entry");
            Queue(typeof(Array).GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance).First(), null, "Explicit Entry");
            Queue(typeof(MulticastDelegate).GetMethod("GetInvocationList"), null, "Explicit Entry");
            Queue(ExceptionHelperRefs.CurrentExceptionRef, null, "Explicit Entry");
            Queue(ExceptionHelperRefs.ThrowInvalidCastExceptionRef, null, "Explicit Entry");
            Queue(ExceptionHelperRefs.ThrowNotFiniteNumberExceptionRef, null, "Explicit Entry");

            mAsmblr.ProcessField(typeof(string).GetField("Empty", BindingFlags.Static | BindingFlags.Public));

            // Start from entry point of this program
            Queue(aStartMethod, null, "Entry Point");

            ScanQueue();
            UpdateAssemblies();
            Assemble();

            mAsmblr.EmitEntrypoint(aStartMethod);
        }