we started a new open source project Sulong: https://github.com/graalvm/sulong.
Sulong is a LLVM IR interpreter with JIT compilation running on top of the JVM.
By using the Truffle framework, it implements speculative optimizations such as inlining of function pointer calls through AST rewriting.
One area of our research is to provide alternative ways of executing LLVM bitcode that provide memory safety guarantees.
We are looking forward to feedback and/or contributions!
What's the primary target audience for the project?
It could be people who want to take their JVM bytecode to machine code, or it could be people who want to implement a compiler in Java but use LLVM for the backend, the Readme wouldn't tell me (probably because I don't know Truffle, or am missing other background).
I'm interested in hearing more about how you do this. Do you use
guarded devirtualization (i.e. `if *fn_ptr_loc != @foo then
side_exit(); else @foo()`), or is there something else? I'd guess
implementing "invalidation" based deoptimization (i.e. the value of
`fn_ptr_loc` changed, so deoptimize compiles that depend on it not
changing) will require instrumenting all (?) writes that could alias
I agree that the readme failed to explain for what Sulong can actually be used for.
Based on your feedback, I updated it to also include some use cases.
this Sunday I held a presentation at FOSDEM where I explained Sulong using function pointer call inlining. Yesterday, I uploaded the slides .
We use a form of “guarded devirtualization” as you expected. We do this based on Abstract Syntax Tree (AST) node rewriting in the interpreter. We use a direct call node that directly calls a function if it matches the function that has been profiled before. If it doesn’t, we either insert another such direct call node or fall back to an indirect call based on some threshold. Truffle then can perform the inlining on the AST level. After Graal compiles the AST to machine code and when the speculation on the target fails, a deoptimization handler transfers back to the interpreter where the node rewrite is handled.
We thus do not instrument the writes, but implement a polymorphic function pointer inlining cache at the call site.
Since polymorphic inline caches are also often used to implement other languages, Truffle’s domain specific language allows to express this logic in only a few lines of code. You can have a look at the implementation in com.oracle.truffle.llvm.LLVMCallNode$LLVMFunctionCallChain.