Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mono Method Body Replacement #44806

Closed
51 tasks done
Tracked by #5456
lambdageek opened this issue Nov 17, 2020 · 7 comments
Closed
51 tasks done
Tracked by #5456

Mono Method Body Replacement #44806

lambdageek opened this issue Nov 17, 2020 · 7 comments
Assignees
Labels
area-EnC-mono Hot Reload for WebAssembly, iOS/Android, etc hard-problem tracking This issue is tracking the completion of other related issues.
Milestone

Comments

@lambdageek
Copy link
Member

lambdageek commented Nov 17, 2020

Contributes to dotnet/xamarin#13 and dotnet/aspnetcore#5456

Overview

The goal of Mono method body replacement is to improve the inner dev loop experience for customers using Xamarin to create mobile apps and those using Blazor to create WebAssembly projects.

Method body replacement is a subset of a more general hot reload experience with a restricted subset of allowed edits. Non-supported ("rude") edits will generally be rejected by the tooling outside the runtime, however the runtime
itself should be transactional in that a change is either committed by the runtime in total or else it is rejected and the runtime state is unchanged.

The changes are delivered to the runtime using the EnC "dmeta" and "DIL" (and "DPDB") delta files. If the changes are accepted, then future invocations of methods affected by the delta will use the new method bodies. Currently executing versions of the methods will use the previous versions.

Multiple versions of changes can be applied in succession. Once a change is applied, it cannot be unapplied (but of course a new change can be used to undo the previous change). For collectible ALCs unloading the assembly will unload all its changes.

Method body replacement will only be supported with the Mono interpreter with inlining turned off. The DOTNET_MODIFIABLE_ASSEMBLIES environment variable must be set to the (case-insensitive) value debug. The assemblies that are eligible for modifications must be compiled with the /debug option.

Method body replacement will not interfere with debugging.

Metadata deltas will be injected either using the debugger or using a managed API. If the debugger is not involved, the runtime will pause the executing user threads at critical points during the update.

End to end scenarios

Tasks

Priority 0

Priority 1

Future (.net7 +)

Moved to #57365

Bugs

@lambdageek lambdageek added hard-problem area-VM-meta-mono tracking This issue is tracking the completion of other related issues. Team Epic labels Nov 17, 2020
@ghost
Copy link

ghost commented Nov 17, 2020

Tagging subscribers to this area: @CoffeeFlux
See info in area-owners.md if you want to be subscribed.

Issue Details
Description:

Method Body Replacement

Contributes to dotnet/xamarin#13 and dotnet/aspnetcore#5456

Overview

The goal of Mono method body replacement is to improve the inner dev loop experience for customers using Xamarin to create mobile apps and those using Blazor to create WebAssembly projects.

Method body replacement is a subset of a more general hot reload experience with a restricted subset of allowed edits. Non-supported ("rude") edits will generally be rejected by the tooling outside the runtime, however the runtime
itself should be transactional in that a change is either committed by the runtime in total or else it is rejected and the runtime state is unchanged.

The changes are delivered to the runtime using the EnC "dmeta" and "DIL" (and "DPDB") delta files. If the changes are accepted, then future invocations of methods affected by the delta will use the new method bodies. Currently executing versions of the methods will use the previous versions.

Method body replacement will only be supported with the Mono interpreter with inlining turned off.

Method body replacement will not interfere with debugging.

Metadata deltas will be injected either using the debugger or using another API. If the debugger is not involved, the runtime will pause the executing user threads at critical points during the update.

Tasks

Priority 0

  • Put the metadata update work-in-progress under a compile-time feature flag and merge to dotnet/runtime master
  • Investigate what happens with debugger attached
    • Add support for consuming "dpdb" debugger file deltas
    • What should happen if there is a breakpoint in an old version of a method - migrate breakpoint to new version or keep both? How should a breakpoint hit in a previous version of a method be reported to the debugger frontend?
  • Properly detect cases we don't support, backout metadata updates and raise a managed exception
  • Investiage MonoImage refcount mistake - fix the shutdown hack (exe_image)
  • set compile time feature flag to on by default (in debug builds?), put under runtime feature flag
  • set up testing infrastructure and run CI
    • publish external testing artifact that our CI will depend on
    • msbuild task for working with pre-canned deltas
  • Publish wasm, android and ios Debug runtime packs with MBR support

