Implementing DOES> in Forth, the entire reason I started this mess
18 points by spc476
18 points by spc476
I remember struggling through the FIG Forth Z80 implementation of <BUILDS
and DOES>
in high school. (Why did ANSI rename the former but leave the angle-bracket on the latter?) It’s the FORTH equivalent of Lisp macros, or Zig’s comptime. I think I had that same insight that there are three distinct times to understand.
So, how does one write DOES>
on modern CPUs that make memory write XOR executable?
If you’re single-threaded enough, and if the implementation of DOES>
is prevented from sharing a page with user words, I think you can just change the protection, modify the code, and change it back.
Failing that: put the modified version of the word-definition in a new writable page (or pages), make it -w,+x
after you’re done writing it, then atomically update references to it, and optionally free the old version. If having every word (function) aligned to 4k is too wasteful for you then there’s some additional drudgery of the “write a small-object allocator” sort.
An alternative that the “big” JIT engines use(d?) is to map the same pages twice. Once r/w, once r/x.
When adding new code, write to the r/w section, then flush that, and then flush the r/x as well.
That would only affect primitive (machine code) words. Other Forth words, and stuff created by DOES, are interpreted and don’t contain machine code.