You can gain far more by working on your instruction set. Making it easily extendable is better, making it easy to transpose interpreted code into native code is better, because you can easily benchmark and optimize as you have a more and more clear idea of what will be idiomatic code. For the DTC technique, a bonus is that there's normally no difference between instructions and library bindings.
Nitpick: This sounds more like subroutine threading than direct threading. https://en.wikipedia.org/wiki/Threaded_code
In subroutine threaded code, each function implementing an instruction returns before the next one is called. In direct threading, each code snippet implementing an instruction loads the next address and jumps to it directly without going through a return and another call.
In DTC to call a function of the VM code (ie a another piece of DTC) you typically have a "call" virtual instruction, followed by the virtual address to call. you also have a virtual "return" function that pops the virtual instruction pointer from the virtual call stack.
Subroutine threaded is really just a very primitive form of AoT compilation.
the repo and performance measurements are on Github[1]. It includes a couple of dispatch techniques, register caching, etc.
http://realityforge.org/code/virtual-machines/2011/05/19/int...
Make sure to check out the references. I especially like "Ertl, M. A. and D. Gregg, The structure and performance of efficient interpreters, Journal of Instruction-Level Parallelism 5 (2003)"
Do you know of any recent efforts to combine ML and VM optimizations ?
(I read about the VS compiler and profile-based optimizations)
Though you might not think of hill climbing as "machine learning".