Edit: I'm a silly-billy who doesn't know what words mean. https://en.wikipedia.org/wiki/Threaded_code is not a bad description of a large WAM program, although =/2-inlining and peephole optimisation will turn some procedure clauses into quite sophisticated collections of pattern-matching and unification instructions, which represent a non-trivial computation. Does a tight loop operating over linked lists still count as threaded, if it used to be a tail-recursive procedure call? Or does the term refer instead to the program as a whole? (Probably the second one.)
---
I thought WAM was single-threaded? It does a lot of trickery to simulate "fork, wait, and either kill parent or child" with no copying and minimal rollback, but most of that trickery relies on the absence of threading, and will explode in the presence of such hubristic assumptions as "once we've returned from a procedure, the old stack frame is freed and its memory can be re-used", "a clean-up procedure will be run when we drop objects", and "clean-up procedures do not need to be run when we drop objects".
I would be interested to see approaches that make it work in parallel. Even cheating with Unix and COW would be interesting: since Prolog predicates can have side-effects, a cut in an earlier branch would retroactively cancel the later branches you've eagerly executed in parallel. You'd either have to deal with that somehow (maybe with IO monads?), or invent some notion of (dependent?) purity and then ensure procedures in the dynamic procedure database remain correctly tagged with their purity, transitively (i.e., including all possible callees, unto the deepest generation). I'm not confident the speed-up would be worth the overhead, for most programs.
Threaded interpreters are different than multithreading:
https://en.wikipedia.org/wiki/Threaded_code
https://archive.org/details/R.G.LoeligerThreadedInterpretive... - book on the topic