Why mutable structs are allocated on the heap?

As usual for any discussion about allocation, you have to specify which level you are talking about. There are two very different levels, one is the language semantics and the other one is optimization. (I won’t talk about c# since I’ve basically never used it seriously, only as a VB replacement ~8 years ago.)

As for semantics level. There are differences between heap and stack allocation in C++. However, there’s no “stack” in julia semantics and conceptually, everything in julia are allocated the same way (you can call it the heap, but it really doesn’t matter). This is true for all julia objects, mutable or immutable, isbits or not.[1]

As for optimization level. There are actually less difference between C++ and julia, at least for the subset that can be expressed in both language easily. Both C++ (mordern compilers) and julia do extensive allocation elimination. Since julia does not give you any way to specify where you want to allocate something, it relies much heavily on the allocation elimination and also define the semantics such that the allocation can be elided in more cases more reliably (cases that you would have just use a stack variable in C++). This is where immutability/isbits/escape analysis comes in. In the end, the two languages could achieve a similar level of allocation in the final code (while compilers for both languages still both have cases to improve on for sure, more so for julia).

[1] Struct/Array ABI does couple the two levels slightly, but you can still view it as one of the many implementations allowed by the semantics that is favored by the optimization that could be done on it.

8 Likes