Mono hot reload reorg and beginning (disabled) add method support (#61853)
This PR does two things:
1. Reorganizes how we keep track of deltas, and how we do metadata lookups after updates
2. Adds an ifdefed-out initial draft of support for adding methods. (It worked for a simple test but it's not ready for general use yet).
Details of the delta changes.
* Previously Mono used a fully immutable model of metadata changes. Logically each delta brings in modifications to existing table rows and addition of new rows. Previously mono never formed the fully mutated tables - instead, each lookup was essentially responsible for playing all the changes forward every time it needed to lookup a row. This was fine when we primarily supported only row additions (because we could just skip past all the updates that hadn't added the row we wanted yet, and just look in a single delta). But as we started to support more and more modifications (of custom attributes, of property getters & setters, of parameters, etc) we now had to look through the whole list of deltas to make sure we found the latest modification of every row.
* The new approach is for each `DeltaInfo` (representing a summary of a particular update to a single assembly) to contain a collection of `mutants` - the fully modified tables with all the newly added rows and all the new modifications. So lookups are fast now - we just go to the latest generation that is visible to a particular thread and look at its mutants tables. The downside is increased memory use. So we allocate the mutants from memory pools owned by each `DeltaInfo`. Right now we never dealloc the pools, but in the future we could. We already iterate over all the threads during our stop-the-world phase - we can record the earliest generation still needed by every thread and delete the pools for all earlier copies. In practice this means we only keep 3 sets of tables: the mmaped baseline tables, the newest mutants, and the mutants from the prior generation for any still-executing methods.
* Additionally instead of storing a list of delta images in the `BaselineInfo`, we now store a list of `DeltaInfo` structs which each `DeltaInfo` pointing to a delta image. This means that we can avoid repeated hash table lookups to map from a delta image to its `DeltaInfo` every time the runtime queries us for a table row or for a heap element.
---
* checkpoint: allow adding methods to existing classes.
Doesn't do anything yet.
And needs more sanity checking (roslyn won't give us virtual or abstract
methods, but we should check).
* fixme in loader
* [metadata] Add mono_metadata_table_num_rows
Returns the number of rows in a metadata table, taking into account metadata
update deltas
* add table to ptr table helper
* Param attr lookups for deltas can have param_index == 0
The params are added with a subsequent enclog "add param" function.
* WIP: start adding support for parameter additions.
It "works" in that calling methods appears to work (ie direct token references
seem to do the right thing).
Primarily this is because the param table additions are not that interesting.
All the good stuff is in the method signature (which is just in the blob heap).
Presumably anything that actually needs parameter attributes, or anything that
uses reflection to look at the parameters, will break.
* WIP: add MethodDef -> TypeDef lookup
Allows calling non-public methods, which are now assigned the correct parent
* Add hot reload test for lambda capturing this
Lambdas that only capture `this` (and not local variables or arguments) compile
to a private instance method in the enclosing class. So it is enough to
support EnC deltas that add methods.
* clarify comments about MONO_METHOD_PARAMLIST
* [hot_reload] Store debug info of updated methods
* [hot_reload] Allocate modifiable tables in DeltaInfo
This is the foundation for a new approach for metadata lookups.
Instead of using an immutable model (each lookup traverses every delta to find
the most up to date version of each table row), we are going to create a
complete updated table for each generation and only do the lookup in the latest
exposed generation directly. (This is essentially the CoreCLR model).
This commit is just the first foundations: we allocate the tables and copy over
the previous generations' rows and zero out any rows that will be inserted.
Delta applications and lookups have not been updated yet.
As a slight optimization, tables that don't have modified or added rows are not
copied from the base image. If a generation modifies or adds rows, from that
point forward, each subsequent generation will copy the table.
We could be a bit more thrifty with copying, but it will complicate lookups.
Also eventually we will try to deallocate the pools for generations that are
older than no thread needs anymore.
Metadata heaps are still looked up in each delta directly - heap combining does
not seem necessary yet.
* [mini] Allow MONO_VERBOSE_METHOD='*:*'
Implement method name wildcard matching for method descriptions
Globbing doesn't work because we don't have g_pattern_match_simple in eglib.
But a plain '*' wildcard does work.
* populate mutated table rows
leave suppressed columns unchanged
* [hot_reload] Switch lookups to the mutant tables
* cleanup: remove of effective_table calculation
The row index doesn't change in the new scheme, pass it by value
* cleanup: Remove relative_delta_index from component API
It's only used internally by the update logic
* cleanup: Pass DeltaInfo to relative_delta_index
don't compute it from the dmeta image
* cleanup: Store a list of DeltaInfo in the BaselineInfo
Instead of storing a list of delta images and then relying on delta_info_lookup
to find the DeltaInfo, just store them directly on the baseline info.
This changes the cleanup responsibilities a bit. Now we destroy the DeltaInfo
when we are iterate through the delta infos when we close the baseline image,
instead of when we remove the delta_image_to_info hashtable entry.
* Turn off method addition support, for now
Just want to get the cleanups enabled for now
* Fix null ptr when checking for updated ppdb info
13 files changed: