Sender | Message | Time |
---|---|---|
2 Jul 2022 | ||
17:05:13 | ||
3 Jul 2022 | ||
00:44:11 | ||
01:31:58 | ||
16:52:40 | ||
16:52:41 | ||
22:55:57 | ||
4 Jul 2022 | ||
00:39:31 | ||
03:03:36 | ||
Next challenge: making it so you can share processes between processes, ideally without complicating code generation too much | 21:42:28 | |
That is, if you spawn a process you sort of get a handle/client back (really just a pointer to the spawned process). You should be able to clone that, so multiple processes can send messages to the same one | 21:43:06 | |
This introduces a few challenges though:
Alternatives involve wrapping the client side in a dedicated type, but then you're lying at the type level (e.g. you'd actually have a | 21:47:55 | |
basically the meaning of class literals changes, which I'm not a fan of | 21:48:07 | |
also you'd need extra work when sending messages, because given a proc.message() call, you'd have to translate that to proc.wrapped_process_pointer.message() more or less | 21:48:38 | |
And of course spawning a process would require two allocations: one for the server-side, and one for the client-side | 21:48:58 | |
Today I experimented with basically adding "shared values", which are values that use atomic reference counting, and dropping their owned counterpart doesn't run the destructor/frees it until the ref count is zero. I applied it to both processes and strings (since I want strings to be value types but not copy the bytes). It sort of works, but it feels icky | 21:50:06 | |
In particular, I'm still not sold on strings being value types | 21:50:23 | |
The implementation is also icky: basically every object header now stores a shared flag, and based on the value of this flag it either uses regular ref counting operations or atomic ones, but it's not clear how this impacts optimisations of the VM | 21:50:58 | |
and it's an extra branch for every increment and decrement | 21:51:17 | |
5 Jul 2022 | ||
07:02:21 | ||
16:47:28 | ||
16:47:56 | ||
20:30:00 | ||
Got this working, now need to decide if I like it. In particular generics are complicated a bit more, due to the lack of monomorphisation | 21:48:19 | |
e.g. fn foo[T](value: T) {} produces this CFG: | 21:48:58 | |
Download bb.png | 21:49:21 | |
Here the issue is that T could be an owned value, a reference, or a value that uses atomic reference counting | 21:49:46 | |
One thing I need to decide on is if I want my drop instruction to be a sort of macro that expands to the above | 21:50:27 | |
That is, in MIR there's just drop that can operate on an owned value, a ref, or an atomic value. When generating the final code, this would expand into the appropriate code based on the type it's operating on | 21:50:52 | |
This simplifies generating MIR in a few places, and makes it easier to remove/adjust through optimisations, as only a single instruction needs to be looked at/modified/etc, instead of a bunch of instructions in different basic blocks | 21:51:35 | |
6 Jul 2022 | ||
13:15:52 |