| .NET follows platform calling convention. GC reference assignment to a memory location does involve going through a write barrier (main user of which is concurrent mark phase of GC) but otherwise it's just plain Windows or System V ABI for the respective ISA. Practically speaking, you cannot call .NET methods directly unless they are annotated with [UnmanagedCallersOnly] which is necessary to ensure GC is in consistent state, module initializers have ran, etc. This is a concern for NativeAOT libraries as you don't have to explicitly call their entrypoint before calling them AFAIK. This, however, is true for most languages that are not C. This is also a constraint for both Swift, which has its own reference counting and ABI (Library Evolution ABI) and likely Vala assuming it is reference counted. The runtime vs runtime-less arguments are not exactly helpful given the context - there are """runtime"""-heavy interpreted languages like Python, Elixir or JS, there is Java which assumes JVM, but is already lower level, and then there's .NET, which under the hood looks a lot like a strange flavour of C++ when you e.g. inspect the AOT binaries with Ghidra. Fun fact, native profilers work with NAOT applications transparently on all platforms. You can hit "sample" in activity monitor on macOS and it will show you fully symbolicated trace if symbols are available. Just recently, I used Samply to perform multi-threaded profiling and it worked just as well as it would for something written in Rust, if not better. |
That’s an enormous difference in ABI.