WEBVTT 00:00.000 --> 00:15.720 Okay, good to see y'all, my name is Andy Wingo, and this is a talk about a new head of time 00:15.720 --> 00:21.000 compiler for WebAssembly, it's called Wastrel, it's WebAssembly without rentime, and once 00:21.000 --> 00:28.320 you start the talk with a little demo, let's see, it's my terminal, it's where they've 00:28.320 --> 00:34.920 mostly, I don't actually use a terminal inside e-max, I don't use many tools, because 00:34.920 --> 00:41.760 I'm not very smart basically, so we have, I'm in my Wastrel directory, I have to run 00:41.760 --> 00:47.160 inside a little environment, okay, Wastrel, I want to run a little WebAssembly file, and 00:47.160 --> 00:58.280 I don't know if people are aware, but WebAssembly is a list, and it has this set 00:58.280 --> 01:04.880 textual format, which is one-to-one correspondence with a binary, so you can write it 01:04.880 --> 01:10.400 as text directly, and this is called Wat format, or the assembly text format, so I opened 01:10.400 --> 01:14.400 up the Wat, obviously, I don't have my e-max very well configured either, still in the 01:14.400 --> 01:19.080 fundamental mode, I have to go in schema, though, because Wat has parentheses, and I don't 01:19.080 --> 01:23.880 know how to write things with parentheses without par edit and all these niceties, so writing 01:23.920 --> 01:31.560 a WebAssembly module, you start with a module, usually, it's actually optional, but it 01:31.560 --> 01:39.240 expands out to module, and we're going to do a hello-fuzz them here, so a funk hello, we're 01:39.240 --> 01:45.640 going to take no parameters, so you can put no parameters or not if you leave it out, it's 01:45.640 --> 01:52.320 not a problem, no results, okay, we're going to do a hello world here, let me just say 01:52.320 --> 01:57.480 call, and we're going to need to call some sort of procedure that outputs things onto the 01:57.480 --> 02:02.400 screen, and as you might know, WebAssembly doesn't have any capabilities in and of itself, 02:02.400 --> 02:07.040 you have to provide it with capabilities, including the capability to output to the screen, 02:07.040 --> 02:16.040 so we have to import, define a function, and say it's, well, call it pk, actually, it's 02:16.040 --> 02:22.280 kind of a nice name, and we're going to import it from, I don't know, some debug library, 02:22.520 --> 02:29.720 we're going to call it debug stir, and it's going to take as a parameter, and this is the 02:29.720 --> 02:37.720 problem with WebAssembly, it's like WebAssembly 1.0, you have N32 and 64, float 32, float 64, and how 02:37.720 --> 02:42.680 are you going to get a string into that, and this is the new thing in WebAssembly now, is that we 02:42.680 --> 02:49.240 have structured data, which is managed by WebAssembly itself, we almost had a good thing, in 02:49.240 --> 02:55.880 the sense that we almost had the ability to have a string data type in WebAssembly itself, 02:55.880 --> 03:03.800 and we didn't, we haven't managed to get it in yet, but we still have it in the tool chain 03:03.800 --> 03:08.160 that, that WebAssembly uses, this actually lowers down to an array of bytes at some point, 03:08.160 --> 03:13.080 so, has a parameter of a restring and no results, so we're going to import it from some 03:13.160 --> 03:24.360 standard library, so we're going to call pk on string.const, hello fuzz them, new line, all right, 03:24.360 --> 03:30.520 and we're going to start this WebAssembly module with the hello function. Now, if I didn't 03:30.520 --> 03:37.400 fuck up here, then I should be able to run this, let's see, last row, what is this, hello something, 03:38.040 --> 03:47.560 hello fuzz them, dot wet, does that fuck up? Ah, yes, there's one thing, 03:49.240 --> 04:00.200 expose the, talk about this in just a minute, hello fuzz them, oh thank you, y'all are so nice, 04:01.400 --> 04:05.560 that's not a little demo, so I'm going to get back to what the demo is, but I have to start with 04:05.560 --> 04:09.960 some story time, right, so let's go on on this side with me, I'm a long time commentator of the 04:09.960 --> 04:17.000 Gauss game invitation, Gauss uses the boom demo's Weiser Collector, the BDWGC, it's very reliable, 04:17.000 --> 04:23.320 we've had almost no problems with it over the 20 years, I think, that we've been using it, but it 04:23.320 --> 04:29.720 has some limitations, it's performance is not that great when you have multiple mutator threads, 04:29.720 --> 04:35.160 it has a relatively inflexible memory usage profile, you can't really get some very 04:35.160 --> 04:41.000 tight heaps with it, it can't move objects, it can't compact the heap, and there are new things, 04:41.000 --> 04:47.240 and I say new, but I realize that actually the new thing that I saw that I heard of at one point 04:47.240 --> 04:54.040 in was inspired to work on GCs was this design called Inix, it's a design for a garbage collector, 04:54.040 --> 05:00.040 and I'm like, it's a new design, it's 18 years old people, the time pass is really, really fast, 05:00.040 --> 05:06.200 but some of the work, precisely that we build on in this garbage collection work was 05:06.200 --> 05:09.000 happening a bit later, it's a kind of family of papers, but that one was the first one, 05:10.520 --> 05:13.960 so I always wanted to write a garbage collector, and that's probably actually, 05:15.080 --> 05:19.640 it's not one of these three bullet points here, but the problem with Gauss using the 05:19.640 --> 05:26.760 boom collector is that I didn't write it, which is not a good reason, but I've always wanted to 05:26.760 --> 05:32.840 work on a GC, and so I wrote a collection library built around this Inix inspired collector, 05:33.720 --> 05:39.240 and this collection library is called Wipit, Wipit is a embedable GC library, it's designed not 05:39.240 --> 05:46.200 to link to, but rather to include into your project's source tree, it's mainly designed for a 05:46.200 --> 05:51.800 project written in C, for a number of reasons we can talk about, now there's no dependencies, 05:51.800 --> 05:57.560 whatsoever, and the way it works is customizable, it compile time, you choose the collector, 05:57.560 --> 06:02.440 you choose the object representation, you specify how you trace your objects, you specify how you 06:02.440 --> 06:07.480 get your, how you identify the set of roots from which you need to start tracing, and that's 06:07.480 --> 06:12.280 such, it also contains a collector of collectors, collection of collectors, so I have another little 06:12.360 --> 06:20.120 demo here, so this is one of these commands that's kind of like the get sort of interface, 06:22.120 --> 06:28.920 and I have only really two options, I two sub commands right now, I have the run in the compile 06:28.920 --> 06:36.360 commands, so we're going to do a compile. Wastoral compile, and I can specify a GC with which to compile, 06:37.320 --> 06:43.400 oh man, it's kind of wrapping around my screen here, but I need an E equals here, GC equals help, 06:44.200 --> 06:53.240 help us them. Watt, let's compile it to hello, fuzz them, and I don't know, but, 06:53.240 --> 06:58.920 I specify in GC equals help is going to get me this list of available GC augmentations here, 06:58.920 --> 07:04.920 which you can choose, when you compile your, your Wastoral module, actually not all of these are 07:05.000 --> 07:10.760 appropriate for, for this, we'll get into this in just a minute, but I'm going to choose, for example, 07:12.360 --> 07:23.800 BDW, for example, so hello fuzz them, BDW, um, that work, okay, maybe I'll choose another one, 07:24.440 --> 07:31.480 MMC, which is another one of the main collectors in Wastoral, okay, 07:31.880 --> 07:46.600 hello fuzz them, star, all right, so we got the BDW one, compile the 70 kilobytes, and MMC, BDW is 07:47.800 --> 07:54.440 whip it's collector, but implementing whip it's API is the bomb library, so we're dynamically 07:54.440 --> 08:02.200 leaking to the bomb collector, for this one, we can run both of them, hello fuzz them, BDW, and C, okay, 08:02.200 --> 08:08.760 great, let's strip them both to get an idea of the size of them, so hello, I think about a 08:08.760 --> 08:18.440 father it puts in debugging symbols in BDW and C, let's look again, get an idea of what the size 08:18.440 --> 08:23.400 of these things are, so this is about the minimum you can get to with a with a Wastoral binary, 08:24.120 --> 08:32.200 the BDW one's 27 kilobytes, and it links out to the libgc, oh you can see, LDD on your hello fuzz them, 08:33.240 --> 08:37.560 BDW, and because I'm on geeks you can't really see anything, but the important thing is this, 08:38.600 --> 08:46.200 libgc here, so this one's looking to the libgc, and the other one is not, right, it links to 08:46.360 --> 08:52.520 what is this, LD Linux, libgc itself, that you see support library, libm, and I don't know what 08:52.520 --> 08:58.680 Linux video is, we'll see, right, so that's an example of choosing the different collectors, 08:59.960 --> 09:06.200 in whip it, there are three main collectors, right, three main collector variants and main, 09:06.200 --> 09:10.360 my quality collectors, because I've tried many things, but these are the ones that they're actually 09:10.360 --> 09:15.320 good, first one is a parallel copying collector, so semi-space collector, but it's heap is organized 09:15.320 --> 09:21.800 in a block structured way to allow for parallel both mutator and collector threads, it's a very 09:21.800 --> 09:27.080 good collector, but it requires a memory, and it requires the ability to precisely enumerate all of the 09:27.080 --> 09:32.840 edges in your heap graph, so that when collection time comes it can relocate them from from space 09:32.840 --> 09:37.720 to tree space, so it rewrites all the references at every collection, it's much faster than you 09:37.720 --> 09:43.560 would think though, the other one is the in-ex inspired collector, the MMC, and they're a mostly 09:43.560 --> 09:48.600 marking collector, because it mostly marks objects in place, but sometimes can compact them, 09:48.600 --> 09:53.080 and talk about these in some previous files and talks, I'm not going to go too deep onto them, 09:53.080 --> 09:58.440 and the other one is using the bone collector behind, and so I showed an example of using 09:58.440 --> 10:06.760 MMC and using BDW in this case, and the whole pitch here now is that this is what I would like to 10:06.760 --> 10:11.320 believe, and I haven't fully proven this, I'm not going to show a bunch of graphs today, but the 10:11.320 --> 10:17.400 pitch of this collector is that MMC collector improves on BDW, and that allows you to access 10:17.400 --> 10:22.040 tighter heaps, it scales better for multiple user threads, and it can compact the heap, so you 10:22.040 --> 10:28.360 never have that worry that's like, why is my memory like this, what's the reason, and BDW is not 10:28.360 --> 10:33.240 really something you can introspect and find that out, and whip it was developed with the support 10:33.240 --> 10:37.640 of NONET, thank you very much, and also with the Guardian, I have a bit of paper on this, oops, 10:38.600 --> 10:41.560 so if you, I'll share the side link later, but if you search for like, 10:42.600 --> 10:48.120 a whip it isn't in the name, this is going to be hard to search for, anyway, so whip it was made 10:49.400 --> 10:56.760 forgot, right? I designed it in some of the ways so that I could replace the use of the bone 10:56.760 --> 11:04.600 collector in-gile with whip it, and I, last year, from the period of about April to August, 11:05.240 --> 11:13.000 I actually did this, I replaced the bone collector with whip it first, with whip it, but using 11:13.000 --> 11:23.480 BDW, and then whip it, but using MMC, the MX-DRIVed collector, but in a fully conservative mode, 11:24.040 --> 11:30.760 so not precisely enumerating edges on the heap, and then moving to a mode where it scans the stack 11:30.760 --> 11:36.840 and static data, conservatively, but heap edges are precisely enumerated, which allows it to 11:37.400 --> 11:42.760 actually improve on performance, and this took about 300, 350 commits or so, not sure how many of 11:42.760 --> 11:49.240 those are merge commits, because I was merging in whip it periodically on this, and I need to, 11:50.040 --> 11:55.240 I got it to the point where it's pretty good, and I still need to do some evaluations on it, 11:55.560 --> 12:00.920 but I need to do some incremental merging of this work, now that we are on code bird, 12:00.920 --> 12:07.320 and can do like merge requests and proper code review and such, for a push for a gal fore, so 12:07.320 --> 12:11.800 I'd love to talk about this in the next couple of days of the geek states, if anyone's going to 12:11.800 --> 12:18.440 be there, or afterwards, whatever. Right, right, right, but this is like Alice's restaurant, 12:18.440 --> 12:24.760 and so this is a talk about Wastrel, right? Not a talk about whip it. Wastrel is a funny thing, 12:24.920 --> 12:30.200 it's a web assembly to see compiler, right? So you didn't actually see the see compiler 12:31.320 --> 12:36.680 being invoked when I, when I invoked Wastrel before, but it just takes care of that itself. 12:37.560 --> 12:45.560 It's a Wastem to see compiler, but which embeds the whip it collector for managed data types. 12:46.520 --> 12:48.520 Wastem to see compiler with whip it, okay. 12:54.920 --> 13:00.440 I don't believe it was narcissism that I started all of these projects with a W. It really, 13:02.680 --> 13:07.560 Wastem, I didn't name that, whip it was named because it was a work in progress, 13:08.280 --> 13:13.480 garbage collector, and Wastrel because Wastem things are often named starting with the W. 13:14.280 --> 13:20.440 It's what I'm telling you today. So Wastrel is not, it's not like the first, 13:20.440 --> 13:24.040 and I'm sure it's not going to be the only compiler that's like a Wastem to see compiler, 13:24.920 --> 13:28.040 there's a number of them out there, originally there was Wastem to see, 13:28.760 --> 13:35.720 and then there's an update version of this called W2C2, improves on a number of ways. 13:37.880 --> 13:47.960 Our differentiator for the Wastrel project is that we aim to do Gc, so I'm doing whip it, 13:47.960 --> 13:53.640 and it's built in Gile on top of the WebAssembly libraries that were made as part of the 13:53.640 --> 13:59.960 hoop compiler. So all of that Wasm work allowed us, well, allow me to make the first version 13:59.960 --> 14:05.560 of Wastrel in a couple of days, right. The first version of Wastrel that couldn't do anything, of course, 14:05.560 --> 14:11.320 because Wastrel is essentially a baseline compiler in structure, and I've written baseline 14:11.400 --> 14:17.640 compilers before, and I've written things based on the who-wastem libraries, the process, 14:17.640 --> 14:22.600 Wastem modules, but actually getting it to do something, took a little bit longer, 14:22.600 --> 14:25.560 in the sense of wiring it up to other capabilities. A little bit more in that minute. 14:26.280 --> 14:31.960 How does it perform? It's, it's great, right? No, no, no, I mean, 14:35.560 --> 14:40.520 say you can probably, I haven't done a full battery of tests, but say you can pass something like 14:40.680 --> 14:48.840 core mark, right? You compile it native, and then you compile it by a Wastrel or, or Wasm time, 14:48.840 --> 14:55.320 or Wtc2. Wastrel is like a few percent off native, like maybe three, four, 14:56.840 --> 15:04.120 and Wtc2s about there, and Wasm times significantly below that in my tests anyway. So like it, 15:04.200 --> 15:12.120 it is a state-of-the-art compiler in that sense. It, and it doesn't, on the features of Wasm, 15:12.120 --> 15:19.560 for example, memory isolation, and it does so, because it, a lot of the more complicated Wasm 15:19.560 --> 15:23.480 run times allow you to instantiate modules at runtime, but because this is a fully ahead of time 15:23.480 --> 15:28.440 compiler, we can fully allocate everything statically, we can fully allocate all of the memory statically, 15:29.000 --> 15:34.920 and, and, and thus at runtime reserve, a gigabyte map regions for the memory, for example, 15:34.920 --> 15:39.640 so you don't have to do any runtime checks that, that your pointers are in balance, for example. 15:40.920 --> 15:44.760 Yeah, hey, I'm sure a lot of people have worked in C here. 15:46.440 --> 15:53.320 My, my approach to C is, is much, much different than when I learned it poorly 20 years ago. 15:53.320 --> 15:57.960 So I, I just wanted to have a little slide here about if you're working with C, this is what I've 15:58.920 --> 16:05.240 found to work for me in recent projects. So I, I think you want to heavily lean in, 16:06.440 --> 16:12.920 trust the optimizer, for example. Like sometimes we are when writing C or when generating C, 16:13.640 --> 16:18.120 we try to smash everything together, right, because you're like, okay, we're just going to 16:18.120 --> 16:22.120 inline everything in, in, in an expression, because that, that way the compiler is going to do things, 16:22.120 --> 16:28.760 good things about it. We can actually use abstractions in, in terms of static inline always inline 16:28.760 --> 16:34.360 functions, and it, and it, and it works great. It burn away completely a compile time. And, and as such, 16:34.360 --> 16:40.600 you can have extractions without runtime overhead, and, and, and, and, and, and avoid a lot of, like, 16:40.600 --> 16:45.800 the pathological, um, undefined behavior stuff in, and C, for example, about, uh, casts, 16:46.600 --> 16:50.840 completely remove casts from your program, uh, both implicit and implicit, always go through 16:50.920 --> 16:56.040 static inline functions to do so, just to make everything, um, explicit. If you need to read 16:56.040 --> 17:00.680 from memory, you can always mem copy, uh, even if it's four bytes, in the case of web assembly, 17:00.680 --> 17:04.440 and the compiler will rewrite that to a four byte load if it can, but that, that follows, like, 17:04.440 --> 17:11.160 the C memory model. Um, and absolutely avoid, um, like, using any kind of integer data type to represent 17:11.160 --> 17:15.640 anything of semantic value, like, always wrap that in a struct of one value, and it will get 17:15.640 --> 17:19.640 compiled just as well. But that just means, like, you've given a name to what that is, and it won't 17:19.720 --> 17:25.400 get confused with any other U.N. pointer, or, or, or, enter, whatever that, that is, uh, that might 17:25.400 --> 17:30.440 implicitly convert to that value. And, and the goal is, like, so Wasm as a type system is a strongly 17:30.440 --> 17:35.960 typed, and, and, and the type system, like, is the reification of a proof that when run at runtime, 17:35.960 --> 17:40.840 it's not going to do a number of things. And, and if we manage to translate the types from Wasm 17:40.840 --> 17:46.360 into the types and C, then I've also translated that proof, right, like, because I've eliminated 17:46.440 --> 17:52.600 a number of sources of, of errors that GCC can actually, uh, check that, that my compilation is, 17:53.720 --> 17:58.920 preserve these properties for me in a bit. Of course, you know, you also want, like, sanitizers 17:58.920 --> 18:03.160 and things like this, but, but you can lean into, and, and the C type system a bit better than, 18:03.160 --> 18:06.920 at least, at least what I was used to doing, you know, 20 years ago with a bunch of castes and stuff. 18:07.960 --> 18:13.640 Um, right, so the question is, what do we do about a standard library? Uh, with, with C programs, 18:13.720 --> 18:20.440 there's a C standard tool chain called the Wasm SDK. Uh, it's a version of clang plus, uh, a C library, 18:20.440 --> 18:26.040 and you just compile like clang with target Wasm 32. Uh, Wasm 32 wasn't p1, for example. 18:26.040 --> 18:31.960 And, and that runs great in, in Wasm, I can run LVM, for example, uh, with, with Wasm, 18:31.960 --> 18:37.160 takes forever to compile. This is, this is another issue, but, um, uh, but it was really excruciating 18:37.160 --> 18:44.520 implement, um, because, uh, the Wasm interface is essentially what you're given is the, the reified 18:44.520 --> 18:50.760 artifacts of, of an API, API lowering in terms of N32s and floats and stuff. You don't actually 18:50.760 --> 18:56.200 have pointers or meaning when, when you're, when you're implementing Wasm unless you, unless you 18:56.200 --> 19:01.400 implement other tools. So, I, I kind of running in circles here, but that was very, very annoying 19:02.360 --> 19:07.720 The one, the one thing I would note that was that, uh, Wasm can expose a file system interface, 19:07.720 --> 19:14.040 and, uh, I, I do so with Linux namespaces, so it only runs on Linux. Okay, better force. 19:14.600 --> 19:21.560 Uh, if you need access to file system. Okay, get back to GC. Uh, Wasm 1.0 was number of instructions 19:21.560 --> 19:28.520 that can operate on an array of bytes. We're up to 3.0, anomaly, now, which is linear memory, 19:28.520 --> 19:35.160 but also exceptions, manage memory data types. And so, uh, here's, here's, for example, a 19:35.160 --> 19:42.520 definition of a pair type, right, in WebAssembly. Uh, well, I can't actually highlight it. There, uh, 19:43.800 --> 19:49.480 I have a, a cursor. So I have a, a pair type. It's a structured data type, a product type, 19:49.480 --> 19:57.240 and it contains two fields. I didn't give them names here. Um, X is in the type hierarchy of WebAssembly, 19:57.320 --> 20:02.120 values that can be prepared, that can be compared by identity. You can, you can, you can apply 20:02.120 --> 20:08.680 ref X on them. Um, so it's like, it's a pair of any values, essentially. And to const, to make a pair, 20:09.400 --> 20:16.280 I write a function that takes as a parameter A and B, my X refs, and then I return a pair, and I, I, 20:16.280 --> 20:22.040 I return it by, it being the last value in the, in the function, and I just call structure new pair, 20:22.040 --> 20:27.560 and I, and I give it the operands as organs. It's, um, it's a higher level assembly, and it's an 20:27.560 --> 20:34.680 interesting target for for compilers, because you can run this on the web. You can run it on cloud environments, 20:34.680 --> 20:39.640 and you can run it with last row now. Uh, we have, uh, in addition to structs, there are also arrays. 20:40.360 --> 20:48.280 Subtyping is a whole thing, um, recursive types, immediate, uh, casts, and, and it needs stuff. 20:48.360 --> 20:54.120 So it was, it was, um, took me longer than expected to add, uh, Gc to last row, because of subtyping, 20:55.000 --> 21:02.200 because you have, like, um, well, in wasm, you have typing judgments that are formally verified, 21:02.200 --> 21:09.480 and to translate those, like subtyping into C, uh, was, was very annoying. Um, but, uh, 21:09.480 --> 21:15.640 it managed to work, and so Gc can check our work. So here's an example, right? In, in wasm, Gc, 21:15.720 --> 21:22.200 you have three top types. So three type trees, sort of, or lattices, right? Uh, there's any, and 21:22.200 --> 21:30.760 external, and funk. And they are, um, yeah, they're, uh, external, and any can be interconverted, 21:30.760 --> 21:37.240 but funk cannot, and this is based on, uh, reasons of how things are represented in, um, in, in 21:37.240 --> 21:45.240 web browsers. And so under any, you have x, and then under x, you have i31, which is, uh, 31 bit 21:45.320 --> 21:52.040 immediate. You have strokes and arrays, right? And, and we represent them as, you know, uh, C 21:52.040 --> 21:58.600 strokes, which include the parent just, uh, directly like that. Um, and functions, they include just 21:58.600 --> 22:03.320 the function pointer as a value, and I hear I have to use a voice star for reasons. And, and functions 22:03.320 --> 22:07.320 are the, are the pointer type that actually bears the type in the, in the reference itself. But for 22:07.320 --> 22:12.440 objects, their type is in this, uh, tag word initially, and then so you have an object representation 22:12.520 --> 22:18.520 hierarchy as well. Like you have any object, and instructs are any object, and arrays are any object, 22:18.520 --> 22:23.800 but also with a length field. And so, that was a header that's like the sort of base types, 22:23.800 --> 22:29.960 and then last rolled generates a number of, uh, implementations for these types. Uh, uh, this, 22:29.960 --> 22:34.760 there's some, um, routines on the, on the base type. So you have, you have noble types, and non-noble 22:34.760 --> 22:38.920 types, and you can check if something's immediate, and then you can, you can get an object reference 22:38.920 --> 22:44.120 out of a, uh, of an any rough. I'm going a little fast here, because we got, you know, a couple 22:44.120 --> 22:48.520 minutes. So let's step through some, some generated see here. Here we have two types. One is a, 22:48.520 --> 22:54.760 uh, as type 0 is a struct, it has an i31, i32 field. And then we have type 1, which derives from type 0, 22:55.320 --> 23:01.480 which has the same i31, i32, this is supposed to be i32, excuse me. But additionally has a, 23:01.480 --> 23:05.960 uh, a ref to type 1, so there are a cursive type. And so that reason we've, we've wrapped it in 23:06.040 --> 23:13.080 rec here. Uh, what is this generate? We generate, uh, some, the ref types for which we can refer 23:13.080 --> 23:19.320 to these values. So type 1 ref, derives from struct graph. Uh, type 0 ref, derives from struct 23:19.320 --> 23:25.160 graph, type 1 ref, should derive from type 0 ref. You know, excuse me here. Um, and, and the representations 23:25.160 --> 23:30.760 of the actual objects, uh, type 0, directly from struct, type 1, this should be directly from 0, excuse me. 23:31.480 --> 23:35.960 Um, and then we can have our type predicate. Because we're at a header time compiler, 23:35.960 --> 23:42.680 we can allocate type tags continuously, uh, via depth or search, so that a type test can include 23:42.680 --> 23:48.200 subtypes. Like I just have, uh, what are two comparisons in, uh, in the source code, but which 23:48.200 --> 23:54.680 compiles that one comparison, um, here. Because the range of types has a continuous range of, of, of, 23:54.760 --> 24:02.200 tags, um, having sorted the tag values according to the type tree. Um, and then you can, when you 24:02.200 --> 24:08.280 create one of these values, you can pack it into a ref with loads of, of, of, of braces, you know, 24:08.280 --> 24:14.520 so, as you can tell, web assembly is definitely a list here. Um, and, and here's the, the one, 24:15.560 --> 24:20.920 instance of, of, of, of, of, of whip it code here. You pass a mutator around because we're, 24:21.000 --> 24:26.680 static the allocating just one thread currently. This is a global variable. Um, you allocate the size of type 24:26.680 --> 24:32.280 one, we're telling it's a tag allocation, initialized tag word, initialized field 0 in the parent, 24:32.280 --> 24:38.440 because that's how the types work, and then we're, we return the pack value. Okay. Um, right, 24:39.240 --> 24:45.400 one, uh, so we have a currently to get capabilities, uh, we look at the set of imports and provide 24:45.400 --> 24:50.280 imports that we know by name. So for example, debugster is something that who uses, for example, 24:51.240 --> 24:56.280 in, in, in, in, in, in, Wazun couple of hoot artifacts. I implement that, and that's what allows us to 24:56.280 --> 25:00.120 know how the world. Um, I'm going to look, you know, soon to building out the hoot standard 25:00.120 --> 25:04.360 lived, including big norms and other things. And, and Wastrel skin, Wastrel can also, in many 25:04.360 --> 25:09.000 other extensions. So for example, the string wrap support that we saw is actually, uh, an artifact 25:09.000 --> 25:13.640 of the tool chain, not of the, an imitation, but like, because it, because it's built on the, on the 25:13.640 --> 25:18.600 hoot, Wazun lives, we can compile the, the text format to the Wazun format on the fly. And from, 25:18.760 --> 25:23.000 from this code, we can still access the Wazun capability. But it's, it's not really because Wazun 25:23.000 --> 25:27.720 often assumes, uh, that you're passing parameters through linear memory and doing so, uh, via, 25:27.720 --> 25:32.520 via Wazun Gc isn't so nice. The status is that it's, it's somewhat demoware right now, right? 25:32.520 --> 25:37.480 I just got it working, right? Um, but it's up on Wastrel. We have never issues for things that are 25:37.480 --> 25:41.960 still dimmed. We're going to be rolling this out over the next month or two. Um, and next up, 25:42.840 --> 25:49.080 other, uh, language runtimes. There's Kotlin, Skala, OCaml, happy to have been any, uh, any of the 25:49.080 --> 25:53.480 facilities that these run times need, uh, from web browsers. So we get native compiles for them as 25:53.480 --> 25:58.200 well. With hoot, uh, since we can compile a guy, essentially, to web assembly, we now have a web 25:58.200 --> 26:04.280 assembly to native, uh, target as well. Interesting. Uh, benchmarking some more Wazun features. 26:05.000 --> 26:10.840 Um, as you saw, I had to expose the root directory, uh, when I ran things, because the Gc 26:10.920 --> 26:15.160 wants to read proxail from app, and as I need to fix, uh, the file system sandbox, 26:15.160 --> 26:20.040 with regards that you see, some bugs, more Wazun standards, stack switching, which is essentially 26:20.040 --> 26:25.320 fibers and drilling conditions, drilling situations, in the Wazun standard, and to be active, 26:25.320 --> 26:30.200 which is meant in helping evolve Wazun standards. So, and if you're writing a new language, 26:30.200 --> 26:34.760 consider, generally, Wazun Gc, because it's a growing ecosystem. There's not so many things right 26:34.760 --> 26:39.480 now. You'll be the center of attention. If you are targeting Wazun Gc already, then let's talk 26:39.480 --> 26:43.160 about implementing your standard library. And if you are implementing a language runtime, 26:43.160 --> 26:46.760 and you need a garbage collector, let's talk to you. So, thank you for a much, uh, I can take 26:46.760 --> 27:01.080 a question so we can ask you a question. Sure, and note. Sure, and note. 27:01.480 --> 27:12.120 Yeah. Yeah. Good question. The question is, uh, just compile and you see how you 27:12.120 --> 27:18.200 have your head. Uh, on one side note, um, on the other side, uh, some things are unavailable to us. 27:18.200 --> 27:23.160 For example, uh, implementing exceptions, you would like to have a side table mapping program 27:23.160 --> 27:28.920 counter to ranges of of exceptions, and I'm not going to be able to do that, right? Uh, 27:29.240 --> 27:37.480 or because I am not using handles in all of my GC objects, like here, for example, 27:38.520 --> 27:44.600 if, if I had a moving GC, this should be a handle. This type 1ref should be a, uh, should be a 27:44.600 --> 27:49.960 relocatable pointer, because it's present before I allocate a value. And when I allocate, 27:49.960 --> 27:56.600 that can cause collection, invalidating that value. Uh, I could do that, but it's, it's, um, 27:56.600 --> 28:02.760 it's so gnarly to do handles, and I, I don't want to, but it's also a limitation of C, and 28:02.760 --> 28:08.280 that it doesn't really facilitate me, uh, ensuring that each pointer is relocatable, um, in the right 28:08.280 --> 28:14.360 way. So, so the answers have been ambiguous there. It's an okay strategy, I think, but it is not 28:15.160 --> 28:17.960 globally optimum. There are other options.