public unsafe ExecutionResult Execute(Assembly assembly, RuntimeGuardToken guardToken, IWorkSession session) { try { Output.Reset(); Flow.Reset(); Console.SetOut(Output.Writer); var main = assembly.EntryPoint; if (main == null) { throw new ArgumentException("Entry point not found in " + assembly, nameof(assembly)); } using (guardToken.Scope(NewRuntimeGuardSettings())) { var args = main.GetParameters().Length > 0 ? new object[] { new string[0] } : null; PerformanceLog.Checkpoint("Executor.Invoke.Start"); var result = main.Invoke(null, args); PerformanceLog.Checkpoint("Executor.Invoke.End"); if (main.ReturnType != typeof(void)) { result.Inspect("Return"); } return(new ExecutionResult(Output.Stream, Flow.Steps)); } } catch (Exception ex) { PerformanceLog.Checkpoint("Executor.Invoke.Exception"); if (ex is TargetInvocationException invocationEx) { ex = invocationEx.InnerException ?? ex; } if (ex is RegexMatchTimeoutException) { ex = new TimeGuardException("Time limit reached while evaluating a Regex.\r\nNote that timeout was added by SharpLab — in real code this would not throw, but might run for a very long time.", ex); } if (ex is StackGuardException sgex) { throw new Exception($"{sgex.Message} {sgex.StackBaseline} {sgex.StackOffset} {sgex.StackLimit} {sgex.StackSize}"); } Flow.ReportException(ex); Output.Write(new SimpleInspection("Exception", ex.ToString())); if (ShouldMonitorException(ex)) { _monitor.Exception(ex !, session); } return(new ExecutionResult(Output.Stream, Flow.Steps)); } }
private void AddToCaches(IReadOnlyCollection <string> assemblyPaths) { PerformanceLog.Checkpoint("PreCachedAssemblyResolver.AddToCaches.Start"); foreach (var path in assemblyPaths) { var file = new PEFile(path); _peFileCache.TryAdd(file.Name, file); var definition = AssemblyDefinition.ReadAssembly(path); _cecilCache.TryAdd(definition.Name.Name, definition); } PerformanceLog.Checkpoint("PreCachedAssemblyResolver.AddToCaches.End"); }
public static MirrorSharpOptions CreateMirrorSharpOptions(ILifetimeScope container) { var options = new MirrorSharpOptions { IncludeExceptionDetails = true }; var languages = container.Resolve <ILanguageAdapter[]>(); foreach (var language in languages) { language.SlowSetup(options); } PerformanceLog.Checkpoint("Startup.CreateMirrorSharpOptions.End"); return(options); }
public static MirrorSharpOptions CreateMirrorSharpOptions(ILifetimeScope container) { var options = new MirrorSharpOptions { SetOptionsFromClient = container.Resolve <ISetOptionsFromClientExtension>(), SlowUpdate = container.Resolve <ISlowUpdateExtension>(), IncludeExceptionDetails = true, ExceptionLogger = container.Resolve <IExceptionLogger>() }; var languages = container.Resolve <ILanguageAdapter[]>(); foreach (var language in languages) { language.SlowSetup(options); } PerformanceLog.Checkpoint("Startup.CreateMirrorSharpOptions.End"); return(options); }
public ExecutionResult Execute(CompilationStreamPair streams, IWorkSession session) { var readerParameters = new ReaderParameters { ReadSymbols = streams.SymbolStream != null, SymbolStream = streams.SymbolStream, AssemblyResolver = _assemblyResolver, SymbolReaderProvider = streams.SymbolStream != null ? _symbolReaderProvider : null }; using (streams) using (var definition = AssemblyDefinition.ReadAssembly(streams.AssemblyStream, readerParameters)) { foreach (var rewriter in _rewriters) { rewriter.Rewrite(definition, session); } PerformanceLog.Checkpoint("Executor.Rewrite.Flow.End"); AssemblyLog.Log("2.WithFlow", definition); if (definition.EntryPoint == null) { Output.Reset(); Flow.Reset(); Output.WriteWarning("Could not find any code to run (either a Main method or any top level code)."); return(new ExecutionResult(Output.Stream, Flow.Steps)); } var guardToken = AssemblyGuard.Rewrite(definition, _guardSettings); using (var rewrittenStream = _memoryStreamManager.GetStream()) { definition.Write(rewrittenStream); AssemblyLog.Log("3.Unbreakable", definition); rewrittenStream.Seek(0, SeekOrigin.Begin); PerformanceLog.Checkpoint("Executor.Rewrite.Unbreakable.End"); using (var context = new CustomAssemblyLoadContext(shouldShareAssembly: ShouldShareAssembly)) { var assembly = context.LoadFromStream(rewrittenStream); PerformanceLog.Checkpoint("Executor.AssemblyLoad.End"); return(Execute(assembly, guardToken, session)); } } } }
public ExecutionResult Execute(CompilationStreamPair streams, IWorkSession session) { var readerParameters = new ReaderParameters { ReadSymbols = streams.SymbolStream != null, SymbolStream = streams.SymbolStream, AssemblyResolver = _assemblyResolver, SymbolReaderProvider = streams.SymbolStream != null ? _symbolReaderProvider : null }; using (streams) using (var definition = AssemblyDefinition.ReadAssembly(streams.AssemblyStream, readerParameters)) { AssemblyLog.Log("1.Initial", definition); foreach (var rewriter in _rewriters) { rewriter.Rewrite(definition, session); } PerformanceLog.Checkpoint("Executor.Rewrite.Flow.End"); AssemblyLog.Log("2.WithFlow", definition); if (definition.EntryPoint == null) { throw new ArgumentException("Failed to find an entry point (Main?) in assembly.", nameof(streams)); } var guardToken = AssemblyGuard.Rewrite(definition, _guardSettings); using (var rewrittenStream = _memoryStreamManager.GetStream()) { definition.Write(rewrittenStream); AssemblyLog.Log("3.Unbreakable", definition); rewrittenStream.Seek(0, SeekOrigin.Begin); PerformanceLog.Checkpoint("Executor.Rewrite.Unbreakable.End"); using (var context = new CustomAssemblyLoadContext(shouldShareAssembly: ShouldShareAssembly)) { var assembly = context.LoadFromStream(rewrittenStream); PerformanceLog.Checkpoint("Executor.AssemblyLoad.End"); return(Execute(assembly, guardToken, session)); } } } }
public async Task <(bool assembly, bool symbols)> TryCompileToStreamAsync(MemoryStream assemblyStream, MemoryStream?symbolStream, IWorkSession session, IList <Diagnostic> diagnostics, CancellationToken cancellationToken) { PerformanceLog.Checkpoint("Compiler.TryCompileToStreamAsync.Start"); if (session.IsFSharp()) { var compiled = await TryCompileFSharpToStreamAsync(assemblyStream, session, diagnostics, cancellationToken).ConfigureAwait(false); return(compiled, false); } #warning TODO: Revisit after https://github.com/dotnet/docs/issues/14784 var compilation = (await session.Roslyn.Project.GetCompilationAsync(cancellationToken).ConfigureAwait(false)) !; var emitResult = compilation.Emit(assemblyStream, pdbStream: symbolStream, options: RoslynEmitOptions); PerformanceLog.Checkpoint("Compiler.TryCompileToStreamAsync.Emit.End"); if (!emitResult.Success) { foreach (var diagnostic in emitResult.Diagnostics) { diagnostics.Add(diagnostic); } return(false, false); } return(true, true); }
public async Task <object?> ProcessAsync(IWorkSession session, IList <Diagnostic> diagnostics, CancellationToken cancellationToken) { PerformanceLog.Checkpoint("SlowUpdate.ProcessAsync.Start"); var targetName = GetAndEnsureTargetName(session); if (targetName == TargetNames.Ast || targetName == TargetNames.Explain) { var astTarget = _astTargets[session.LanguageName]; var ast = await astTarget.GetAstAsync(session, cancellationToken).ConfigureAwait(false); if (targetName == TargetNames.Explain) { return(await _explainer.ExplainAsync(ast, session, cancellationToken).ConfigureAwait(false)); } return(ast); } if (diagnostics.Any(d => d.Severity == DiagnosticSeverity.Error)) { return(null); } if (targetName == LanguageNames.VisualBasic) { return(VisualBasicNotAvailable); } if (targetName != TargetNames.Run && targetName != TargetNames.Verify && !_decompilers.ContainsKey(targetName)) { throw new NotSupportedException($"Target '{targetName}' is not (yet?) supported by this branch."); } MemoryStream?assemblyStream = null; MemoryStream?symbolStream = null; try { assemblyStream = _memoryStreamManager.GetStream(); if (targetName == TargetNames.Run || targetName == TargetNames.IL) { symbolStream = _memoryStreamManager.GetStream(); } var compiled = await _compiler.TryCompileToStreamAsync(assemblyStream, symbolStream, session, diagnostics, cancellationToken).ConfigureAwait(false); if (!compiled.assembly) { assemblyStream.Dispose(); symbolStream?.Dispose(); return(null); } if (targetName == TargetNames.Verify) { assemblyStream.Dispose(); symbolStream?.Dispose(); return("✔️ Compilation completed."); } assemblyStream.Seek(0, SeekOrigin.Begin); symbolStream?.Seek(0, SeekOrigin.Begin); var streams = new CompilationStreamPair(assemblyStream, compiled.symbols ? symbolStream : null); if (targetName == TargetNames.Run) { return(_executor.Execute(streams, session)); } // it's fine not to Dispose() here -- MirrorSharp will dispose it after calling WriteResult() return(streams); } catch { assemblyStream?.Dispose(); symbolStream?.Dispose(); throw; } }
public async Task <object?> ProcessAsync(IWorkSession session, IList <Diagnostic> diagnostics, CancellationToken cancellationToken) { PerformanceLog.Checkpoint("SlowUpdate.ProcessAsync.Start"); var targetName = GetAndEnsureTargetName(session); _topLevelProgramSupport.UpdateOutputKind(session, diagnostics); if (targetName is TargetNames.Ast or TargetNames.Explain) { var astTarget = _astTargets[session.LanguageName]; var ast = await astTarget.GetAstAsync(session, cancellationToken).ConfigureAwait(false); if (targetName == TargetNames.Explain) { return(await _explainer.ExplainAsync(ast, session, cancellationToken).ConfigureAwait(false)); } return(ast); } if (diagnostics.Any(d => d.Severity == DiagnosticSeverity.Error)) { return(null); } if (targetName == LanguageNames.VisualBasic) { return(VisualBasicNotAvailable); } if (targetName is not(TargetNames.Run or TargetNames.Verify) && !_decompilers.ContainsKey(targetName)) { throw new NotSupportedException($"Target '{targetName}' is not (yet?) supported by this branch."); } MemoryStream?assemblyStream = null; MemoryStream?symbolStream = null; try { assemblyStream = _memoryStreamManager.GetStream(); if (targetName is TargetNames.Run or TargetNames.IL) { symbolStream = _memoryStreamManager.GetStream(); } var compilationStopwatch = session.ShouldReportPerformance() ? Stopwatch.StartNew() : null; var compiled = await _compiler.TryCompileToStreamAsync(assemblyStream, symbolStream, session, diagnostics, cancellationToken).ConfigureAwait(false); compilationStopwatch?.Stop(); if (!compiled.assembly) { assemblyStream.Dispose(); symbolStream?.Dispose(); return(null); } if (targetName == TargetNames.Verify) { assemblyStream.Dispose(); symbolStream?.Dispose(); return("✔️ Compilation completed."); } assemblyStream.Seek(0, SeekOrigin.Begin); symbolStream?.Seek(0, SeekOrigin.Begin); AssemblyLog.Log("1.Compiled", assemblyStream, compiled.symbols ? symbolStream : null); var streams = new CompilationStreamPair(assemblyStream, compiled.symbols ? symbolStream : null); if (targetName == TargetNames.Run) { if (!session.HasContainerExperimentFailed()) { try { var output = await _containerExecutor.ExecuteAsync(streams, session, cancellationToken); if (compilationStopwatch != null) { // TODO: Prettify output += $"\n COMPILATION: {compilationStopwatch.ElapsedMilliseconds,15}ms"; } streams.Dispose(); _monitor.Metric(ContainerExperimentMetrics.ContainerRunCount, 1); return(output); } catch (Exception ex) { _monitor.Metric(ContainerExperimentMetrics.ContainerFailureCount, 1); _monitor.Exception(ex, session); session.SetContainerExperimentException(ex); assemblyStream.Seek(0, SeekOrigin.Begin); symbolStream?.Seek(0, SeekOrigin.Begin); } } _monitor.Metric(ContainerExperimentMetrics.LegacyRunCount, 1); return(_executor.Execute(streams, session)); } // it's fine not to Dispose() here -- MirrorSharp will dispose it after calling WriteResult() return(streams); } catch { assemblyStream?.Dispose(); symbolStream?.Dispose(); throw; } }