7 ms·
I'm a bit skeptical about this. This is significantly increasing WebAssembly's complexity. Garbage collectors are a leaky abstraction: Some support interior po
by ngrilly 3y ago
I'm a bit skeptical about this. This is significantly increasing WebAssembly's complexity.
Garbage collectors are a leaky abstraction: Some support interior pointers, others don't. Some support parallel tasks sharing memory, others don't. Some require compaction, making C FFI more difficult, others don't. Some require a deep integration with whatever mechanism is used for green processes/threads and growable stacks, others don't. Etc.
When looking at languages like Erlang, JavaScript, Python, or Go, the choices made at the language level are partly reflected in their garbage collectors.
That idea of a universal/generic VM supporting many languages has been tried many times, with limited success, for example with the JVM, CLR, or Parrot. What makes this different?
- kaba0 3y agoThe correct question is “what makes WASM different”, not the other way around. And, mostly nothing, besides some “elegance” from being a new thing not yet full of legacy constructs. Oh, and that the browsers (or whatever is left from the browser scene with nigh everything being blink unfortunately) agreed on this one and not the others. I personally think that GraalVM’s truffle infrastructure is much more impressive, and supporting the much wider managed language landscape may have been a better idea for wasm as well.
- knome 3y ago>“what makes WASM different” As I understand it, it's just difficult to efficiently implement GC because of the stupid decision to abstract the call stack within WASM, making it painful to get at stack pointers during collection. One would think that a generic VM assembly and the ability to make pages of memory as no longer in use so the VM and then OS can recollect them would be sufficient. Rather than admitting to and fixing their mistake, they're doubling down and doing something of much greater complexity to work around it.
- johncolanduoni 3y agoThat “stupid decision” is pretty key to WASM sandboxing model. How do you propose to preserve call flow integrity without it?
- ori_b 3y agoDon't put return address on the data stack, and don't allow write access to the call stack via anything other than call/ret.
- johncolanduoni 3y agoOkay, where does the VM spill registers to?
- HappMacDonald 3y agoI don't understand why more languages don't just handle a separate data stack from the call stack. Then the call stack can remain harder to screw up and you can continue using stack frames for arguments or locals as desired. When feeling productive (not much in the past year unfortunately) I've been trying to build a bytecode for i86/x64 that operates this way.
- ori_b 3y agoI see what you're getting at. I think something like code pointed integrity would be more interesting, and would even protect pointers in vtables and other heap allocated structures: https://www.usenix.org/system/files/conference/osdi14/osdi14-paper-kuznetsov.pdf https://www.usenix.org/system/files/conference/osdi14/osdi14...
- quonn 3y ago> the JVM, CLR, or Parrot. What makes this different? I think primarily because the decision to run a certain language on WebAssembly comes first and now the question is how to make it fast. For the JVM or CLR there was usually no need: Just pick Java C# or run the other language natively.
- xiphias2 3y agoI think what makes it different is the importance of the project. JavaScript garbage collection is here to stay, and it seems like it's the most sticky one of all the examples you mentioned. Other languages and applications/libraries have to adapt to it even if it's inferior in many cases.
- ngrilly 3y agoFair enough. I'd say the JVM and CLR are quite important and "sticky" as well on the server-side ;) But on the client-side, there is no contest, JavaScript (and thus WebAssembly) are the only option.
- ikari_pl 3y agoJust wanted to note that webassembly doesn't imply client, especially since docker's somewhat native support appeared
- dinosaurdynasty 3y agoWASM also looks really good for native plugins and modifications (it's fast and secure by default).
- jasode 3y ago>That idea of a universal/generic VM supporting many languages has been tried many times, with limited success, for example with the JVM, CLR, or Parrot. What makes this different? What's different this time is that WASM flips the timeline backwards from how Sun JVM and Microsoft CLR tried to do it. - JVM/CLR : create virtual machine & IL instruction codes specification & runtime first, then later try to distribute widely as possible and hope for universal client adoption. In other words, the "intermediate language vm" will be so compelling that it causes industry to spread it throughout the landscape. This hope was only partially true. JVM/CLR did spread on desktop & servers but fell short on web browsers with Java Applets and Microsoft Silverlight. JVM/CLR also never got widely adopted on mobile platforms. - WASM has opposite timeline : take something (aka Javascript) that's already distributed and adopted industry-wide and work backwards from that to create a "virtual machine & IL instruction codes specification & runtime". In that view, Javascript (the so-called "toy language") was the 20-year long "Trojan Horse" of getting wide distribution on all clients first. Now the industry says: "Hey, did anyone notice that we finally have a universal runtime (Javascript) on server+desktop+browser+mobile?!? Let's make it fast by creating an IL runtime!!!" There were a few technical issues such as Sun JVM not having raw pointers which makes it not a good performing target for pointer-based languages like C/C++. And MS CLR wasn't available on macOS (except for Silverlight minimal-CLR). But those technical limitations don't have as much explanatory power as the Javascript-as-harmless-trojan-horse-distribution timeline.
- hackyhacky 3y ago> take something (aka Javascript) that's already distributed and adopted industry-wide and work backwards from that to create a "virtual machine & IL instruction codes specification & runtime". I don't understand this. WASM is not JavaScript: it can't do things that JavaScript can do (such as directly access the DOM) and JS can't do things that WASM can do (such as pointer arithmetic). Their abstractions are totally different, which is why they complement each other. JS does not run in the WASM virtual machine. Other than the fact that they both run in a web browser, they have almost nothing in common. So I think your analogy fails. WASM is not a JS IL, it's a separate IL that happens to be distributed by the same mechanism. As such, it can still fail and is still vulnerable to the hubris of the JVM, wherein a single memory model was selected for all platforms and all (higher-level) languages.
- zozbot234 3y agoThe WASM-GC support is intentionally kept as simple as possible, see https://github.com/WebAssembly/gc/blob/main/proposals/gc/MVP.md https://github.com/WebAssembly/gc/blob/main/proposals/gc/MVP... . Building a "universal" or "generic" VM supporting many languages on an equally seamless basis is explicitly not a goal of WASM-GC; it is expected that each implementation might require its own hacks and special semantics on top of the basic support WASM provides, but this is okay because FFI/cross-language interop is seen as an entirely separate issue.
- cranx 3y agoI can see value in running code on multiple browsers on multiple OSes via web pages. I’d hate to npm install 2k+ JS libraries I don’t know or understand to be able to compile a simple Hello World Kotlin program that runs on a webpage. There does seem to be some notion in the industry that everything should be in a browser/JS, sigh.
- DanielHB 3y agoTo run a wasm-compiled program in a webpage you need maybe 30 lines of JS total. Maybe a 10 more lines if your application wants to draw on the page through a canvas
- dns_snek 3y agoIt's a bit more complex than that, JS and WASM have a huge impedance mismatch (if you can call it that) because they can only communicate via shared memory and functions calls using numeric types as arguments. As soon as you want to pass a string, struct or arbitrary map between JS and WASM you'll find yourself in a world of pain that comes from writing bindings that de/serialize data on both sides. Rust seems to have a somewhat capable bindings generator but the core issue still remains in any other language targeting WASM. I'm not keeping myself up to date, but as far as I remember WASM/JS interface types proposal was supposed to address this issue. Has there been any progress on that front?
- DanielHB 3y ago> To run a wasm-compiled program in a webpage you need maybe 30 lines of JS total. Maybe a 10 more lines if your application wants to draw on the page through a canvas If you read more carefully you will see that I mean that if your application is completely written in WASM with no JS interop all you need is some JS glue code to load the WASM binary If you want to manipulate the browser DOM from inside the WASM binary then yes, you need a lot of JS > I'm not keeping myself up to date, but as far as I remember WASM/JS interface types proposal was supposed to address this issue. Has there been any progress on that front? Last I heard it is somewhat abandoned proposal
- klabb3 3y ago> I'm a bit skeptical about this. [...] Some support [X], others don't. [...] I am super conflicted, but I err on the side of agreeing with you here. Gut feeling says it's too complex and fragmented to be "standardized". Generally speaking, "abstracting out" something should be done when that "thing" is actually pretty clearly defined and always end up behaving the same way. My understanding is GC does not qualify - despite its popularity we still don't know where the cut points are, in all honesty. There's a reason why languages differ so much from one another, and afaik this is still an area of quite active research. Adding to that, intricate understanding of GC internals of multiple languages is probably restricted to a very low amount of engineers, worldwide. This makes it very difficult for curious bystanders to understand, follow and critique the progress. Remember that this is a massive career project for the proponents, so they're also incentivized to push ahead and perhaps gloss over legitimate issues. And what if the design ends up being flawed, yet wildly popular? Then languages may be forced to conform to the WASM GC model in order to stay "modern" and attractive, while constraining their normal design space. That said, if everything goes dandy it can be a huge win, so I can relate to the excitement as well.
- The_Colonel 3y agoThe blog post goes into this topic. It's basically a question of trade-off between performance and exact semantics, in some cases you will need to sacrifice minor semantic differences for meaningful performance gains. I think this is rather common when porting languages to "foreign" VMs and doesn't seem to be a showstopper. The application developers targeting WASM and other platforms of course have to test on all platforms and will avoid those cases with semantic differences.
- augusto-moura 3y agoIsn't the JVM kinda of a universal GC? Putting the different GCs in the JVM itself aside, a lot of other languages actually have runtimes for Java and work very well, used in production and all. Jython, JRuby, JS engines (Rhino/Nashorn), Groovy, etc.
- bradfitz 3y ago> Isn't the JVM kinda of a universal GC? Nope. No interior pointers for one.
- masklinn 3y agoThe reference JVM has at least 4 different GCs, with pages of tunables. That’s a far cry from universal.
- augusto-moura 3y agoAFAIK all of the different GCs are implementation transparent, no? Implementations like Jython or Jruby work independently of the GC being used
- masklinn 3y agoIf your criteria for a universal GC is that the GC does the job of a GC, every GC is universal.
- titzer 3y ago> That idea of a universal/generic VM supporting many languages has been tried many times, with limited success, for example with the JVM, CLR, or Parrot. What makes this different? I would say that the JVM and CLR were not designed to support many languages. The JVM has one master, which is the Java language, and other languages that want to run on the JVM do so with a burden that increases as the distance from Java's type system increases. Wasm is lower-level than most of the above bytecode formats. Even with Wasm GC, which adds statically-typed structs and arrays, and the function-references proposal which brings typed functions. With Wasm GC, there is also explicit support for tagged pointers (i31ref). All of the above makes Wasm GC more general (by virtue of being lower-level) than the efforts you listed.
- mmcdermott 3y agoJVM wasn't originally intended to support multiple languages. IIRC, Sun wasn't welcoming to new languages on the JVM (Java Virtual Machine). But CLR stands for Common Language Runtime and had three official languages shortly after release (VB.NET, C# and J#, offhand). In fairness, both Sun and Microsoft advertised what they were shooting for in the name.
- orthoxerox 3y agoMicrosoft planned to support all kinds of languages and the list of CLR languages is respectably long, but most of them can't really keep up with the co-evolution of .NET and C#. The generics in .NET 2.0 were the first big compatibility break, and I think async/await was the second and even bigger one that killed off the bulk of alt-langs.
- WorldMaker 3y agoasync/await was never a compatibility break at the CLR level. Most of async/await is "just" the TPL (Task Parallel Library), a subset of the .NET BCL (Base Class Library) and entirely handled as libraries, which any language can use/interact with even without async/await language support. The async/await language support in C# is basically a Monad transformer, building a generator-like asynchronous state machine. (The output of an async/await function in C# is rather similar in concept/implementation to the output of a generator function using yield syntax.) This is also why F# has never had a tough time with async/await because it has even more generic Monad transformer support ("computation expressions"). Any "alt-lang" could make use of the TPL whether or not they could transform their own similar syntax, and there's nothing stopping them from building a similar syntax. As far as I saw that wasn't a killer of languages.
- msla 3y agoHow universal did the JVM ever try to be? Aren't its semantics pretty tied to what's legal in Java?
- naasking 3y agoNot quite, and this has had security implications. These are known as "full abstraction" failures, where JVM bytecodes can violate guarantees made by a language running on top of the JVM. The Joe-E language is basically a security-oriented subset of Java, and they had to explicitly decompile JVM bytecode of any code they're using, then recompile it in order to preserve full abstraction and avoid introducing vulnerabilities. C# is close to CIL bytecode as well, but they too had some full abstraction failures: http://lambda-the-ultimate.org/node/1588 http://lambda-the-ultimate.org/node/1588
- naasking 3y agoThe main difference is that WASM started with unsafe languages that have all of those features, so the developers are aware of them, and now they're trying add safety. Prior universal VMs started with a safe language and bytecode and then added unsafety. Maybe that will change the outcome, maybe not. At the very least you can still use conservative GC.
- throwaway894345 3y agoYeah, I don't know how you could have one gc that works for everything unless that gc was very tunable/configurable and you could have different profiles for each language. Maybe the program payload includes the gc tuning parameters such that the gc performs like the GC for the program's host language?
- adrusi 3y agoThat idea of a universal/generic VM supporting many languages has been tried many times, with limited success What wasm is doing is something different than previous efforts. The gc facilities aren't provided for the sake of interop with other languages, or for the sake of sharing development resources across language runtime implementations. Wasm is providing gc facilities so that managed-memory runtime languages can target wasm environments without suffering on account of limitations imposed by the restrictive memory model, and secondarily to reduce bundle sizes. Wasm can potentially support more tunable gc parameters to better suit the guest language's idiosyncrasies than can other general purpose language runtimes. And unlike the runtimes we're comparing it against, language implementers don't have to option of making something bespoke.