I'm a bit concerned by the addition of Garbage Collection to WASM. Is there a way to implement those without favouring some type of language?
It seems to me that GC tuning and memory models are very language-specific. A purely-functional language like Haskell or Closure can make different assumptions about the memory regions but also generate a lot more young generation items compared to OOP languages.
Well, not implementing GC isn't really a viable option long-term. You have to have some bridge between Web Assembly and objects defined in WebIDL, and, for better or for worse (I think: for better), GC'd objects with WebIDL interfaces are the COM objects of the Web.
If DOM objects can hold on to Web Assembly objects--as for example happens in the case of event listeners implemented in wasm--and Web Assembly objects can hold on to DOM objects, then the only sensible solution to memory management is a GC that can trace both kinds of objects. All other solutions eventually lead to uncontrollable memory leaks (see IE6).
Why not implement the GCs themselves using low-level WASM code? That would enable a language-agnostic approach (though it would prohibit collecting garbage over multiple cooperating languages at the same time, which is a less urgent problem imho).
Yes, the target audience for WebAssembly seems to be performance-conscious application authors who use non-GC'd languages, and unpredictable GC is a headline reason for choosing WS in those circles. So giving authors control over GC would be a fine thing to deliver, it would let real-time app authors still use GC in a controlled fashion.
It could probably be done in a way that allowed multiple GC's to coexist and cooperate.
> We've been interfacing C with e.g. Python without needing a garbage collector that crosses language boundaries. So why would we need one now?
Because C doesn't need garbage collection, it uses 'manual' memory management. This scenario is exactly analogous to the WASM-JS world that exists now (WASM is manual, and JS is GC).
The goal here is to have a GC that's usable in WASM, and WASM is going to be interoperating a lot with JS for many applications, so it needs to cope with that. A better analogy in this case would be IronPython which is Python built on the .NET framework rather than C. In that case, the Python GC is the .NET GC, so that objects can be passed back and forth 'between worlds'.
I'm sure that if you can make WASM secure without the GC part, then you can create a safe interface. Yes, it may leak memory (remember, so can a GCed program that forgets to unreference objects), but that's just something you have to deal with when programming at a low level; and languages built on top of WASM can make that a non-issue, actually.
Let's keep WASM simple. It's probably the best thing one could do in view of security.
Can you elaborate on how two WASM modules each with its own GC could safely interface without unnecessary overhead? Why would we want to have this overhead in the first place? It may not be that bad with 2 modules, but you might easily have 20 or (way) more.
OK, but could you share the specifics? I'd like to understand. Emphasis on combination of safety (primary) and performance (secondary) - remember that any number of completely unrelated, untrusted, maybe buggy and potentially even malicious modules might be combined. They're being very careful about not forcing languages into one model, BTW.
The kinds of memory guarantees and controls a GC wants for good performance seem to be the kind of things you wouldn't want to give to some random third-party.
I believe the GC integration is far more important for Javascript (or other host language) interoperability than for WASM-targeting languages. Many of them will probably be able to take advantage of it, but anything more special-purpose should still be possible to implement in a custom language runtime.
At one time people thought that you couldn't possibly have a high performance runtime that supported both object-oriented and functional patterns vis-à-vis garbage collection, yet the CLR managed to pull it off with some clever use of ML (pun intended)[1].
> In systems designed to support multiple programming languages, reification brings a different problem. All languages must deal with the complexity of reification; worse they must conform to the expectations of the reified generic type system of the "master language" (C# or Java, for example).
> Consider .Net, the poster child of generic reification. Originally, .Net was intended to be a multi-language system, but dynamic language support there has suffered, in no small part due to reification. Visual Basic was a huge success until .Net came along and made it conform to C#. And what Iron Ruby/Python programmer ever enjoyed being forced to feed type arguments (whatever those might be) into a collection they are creating?
Not saying CLR's approach is bad; just that it doesn't seem like an example of one-size-fits-all as is sometimes claimed (and the same goes for the JVM, etc. too)
This particular snippet that you quote talks about dynamic languages that want to interop with the rest of the CLR language ecosystem. Because CLR provides a strong static type system that has reified generics, it means that dynamic languages have to devise ways to interop with that system. For example, if you're in IronPython, and you want to create a list that is strongly typed from C# perspective, you have to do something like this:
from System.Collections.Generic import List
lst = List[str]()
lst.Add(123)
obj.DoSomething(lst)
However, this is only an interop problem. A dynamic language targeting the CLR that does not care to interop with C# does not have to do anything special. And none of this has anything to do with the GC - that operates on a level far lower than anything to do with generics.
(I would also claim that the quoted snippet vastly overstates the problem, while also misrepresenting it - it has all to do with static/dynamic type system mismatch, and practically nothing with reification. In practice, if you want to interop between C# and Python, you'd just use "dynamic" in C#, and access native Python collections directly - that's exactly the scenario it's intended for. The only time you'd need to muck around with generics from the Python end is when you're calling into a library written with C# - but that's just FFI, no different in principle than having to specify types when you're using ctypes to invoke into C.)
I guess I was hoping for a more informative answer. Are there at least categories of GCs, such that a VM could provide the n main GC types and most languages would be able to choose the appropriate ones? Or is GC very specific to each language?
GCs have a lot of implementation specific quirks and properties, so for example a real-time app would be better served by shipping its own tested GC implementation than giving a "short pauses please" hint to the browser API.
Given the dual needs, it might make sense to have different allocation schemes, one that uses the built-in GC, and which allows sharing/interop outside of WASM (JS, DOM, etc), and one which is entirely manual (or home-rolled GC), which does not (or makes you set a very specific set of flags which alerts the user). Without that, I'm not sure there's a way to really handle memory allocation and deallocation sanely that prevents most memory leaks.
Aren’t they adding gc to node.js/js or some part (I read somewhere) and/or multithreading/parallel processing? Not really me, but it seems the market is demanding that functionality if it’s coming up?
It seems to me that GC tuning and memory models are very language-specific. A purely-functional language like Haskell or Closure can make different assumptions about the memory regions but also generate a lot more young generation items compared to OOP languages.