I am developing a basic POC VM with garbage collection capability. The language I am using is C#, where I am using a pinned byte array as the VM’s memory. Is it possible to dynamically increase the size of the memory without moving it by .net GC?
The code I am using is very straightforward
byte[] _memory = new byte[2048];
var _gcHandle = GCHandle.Alloc(_memory, GCHandleType.Pinned);
var _memHandler = _gcHandle.AddrOfPinnedObject();
If I want to re-size the _memory in the code afterwards, how would I do that without unpinning it? Should I use another technique?
No. And if you think about it, it’s impossible to do dependably.
Imagine a chunk of memory is set like:
[some_string][_memory][boxed_int32][some_URI]
Then it would be impossible to re-size
_memorywithout moving it.The best you could hope for was a call that would re-size it in place if possible, and not otherwise (either failing and forcing you to re-size through copy, or doing the copy when necessary and letting you know which approach worked).
So, as it is, it’s unlikely to be possible, but what about catching the case where it is possible as an optimisation. What if [some_URI] had been collected in the mean-time?
Sadly (though happily really for the majority of code, including the rest of your app), this won’t work as an optimisation for this relatively rare case, because there’s already an optimisation for the entire memory management in that the GC will move stuff into that position if there’s a gap, to reduce fragmentation. That your pinning the array makes it less efficient at moving stuff around just increases the chances that it will do so (because you’ve perhaps forced it to not a small bit of space before your array).
If your array is on the LOH it would be more likely that the space after it wasn’t used, but then less likely that it would have been freed.
So, even though this sort of re-malloc could theoretically work sometimes, the odds of it working any given time are too small to be worth implementing.