SableJIT: A Retargetable Just-In-Time Compiler for a Portable Virtual Machine Project Description ------------------- SableJIT is a retargetable just-in-time compiler for SableVM. The goal of this project is to design a just-in-time compiler that is relatively easy to port to new platforms, especially RISC platforms. SableJIT is written in Java. The code interfacing the compiler with SableVM is written in C. Project Status -------------- This project is still under development. Several major improvements are done weekly. Currently it works on the following platforms: - GNU/Linux / ppc (development platform) - GNU/Linux / x86 (development platform) - FreeBSD / x86 (not tested a lot, but seems to work) - Darwin / Mac OS X / ppc (not tested a lot, but seems to work) And is currently being developped for: - Solaris / sparc (by Christian Arcand) Platforms that may eventually be added: - NetBSD x86 and ppc - OpenBSD x86 and ppc - GNU/Linux sparc - Windows x86 It may run on other operating systems (such as the BSDs) provided that: 1) The processor is either x86 or ppc 2) The abstract binary interface is the same as one of the platforms supported: - Sys V on ppc and x86 - Darwin on ppc See the FAQ at the end. SableJIT can work with either 3 of SableVM interpreter: switch, direct and inlined. Note that the compiler is robust in that if a method fails to compile, the method will be marked as uncompilable and will be interpreted instead. Requirements ------------ All SableVM requirements plus: - An x86 or ppc machine running GNU/Linux - Perl (needed only to build it) - Junit 3.8.1 or later (optional, to run test cases) Installation ------------ If you are interested to try it out for fun, here are the instructions. In this section, I will use SableVM to refer to SableVM + the C code of the JIT that gets compiled and linked with SableVM. I will use Compiler to refer to the actual compiler component that is written in Java code. 1. Getting the source Get the latest source code tree from the subversion repository. It is located in the directory: /developers/belanger/sandbox/sablejit-classpath In that directory, there are three subdirectories: sablevm/ - SableVM + SableJIT support sablejit/ - Actual Compiler (Java code) bin/ - Various building scripts. 2. Configuring the environment Look at the beginning of Makefile.common in SableJIT directory for any required changes. 3. Build SableVM and SableJIT In SableVM top level directory: a) Generate the configure script. You may want to use my ./autogen.sh script. b) Configuring and building You may want to have a look at my building scripts located in: /developers/belanger/sandbox/sablejit-classpath/bin For example, to build switch/jit, from the SableVM directory: ../bin/congig/build switch-jit *** IMPORTANT ******************************************************* SableJIT has three level of binary compatibility with SableVM. The default level will tolerate some amount of changes in SableVM source code but not any changes. It is recommended that you recompile SableJIT if the configuration of SableVM changes or if you make changes in its data structures. ********************************************************************* If you are not using the provided script, to build SableJIT: In SableVM source directory, do: ./configure --with-sablejit make make install make -f Makefile.sablejit sablejit make -f Makefile.sablejit sablejit_install To test if installation went well, do: make -f Makefile.sablejit sablejit_version This will prints SableJIT configuration. 4. Testing SableJIT All these commands are to be executed in SableJIT source directory. a) Testing the installation make version This will print SableVM and SableJIT configuration. This seems simple but SableVM will need to correctly locate the SableJITClassLoader and then use it to load the SableJIT class sablejit.Configuration. b) Running test cases Requires some testing code to be compiled with SableVM/SableJIT. Requires methods to be compiled before there 2nd invocation. Pass --enable-sablejit-testing or better --with-sablejit-verbose-level=verbose to configure. (Or use scripts: ../bin/build switch-jit-verbose or ../bin/build-debug switch-jit-verbose) Also, in the file src/sablejit/Configuration.java, set GO_SLOW to true. Running the tests: make test in SableJIT top level directories. Compiles everything. make test in src/sablejit will compile only the test cases. 5. Running SableVM/SableJIT Interpreter-only mode, pass the "-C int" option to SableVM. This turns off the JIT. The overhead of having SableJIT compiled in is negligible. If testing is enabled, SableJIT does not compile anything by default, you need to explicitly specify classes / methods to include for compilation / recompilation. -p sablevm.jit.compile.include= -p sablevm.jit.compile.exclude= -p sablevm.jit.recompile.include= -p sablevm.jit.recompile.exclude= SableJIT will compile: INCLUDE_SET - EXCLUDE_SET If testing is enabled, it will compile also all methods prefixed by __compile_me_. -p sablevm.jit.compile.include=ALL means all are in include set. If sablevm.jit.recompile.include is not specified, it defaults to all methods if recompilation is enabled. Limitation: SableJIT does not support Java stack relocation. It will abort SableVM. Getting help on SableJIT options and properties. Use: -C help and -C info 6. SableJIT for experts SableJIT configuration is in three different locations: 1) ./configure options --with-sablejit-* --enable-sablejit-* --disable-sablejit-* Note: Some SableVM options affects the availability of SableJIT options. 2) Defined constants (most, if not all, are now configure options) 3) src/sablejit/Configuration.java Most end-user options will be moved to ./configure eventually. SableJIT Defines ---------------- Notes: 1) List may not be exhaustive 2) Some configurable via ./configure 3) Not all configuration combination tested. General -DSABLEJIT Turn on JIT support code -DSABLEJIT_VERBOSE Verbose mode -DSABLEJIT_DEBUG Debugging info -DSABLEJIT_DEBUG_GC Used to debug GC-related bug -DSABLEJIT_DEBUG_REF Checks if object ref is valid. -DSABLEJIT_DEBUG_REF_NATIVE Checks native refs by traversing list. -DSABLEJIT_DEBUG_SAFETY_CHECKS asserts and other debugging helper. -DSABLEJIT_WARNING Prints warning. Recommended at all time. -DSABLEJIT_STATISTICS Collect stats. -DSABLEJIT_STATISTICS_INST_COUNT Count number of instructions interpreted. Keeps a separate count for intructions interpreted while the compiler is disabled. -DSABLEJIT_STATISTICS_EXP_RATIO Some stats on how big the equivalent switch code gets compared to the inline-threaded code. -DSABLEJIT_STATISTICS_PREPARE_COUNT Count number of PREPARE_* executed by compiled code and interpreter (-C int) mode. -DSABLEJIT_STATISTICS_INTR_STUB_COUNT Count number of invokes: compiled code --> intr code. -DSABLEJIT_TESTING Adds support for running test cases (ex: compilation of __compile_me) Note: SABLEJIT_DEBUG implies SABLEJIT_VERBOSE SABLEJIT_VERBOSE implies SABLEJIT_WARNING and SABLEJIT_STATS Specific options: -DSABLEJIT_ENABLE_POOL_LIMIT Limit the maximum number of compilations in progress. -DSABLEJIT_COMPILER_POOL_LIMIT The actual limit Recompilation of method that are using slow variant (preparation sequence) -DSABLEJIT_ENABLE_RECOMPILATION -DSABLEJIT_RECOMPILATION_REQUESTS_THRESHOLD -DSABLEJIT_PARTIAL_SUPPORT Compiles in a demo example of compiling a hot loop. Note: The example itself have been removed for now. -DSABLEJIT_USING_DIRECT_INTERPRETER - provide JIT support for the direct interpreter -DSABLEJIT_USING_INLINED_INTERPRETER - provide JIT support for the direct interpreter -DSABLEJIT_USING_STACK_OFFSETS Stack size at each opcode is sent to the Sa -DSABLEJIT_USING_SYNC_INFO SableVM will pass to the JIT whether this method is synchronized or not. -DSABLEJIT_SYNC_IN_CALLEE Synchronization code is moved from caller to callee in order to use runtime information about synchronization. --- deprecated... ------ -DSABLEJIT_COMPILE_COMPILE Enable compilation of Compiler.compile(). ------------------------- --- deprecated ------ -DSABLEJIT_COMPILE_ON_FIRST_INVOKE Try to compile the method the first time it is invoked. Normally, the method is interpreted the first time it is invoked and compiled right before its second invocation. Note: This compiles in support for this option. It must explicitely be enabled at runtime with the '-C first' switch. see SABLEJIT_COMPILE_ON_FIRST_INVOKE_SUPPORT --------------------- -DSABLEJIT_COMPILE_ON_FIRST_INVOKE_SUPPORT Compile in code to be able to compile before first invoke. To actually, compile before first invoke, on the command line do: -C intr-count=0 This profiling code was not used (incompleted/not well tested) and was making SableVM code difficult to read... Will probably be re-implemented later in a more clean way. Deprecated: -DSABLEJIT_PROFILING Compile in better profiling code rather than simply compiling on first or second method invocation. Use SABLEJIT_PROFILING_THRESHOLD to set up the compilation threshold value. Deprecated: -DSABLEJIT_PROFILING_THRESHOLD=value Setups up the default compilation threshold value. If any counter reaches the threshold value, compilation of the method will start. Deprecated but not removed. -DSABLEJIT_PROFILING_COMPILE_AT_BRANCH Allow compilation to be triggered and started on backward branches. *** Requires: SABLEJIT_USING_STACK_OFFSETS -DSABLEJIT_RECOMPILING_AT_BRANCH Adds support for recompilation at switching to compile code at branch. -DSABLEJIT_COMPILATION_AT_BRANCH_SUPPORT Adds compilation/recompilation support for branches. (used internally) New profiling framework: -D_SABLEJIT_PROFILING_METHOD Profile method entry -D_SABLEJIT_PROFILING_METHOD_DEFAULT_THRESHOLD=value Threshold used in interpreter. -D_SABLEJIT_PROFILING_METHOD_DEFAULT_CALLBACK_THRESHOLD=value Invoking non-compiled method from compiled code is expensive. --------- Renamed, see below -DSABLEJIT_LIGHTWEIGHT_EXCEPTION_CHECKS Very light weight exception checking for compiled method. In fact, no null checks and no save current pc code. pc will be compute if exception occurs. -DSABLEJIT_LIGHTWEIGHT_NULL_POINTER_CHECKS -DSABLEJIT_LIGHTWEIGHT_ARRAY_BOUNDS_CHECKS Supported on powerpc. Generates a SIGTRAP for null pointers or array out of bounds. The check needs a single instruction and there are much less code (no code to throw exception in compiled code). However, processing exceptions is more expensive. Note: Possible to have no check at all for null pointer but slightly more difficult. --------- SABLEJIT_SIGNALS_FOR_EXCEPTIONS__NULL (bpc is computed from native pc) sigsegv -> null pointer SABLEJIT_SIGNALS_FOR_EXCEPTIONS__DIV_BY_ZERO sigfpe -> ArithmeticException SABLEJIT_TRAPPING_NULL_POINTERS sigtrap for null SABLEJIT_TRAPPING_DIV_BY_ZERO sigtrap for division by zero SABLEJIT_TRAPPING_ARRAY_BOUNDS sigtrap for out-of-bounds SABLEJIT_TRAPPING_SUPPORT - defined if one of the SIGTRAP is defined (internal, adds support for SIGTRAP handler, etc.) SABLEJIT_SIGNALS_FOR_EXCEPTIONS_SUPPORT defined if we have some or all the way for exceptions with signals. Deprecated - unsupported: -D_SABLEVM_PROFILER Dump a stack trace at regular intervals. SABLEJIT_CODE_POINTER Saves compiled_code in the stack. Simplifies GCC and makes table jump more efficient. Very CPU-specific options ------------------------- Warning code compiled with these may not run on other CPUs of the same family. I doubt difference in performance will be noticeable. -DSABLEJIT_CPU_PPC_750FX Specify that we are compiling for the PowerPC 750FX. Will set SABLEJIT_CPU_PPC_CACHE_BLOCK_SIZE correctly. -DSABLEJIT_CPU_PPC_CACHE_BLOCK_SIZE Specify the cache block size. This is use when flushing cache for generated code. Size is in number of bytes. Note to Users of Debugging Tools -------------------------------- *** Update: This is no longer relevant if you are using the default binary compatibility mode (ADDRESS mode). If you are using debugging tools that affects library loading, when compiling SableJIT, you need to ensure that the environment is the same when the compiling process will invoke SableVM to get symbol addresses. SableVM is invoked to generate constant.out. See src/Makefile. You may want to use the SABLEVM_BIN_PREFIX environment variable to prefix the sablevm command. For example on GNU/Linux/x86, to use Valgrind, you will need to build SableJIT as: make clean && make SABLEVM_BIN_PREFIX=valgrind If you use libMallocDebug on Mac OS X or similar libraries on other platforms, make sure that when you build SableJIT the same libraries are loaded by setting your environment the same way. FAQ --- When running test cases: Q. It does a SIGILL or SIGSEGV on the first method it compiled, no matter what that method is. A. It is very unlikely, but it may be possible that SableJIT incorrectly detect your platform. You may want to have a look in: src/sablejit/Configuration.java. The field IRBUILDER_FACTORY should be: sablejit.OnePassX86 on x86 and sablejit.OnePassPPC on ppc Try a simple test such has test_aconst_null. In the src/sablejit directory do a: make test TESTNAMES=test_aconst_null The --with-sablejit-force-platform may be used to specify the correct platform. If this fixes it, report this problem as a bug. Q. It crashes after a short time running the provided test cases. It does a segmentation fault or reaches code in SableVM that should not be reached. A. Did you recompiled SableJIT after modifying and recompiling SableVM? Do also a make clean before recompiling it. SableJIT support some but not any changes done to SableVM configuration. When running on an application: Q. I get Exceptions. Are they due to bugs? A. It depends on the exception type: *** Update: Implementation is mostly complete. Any compilation exceptions should be reported as bugs. - NotPreparedException, NotImplementedException, NotSupportedException Things that are not implemented. - Other exceptions types should be reported as bugs How to try on new platforms --------------------------- If your platform is not officially supported but it may work, you will have to explicitly specify it via the --with-sablejit-force-platform=PLATFORM ./configure options ("./configure --help" for details). If it works, fine, report the $host string for your platform to the SableVM developer mailing list so it can be added to the known ones. How To Submit A Bug Report -------------------------- Note: I am mostly interested in bugs that can be easily reproduced and that can be isolated in a small piece of code but you may send any bug information to the SableVM developer mailing list. Note: If you send code that reproduce the bug, I may add this code to the test cases. The test cases are also under the LGPL. Let me know if this causes any problem. Performance ----------- I removed the very old measurements. I will add new ones later. Have fun! David Belanger dbelan2@cs.mcgill.ca =========== End-of-file ===========