Priority 1

  • Support mixed AOT/interp hybrid mode
  • Support adding nested classes, lambdas and async methods
  • Propose and implement an API event that can be used to notify frameworks that a change was applied.
  • Implement additional

Future

  • Type system additions (static fields, static methods, virtual method overrides, etc)

Out of scope

  • Type system modifications
  • Active statements / On-stack replacement
  • Object migration
  • JIT support
Author: lambdageek
Assignees: -
Labels:

Team Epic, area-VM-meta-mono, hard problem, tracking

Milestone: -

@Dotnet-GitSync-Bot Dotnet-GitSync-Bot added the untriaged New issue has not been triaged by the area owner label Nov 17, 2020
@lambdageek lambdageek removed the untriaged New issue has not been triaged by the area owner label Nov 17, 2020
@lambdageek lambdageek self-assigned this Nov 17, 2020
@lambdageek lambdageek added this to the 6.0.0 milestone Nov 17, 2020
@srxqds
Copy link
Contributor

srxqds commented Nov 17, 2020

why not support for jit?

@srxqds
Copy link
Contributor

srxqds commented Dec 5, 2020

hope you can support it in jit mode

@lambdageek
Copy link
Member Author

@srxqds The reason we're initially focusing on the interpreter is both for practical implementation reasons and due to the use-case that we're targeting. The use-case is Blazor WebAssembly and Xamarin mobile developers who are iterating on their code. This functionality is intended to be an improvement to the developer experience, not something that we expect developers to ship in production to end-users. For this use-case, it made sense to focus on the interpreter - because that's all that is available for WebAssembly, and it can also be supported on mobile.

The practical engineering reason is because this is going to involve a lot of changes at a foundational level in Mono. There are basically three places where we will need to make changes: in the low-level code that deals with .NET IL metadata; in the type system representation (MonoClass etc); and in the compilation stage and the execution engine. The advantage of doing interpreter first is that it has a relatively isolated compilation (inter/transform.c) and there is a single place where the code to be executed is looked up. So we can make a small change that we are pretty sure won't lead to a ton of bugs.

So we can focus on making changes to the metadata and the type system without also having to deal with the compilation and execution engine at the same time.

Once the metadata and typesystem changes are stable, it might make sense to look at the JIT, but right now it would just be a distraction.

@srxqds
Copy link
Contributor

srxqds commented Dec 7, 2020

@srxqds The reason we're initially focusing on the interpreter is both for practical implementation reasons and due to the use-case that we're targeting. The use-case is Blazor WebAssembly and Xamarin mobile developers who are iterating on their code. This functionality is intended to be an improvement to the developer experience, not something that we expect developers to ship in production to end-users. For this use-case, it made sense to focus on the interpreter - because that's all that is available for WebAssembly, and it can also be supported on mobile.

The practical engineering reason is because this is going to involve a lot of changes at a foundational level in Mono. There are basically three places where we will need to make changes: in the low-level code that deals with .NET IL metadata; in the type system representation (MonoClass etc); and in the compilation stage and the execution engine. The advantage of doing interpreter first is that it has a relatively isolated compilation (inter/transform.c) and there is a single place where the code to be executed is looked up. So we can make a small change that we are pretty sure won't lead to a ton of bugs.

So we can focus on making changes to the metadata and the type system without also having to deal with the compilation and execution engine at the same time.

Once the metadata and typesystem changes are stable, it might make sense to look at the JIT, but right now it would just be a distraction.

ok, thank you for reply.

monojenkins pushed a commit to monojenkins/mono that referenced this issue Jan 9, 2021
First part of support for metadata updates.

Contributes to dotnet/runtime#44806

