All of the cool and quirky stuff it did was solely to support waterbox, which has its own native impl of this now. So now it just lets you allocate memory and change protection on it. Boring. Note that the slot based callback system in waterbox gives constant function pointer addresses inside the box, so it doesn't matter where exactly CallingConventionAdapter is allocated.
Waterbox guest code now runs on a stack inside the guest memory space. This removes some potential opportunities for nondeterminism and makes future porting of libco-enabled cores easier.
This replaces the old managed one. The only direct effect of this is to fix some hard to reproduce crashes in bsnes.
In the long run, we'll use this new code to help build more waterbox features.
According to the rules (which are hard to find), there must be nothing on the evaluation stack when localloc is called (except its own size parameter). The generated string interop code didn't respect that. This didn't cause any problems in existing code.
Cores that used the .invisible section to store data were saving it; this was a regression from before, so PCFX states should be back down to the previous release size, or perhaps a bit smaller.
Add the ability to dirty track libco cothreads, as used in the bsnes core. This saves a lot of space in those states and they're now quite competitive in size.
The waterbox system now uses host os facilities to track whether memory has been written to, to automatically choose what thing to savestate. This results in a large size decrease for some cores, like snes9x or gpgx (when running cartridge games). Doesn't do much for cores that were already memory efficient, or for bsnes because of libco compatibility issues; but those cores don't regress either.
If a particular core instance doesn't use up too much memory, then we don't charge the host OS for that memory.
The strange thing here is that, testing locally on Windows 10, we were already getting the desired semantics even with SEC_COMMIT and not SEC_RESERVE. This commit is still important because:
1) Windows might be providing me an optimization it can't guarantee,
2) Linux might not be able to provide the same optimization
3) In any event, this patch also trims down xor snapshots to match the actual needed size.
The existing code had a lot of copy paste and things that needed to be done twice to keep both impls in sync. Refactor to use a minimal abstraction layer and keep all other code common
The refactoring of platform abstractions should never have changed the name of the public interface. No one cares about MemoryBlockWindows or MemoryBlockUnix - those names are impl details.
It'd be one thing if we needed a sentinel value distinct from IntPtr.Zero but we don't. It's a pointer, and 0 is globally understood to be The Bad Value.
Some brain damage remains:
* LoadLibrary abstraction also returns Nullable<IntPtr>
* I named it `Resolve` and not `GetProcAddr` because I didn't want to see win32 everywhere I went :(
Because of intervening commits, there may be some other incidental changes.
While well intentioned, the refactoring was just a mess when it came to actually groking this low level memory block shuffling code.