Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[generator] Add support for peerConstructorPartialMethod (#1087)
Context: #1085 Context: dotnet/runtime#82121 Some Java objects are *big*, e.g. [`Bitmap`][0] instances, but as far as MonoVM is concerned, the `Bitmap` instances are *tiny*: a few pointers, and that's it. MonoVM doesn't know that it could be referencing several MB of data in the Java VM. MonoVM is gaining support for [`GC.AddMemoryPressure()`][1] and [`GC.RemoveMemoryPressure()`][2], which potentially allows for the parent of all cross-VM GC integrations: using the `GC` methods to inform MonoVM of how much non-managed memory has been allocated. This could allow MonoVM to collect more frequently when total process memory is low. How should we call `GC.AddMemoryPressure()` and `GC.RemoveMemoryPressure()`? `GC.RemoveMemoryPressure()` is straightforward: a class can override `Java.Lang.Object.Dispose(bool)`. `GC.AddMemoryPressure()` is the problem: where and how can it be called from a class binding? This is trickier, as there was no way to have custom code called by the bound type. Instead, various forms of "hacky workarounds" are often employed, e.g. copying `generator`-emitted content into a `partial` class, then using `metadata` to *prevent* `generator` from binding those members. It's all around fugly. Fortunately C# has a solution: [`partial` methods][3]! Add support for a `peerConstructorPartialMethod` metadata entry, applicable to `<class/>` elements, which contains the name of a `partial` method to both declare and invoke from the "peer constructor": <attr path="//class[@name='Bitmap']" name="peerConstructorPartialMethod" >_OnBitmapCreated</attr> This will alter our existing "peer constructor" generation code, a'la: partial class Bitmap : Java.Lang.Object { internal Bitmap (IntPtr h, JniHandleOwnership t) : base (h, t) { } } to instead become: partial class Bitmap : Java.Lang.Object { partial void _OnBitmapCreated (); internal Bitmap (IntPtr h, JniHandleOwnership t) : base (h, t) { _OnBitmapCreated (); } } This allows a hand-written `partial class Bitmap` to do: // Hand-written code partial class Bitmap { int _memoryPressure; partial void _OnBitmapCreated () { _memoryPressure = ByteCount; GC.AddMemoryPressure (_memoryPressure); } protected override void Dispose (bool disposing) { if (_memoryPressure != 0) { GC.RemoveMemoryPressure (_memoryPressure); _memoryPressure = 0; } } } TODO: "extend" this for `<method/>`s as well? [0]: https://developer.android.com/reference/android/graphics/Bitmap [1]: https://learn.microsoft.com/dotnet/api/system.gc.addmemorypressure?view=net-7.0 [2]: https://learn.microsoft.com/dotnet/api/system.gc.removememorypressure?view=net-7.0 [3]: https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/partial-method
- Loading branch information