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
- 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/
- Also GNU classpath source code is required. The ARM
backend is based on Jikes RVM 2.3.2, which requires classpath
0.08.
- Login to antigua.cs.man.ac.uk
- 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.
- To create the build directory, run script jconfigure with argument
BaseBaseNoGC (only compile baseline compiler
using baseline compiler,
with no support for garbage collection).
- 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.
- 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.
- 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.
- 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
- 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.
- 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.
- Rather suspicious about native method calls (JNI),
and whether the calling conventions for bridging from
Java to C and vice versa are correct. [FIXED]
- Also suspicious about locking mechanism (which uses
atomic swaps)? Ming wasn't sure about this either.
- 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]
- 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/.
- 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]
- 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]
- 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.
- 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]
- 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]
- 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]
- 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]
- 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.
- 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.
- 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.