ARM backend for Jikes RVM

This page is for internal use at present, since the relevant source code and machines are local to cs.man.ac.uk.

The ARM backend for Jikes RVM was originally developed by Ming Chen. His Master's thesis [PDF/750KB] describes the initial development work on the baseline compiler. Ming has now left Manchester, and I have taken responsibility for developing the ARM backend. This page gives details of the project's current status.

Other useful links

How to build the source code

  1. Check out the source code for the Jikes RVM from the Jamaica group CVS repository. Use revision tag ARM_BACKEND, and CVSROOT set to /home/simgroup/cvsroot/
  2. Also GNU classpath source code is required. The ARM backend is based on Jikes RVM 2.3.2, which requires classpath 0.08.
  3. Login to antigua.cs.man.ac.uk
  4. Set appropriate environment variables for cross-compilation, on antigua (IA32, linux) and cuba (arm, linux) - e.g. RVM_ROOT=/home/simgroup/jsinger/arm_rvm RVM_BUILD=/home/antigua/jsinger/rvmbuild RVM_HOST_CONFIG=/home/simgroup/jsinger/arm_rvm/rvm/config/i686-pc-linux-gnu.antigua.jsinger RVM_TARGET_CONFIG=/home/simgroup/jsinger/arm_rvm/rvm/config/arm-pc-linux-gnu.ManCS In fact, all the environment variables are stored in scripts, which we execute as necessary. (one for antigua, one for cuba). . env_vars.(hostname) should set up all RVM environment variables properly.
  5. To create the build directory, run script jconfigure with argument BaseBaseNoGC (only compile baseline compiler using baseline compiler, with no support for garbage collection).
  6. Now change to directory $RVM_BUILD, and execute command ./jbuild - I did this on antigua. It should run, and finish with message: jbuild.linkBooter: (booter cleaned) please run me on Linux ARM 168 s jbuild: You need to run the linker on the appropriate platform. Note that lots of trace should be produced, showing the ARM machine instructions that are used in the compilation process of the RVM compiler.
  7. Now login to cuba.cs.man.ac.uk, cd to /home/simgroup/jsinger/. Set up environment vars by running script in arm_rvm_root/env_vars.cuba.
  8. cd rvmbuild. Execute ./jbuild -booter. Because of autoconf problems on ARM Linux, it is quicker to run a hacked script ./jbuild.linkBooter.faster, which does not recompile classpath source code.
  9. To test, run rvm. (No args necessary initially). It should output lots of trace to stdout, notably for ARM code generation.

Known issues and bugs

  1. Doesn't pass all bytecode tests - code generation for baseline compiler is not implemented for all bytecodes. And ARM code emit routines not implemented for all ARM instructions.
  2. rvm hangs as it tries to initialize classes. This is because the trap handler is called when segmentation faults occur (SIGSEGV) but the trap handler itself segfaults, causing an infinite recursion. Need to fix C code in cTrapHandler routine. Alternatively, run gdbrvm with handle SIGSEGV stop print, to catch segmentation faults.
  3. Rather suspicious about native method calls (JNI), and whether the calling conventions for bridging from Java to C and vice versa are correct. [FIXED]
  4. Also suspicious about locking mechanism (which uses atomic swaps)? Ming wasn't sure about this either.
  5. Issue with RVM_FOR_SINGLE_PROCESSOR flag. Should this be set to 1 on uniprocessor machine with flakey pthreads support? Hmmm. Currently set to 0 in arm-linux.ManCS config file and in jconfigure script. (This could have something to do with the deadlock mentioned above, since rvm locks up in the pthread scheduling lib code...) Now set to 1. [FIXED]
  6. Still having problems with com_ibm_jikesrvm_0005f_process.h header file, which should be in dir RVM.scratch, but isn't. I copy the file across manually from $RVM_ROOT/rvm/src/tools/bootImageRunner/ to $RVM_BUILD/RVM.scratch/.
  7. Issue of wild jumps/calls when running class initializers, causes segfaults. Not sure why this is happening yet. Something badly wrong with dynamic code generation (which doesn't seem to happen with code from the boot image). Problem caused because rvm writes dynamically generated code to data cache, but this is not flushed to main memory before instruction cache reads in code to execute it. So instruction cache fills up with junk. Solution is to flush data cache after dynamically generating code. Inefficient on ARM, can't flush individual cache lines, have to flush whole cache each time! [FIXED]
  8. At start of each method, rvm issues code to check whether we need to grow stack. This code is wrong for the case where the stack does need to grow, but we have never got far enough into rvm execution for this to happen. Resolved, the code causes a segfault, which is supposed to happen to signal that stack has overflowed. [RESOLVED]
  9. Large immediate constants for some VM_Assembler methods (larger than 8-bits I think) may not be supported. This is because ARM has smaller immediate fields in instructions than PowerPC.
  10. VM_Assembler overwrites values in some scratch registers that it shouldn't! In methods like emitANDI, where we need to use an extra register that we haven't got. This caused problems, so VM_Assembler now saves scratch register values and restores them when required. [FIXED]
  11. Get a segmentation fault, looking up something like:
    ldr r0, [r5, -#32]
    when we try to do floating-point code before calling java.lang.Double.<clinit>. Note that this is a late class initializer because it uses native methods. Can't use code from classes before their clinit method is called. [FIXED]
  12. ARM backend is based on PowerPC backend. PowerPC has a special register named REGISTER_ZERO which ARM does not have. Any REGISTER_ZERO references actually map onto T0, which rvm expects to be separate. Sometimes lose values like this. Need to eliminate all uses of REGISTER_ZERO in ARM backend. Note that REGISTER_ZERO is generally only used as an extra integer scratch register, can replace most uses with other scratch registers. [FIXED]
  13. JNI parameter passing still not quite sorted. Problems with splitting 64-bit values into two consecutive registers or stack slots. RVM convention is different to native ARM convention. Also, no code to deal with spilled parameters in Java->C transition. [FIXED]
  14. gnu classpath classes are not all being copied across to RVM.classes directory, so RVM can't pick them up at runtime. For instance, gnu.java.lang.reflect.TypeSignature cannot be found. This is an issue with jconfigure, which specifies which classes should be included in the RVM boot image.
  15. for Ming's bytecode test package, need to explicitly copy the test directory into $RVM_BUILD/RVM.classes - so compiler can pick it up properly.
  16. Issues with endianness. ARM port is based on PowerPC code, which is big-endian. However, ARM is little endian! Not all the code has been little-endianized properly! Very suspicious about VM_Compiler pushing,popping, and magically setting long and double values.