Folks, Once we decided that we do not want to limit Harmony with only one VM/JIT/GC instance I think it's time to start discussion how all these components will work together effectively. So the proposal is to discuss helper inlining interface.
Every component we have (VM, GC : ) can have helpers that must be called from managed code. While generating native code for Java method JIT inserts calls to these helpers: "get_vtable", "allocate_new_object", "monitor_enter" e.t.c. Some of these helpers have fast version: a "fast path", the algorithm that worth to be inlined into generated method body to improve overall system performance. Here is an example of such helpers: 1) new object allocation 2) write barriers 3) monitor enters/exits 4) fast access to TLS data ... The problem of inlining of a "fast-path" algorithm is that JIT must know the details of the algorithm it inlines. There are different ways to solve this problem and I will try to describe some of them. Add more if you know better solution. Which one to choose and details of the implementation is the subject of discussion. Solution 1. Use "magic" methods (like MMTk does) and write fast path version of a helper in Java. "Magic" method is a method that is never compiled by JIT but replaced with a native code. In MMTk (see link 1) there is a set of 'unboxed' types that allow to write pointer arithmetic, pointer comparison, casts, and memory reads and writes including atomic operations in Java language. We can use MMTk-like 'unboxed' types with some new operations added to allow to write fast paths for helpers in Java. So JIT can access the bytecode of the fast-path helper version and inline it as a usual Java method. What do we need to add to MMTk's like unboxed types (please correct if I've missed something): a) Fast access to TLS. Used to access thread local data in runtime: GC allocation, per-thread profiling, monitors inlining e.t.c. : b) Develop an approach to call native methods using different calling conventions. Needed to call original and slow helper version if fast path version fails. Solution 2. Standardize algorithms by using custom interfaces for each of them. GC, VM, JIT components interact with each other by using some intercomponent interfaces, e.g. OPEN ones: (see link 2) The proposal is to standardize interfaces for every algorithm or family of algorithms we use in fast path helper versions, so if JIT supports one of them it can ask VM or GC to provide a struct with functions pointers and constants which describe the algorithm. E.g. for a "monitor exit" fast path algorithm that checks some bit in header in atomic operation it's enough to provide an offset of this bit to JIT. Another example is a fast path of "bump pointer" allocation algorithm. Once JIT is able generate a code to access to thread local data and knows the offsets of 'current' and 'limit' pointers it can generate a code that increments 'current' pointer or call to an original slow helper if check with 'limit' failed. Solution 3. Develop and standardize a lightweight low-level language and parse it in JIT to generate a helper's fast path. In this case when JIT decides to inline a call of a helper it asks VM or GC for a textual representation of the helper's fast path and parses it into its internal representation. This solution looks exactly like Solution 1, where Java bytecode serves as lightweight intercomponent language. So to accept this solution we must get an answer why bytecode + "magic" methods are not enough. In my opinion all of these solutions will work, but the first one (Solution 1) is much more flexible. Does anyone have other ideas how to design 'helper inlining' to make it easy and reusable? Is there any limitation with 'magic' approach that can prevent us to use this way? Links: 1) http://cs.anu.edu.au/~Steve.Blackburn/pubs/papers/mmtk-icse-2004.pdf 2) http://issues.apache.org/jira/browse/HARMONY-459. -- Mikhail Fursov