The feature is off by default.  To enable, build with `/p:MonoMetadataUpdate=true` (e.g. `./build.sh --os browser /p:MonoMetadataUpdate=true`).  There are samples in `src/mono/netcore/sample/mbr` (see the README - the samples aren't completely standalone and need some external tooling to build) for console (only tested on Mac and Linux) and wasm.

There's a demo at https://lambdageek.dev/dl0/
lambdageek added a commit to mono/mono that referenced this issue Jan 11, 2021
First part of support for metadata updates.

Contributes to dotnet/runtime#44806

The feature is off by default.  To enable, build with `/p:MonoMetadataUpdate=true` (e.g. `./build.sh --os browser /p:MonoMetadataUpdate=true`).  There are samples in `src/mono/netcore/sample/mbr` (see the README - the samples aren't completely standalone and need some external tooling to build) for console (only tested on Mac and Linux) and wasm.

There's a demo at https://lambdageek.dev/dl0/

* Initial metadata-update prototype

Co-Authored-By: Bernhard Urban-Forster <lewurm@gmail.com>

* Add metadata-update.{c,h} to CMakeLists.txt

* Add icall to corelib

* Add console and browser metadata update samples

   Both samples depend on the roslynildiff tool which should be specified with a RoslynILDiffFullPath property in the .csproj files for the projects.

* Add README for mbr samples

* [build] Add initial runtime support for MonoMetadataUpdate property

   In the runtime defines cmake ENABLE_METADATA_UPDATE option and sets a preprocessor flag.

   In System.Private.CoreLib, defines FEATURE_METADATA_UPDATE and uses it to throw a NotSupportedException from LoadMetadataUpdate

* [runtime] ifdef out metadata updates if not enabled

   Also move execution engine initialization into the main update function and use a MonoError to signal failures (such as if interp inlining is not turned off) instead of asserting at startup.

* [wasm] set log mask to metadata-update

* [mbr] Add InjectUpdate fn to sample

* [metadata-update] don't merge heaps

* Don't make entrypoint public yet

* Add LoadMetadataUpdate to linker descriptor

* [wasm] add default Makefile variable value

* fix mono/mono CI

   don't try to run enc tests yet since they depend on roslynildiff

* remove mono/mono/tests/enc

   Will add as runtime tests in a future PR

* [metadata-update] Add per-thread exposed generation

   A thread has to voluntarily roll up to the latest published generation in order to see updates.

   - Roll up to the latest published generation when attaching a thread
   - The updater thread sees the allocated unpublished generation

* [mbr] Fixup console sample

   Use a single changing testfile

* [metadata-update] delete unused method

* [mbr] Use 2 threads in console sample

* [metadata-update] Respect exposed generation in MethdDef RVA lookups

* [interp] Expose latest metadata update before transforming methods

* [mbr] Update samples after rebase

   Use the WasmApp.targets

* [metadata-update] Don't fail after the first unsupported edit

   Log all the unsupported edits, then cancel the update

* [metadata_update] Keep track of logical table sizes for deltas

   Keep track of inserted/modified rows for each table in each delta. This will help to use a simpler algorithm to locate effective table rows by keeping track of the logical number of rows in the appended tables

* [metadata-update] Use a GList for MonoImage:delta_image

   We're going to need to walk backwards from the latest published delta

* [metadata-update] add effective table lookup debug output

* Address review feedback

* [interp] Save top interp frame at MINT_SAFEPOINT to ThreadContext

   Give metadata updates a peek at the interp frames since the LMF so that it can copy the InterpMethods that are currently executing

   This only works with hybrid and full coop suspend.  Preemptive suspend will need another mechanism.

* [mbr] Extend console sample

   Add a busy thread to demonstrate that interp frames since the last managed frame are visible to the metadata update mechanism and the active method bodies are copied before being invalidated.

* [interp] Check mono_polling_required at safepoint

Co-authored-by: Bernhard Urban-Forster <lewurm@gmail.com>
Co-authored-by: lambdageek <lambdageek@users.noreply.github.com>
lambdageek added a commit to mono/debugger-libs that referenced this issue Mar 3, 2021
[Mono.Debugger.Soft] add ModuleMirror.ApplyChanges
[Mono.Debugging.Soft] add SoftDebuggerSession.ApplyChanges
Related mono/mono Mono.Debugger.Soft PR: mono/mono#20889
Related dotnet/runtime PR: dotnet/runtime#49043

Contributes to dotnet/runtime#44806
@lambdageek lambdageek added area-EnC-mono Hot Reload for WebAssembly, iOS/Android, etc and removed area-VM-meta-mono labels Apr 23, 2021
@srxqds
Copy link
Contributor

srxqds commented Jun 22, 2021

hi, when can you begin to support add static fields and methods to existing classes work?

@lambdageek
Copy link
Member Author

Pushed the future work to a separate tracking issue. This one is done. #57365

@ghost ghost locked as resolved and limited conversation to collaborators Sep 12, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-EnC-mono Hot Reload for WebAssembly, iOS/Android, etc hard-problem tracking This issue is tracking the completion of other related issues.
Projects
None yet
Development

No branches or pull requests

4 participants