public void Execute(SysReflection.MethodBase aStartMethod) { if (aStartMethod == null) { throw new ArgumentNullException("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 mPlugManager.FindPlugImpls(); // 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}'"); } ILOp.mPlugManager = mPlugManager; // Pull in extra implementations, GC etc. Queue(RuntimeEngineRefs.InitializeApplicationRef, null, "Explicit Entry"); Queue(RuntimeEngineRefs.FinalizeApplicationRef, null, "Explicit Entry"); //Queue(typeof(CosmosAssembler).GetMethod("PrintException"), null, "Explicit Entry"); Queue(VTablesImplRefs.SetMethodInfoRef, null, "Explicit Entry"); Queue(VTablesImplRefs.IsInstanceRef, null, "Explicit Entry"); Queue(VTablesImplRefs.SetTypeInfoRef, null, "Explicit Entry"); Queue(VTablesImplRefs.GetMethodAddressForTypeRef, 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", BindingFlags.Static | BindingFlags.Public, null, new Type[] { typeof(string) }, null), null, "Explicit Entry"); Queue(typeof(ExceptionHelper).GetMethod("ThrowOverflow", BindingFlags.Static | BindingFlags.Public, null, new Type[] { }, null), null, "Explicit Entry"); Queue(RuntimeEngineRefs.InitializeApplicationRef, null, "Explicit Entry"); Queue(RuntimeEngineRefs.FinalizeApplicationRef, null, "Explicit Entry"); // register system types: Queue(typeof(Array), null, "Explicit Entry"); Queue(typeof(Array).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, Type.EmptyTypes, null), null, "Explicit Entry"); var xThrowHelper = Type.GetType("System.ThrowHelper", true); Queue(xThrowHelper.GetMethod("ThrowInvalidOperationException", BindingFlags.NonPublic | BindingFlags.Static), null, "Explicit Entry"); Queue(typeof(MulticastDelegate).GetMethod("GetInvocationList"), null, "Explicit Entry"); Queue(ExceptionHelperRefs.CurrentExceptionRef, null, "Explicit Entry"); //System_Delegate____System_MulticastDelegate_GetInvocationList__ // Start from entry point of this program Queue(aStartMethod, null, "Entry Point"); ScanQueue(); UpdateAssemblies(); Assemble(); mAsmblr.EmitEntrypoint(aStartMethod); }