Shark bites ARM
Publiziert: 27. March 2009, Verfasst von: rschuster, Tags:arm,BeagleBoard,buglabs,icedtea,mips,openjdk,shark
No this post is not about a tragic accident.
It is about the half-way successful attempt to get the Shark JIT compiler, which is funded by Red Hat and developed by Gary Benson as part of the Zero (assembler) port of the Hotspot Java VM, running on devices equipped with ARM processors. If this catches your interest then you won’t be dissappointed.
The state of the union is this:
root@beagleboard:~# ./azureus 1 java.lang.String::equals (88 bytes) 2 java.lang.String::hashCode (60 bytes) 3 java.lang.String::indexOf (151 bytes) file:/usr/share/java/Azureus2.jar ; file:/usr/share/java/swt-gtk-3.4.jar ; file:/home/root/ 4 ! sun.nio.cs.US_ASCII$Encoder::encodeArrayLoop (279 bytes) 5 java.lang.String::lastIndexOf (156 bytes) 6 java.lang.String::charAt (33 bytes) 7 java.util.Properties$LineReader::readLine (452 bytes) 8 java.util.Properties::loadConvert (505 bytes) 9 java.lang.Object::<init> (1 bytes) 10 java.io.UnixFileSystem::normalize (75 bytes) 11 java.lang.String::replace (142 bytes) 12 java.lang.String::indexOf (166 bytes) 13 sun.net.www.ParseUtil::encodePath (336 bytes) 14 java.lang.String::startsWith (78 bytes) 15 java.util.jar.Manifest$FastInputStream::readLine (167 bytes) 16 ! java.io.BufferedReader::readLine (304 bytes) 17 ! sun.nio.cs.US_ASCII$Decoder::decodeArrayLoop (241 bytes) 18 java.lang.String::getChars (66 bytes) 19 sun.misc.MetaIndex::mayContain (51 bytes) 20 java.lang.CharacterData::of (120 bytes) 21 java.lang.CharacterDataLatin1::getProperties (11 bytes) 22 java.lang.Math::min (11 bytes) 23 java.util.HashMap::indexFor (6 bytes) 24 java.lang.String::startsWith (7 bytes) 25 java.lang.String::<init> (20 bytes) 26 sun.misc.URLClassPath::getResource (74 bytes) 27 java.lang.AbstractStringBuilder::append (60 bytes) 28 ! sun.nio.cs.ISO_8859_1$Encoder::encodeArrayLoop (356 bytes) 29 org.gudy.azureus2.core3.util.ByteArrayHashMap::hash (29 bytes) 30 java.util.HashMap::hash (23 bytes) 31 ! sun.nio.cs.ISO_8859_1$Decoder::decodeArrayLoop (263 bytes) 32 java.nio.Buffer::position (42 bytes) 33 java.nio.charset.CoderResult::isUnderflow (13 bytes) 34 ! java.net.URL::<init> (543 bytes) 35 java.util.HashMap::put (126 bytes) 36 java.util.HashMap::transfer (83 bytes) 37 java.util.HashMap::get (79 bytes) 38 java.lang.Character::toLowerCase (9 bytes) 39 java.lang.CharacterDataLatin1::toLowerCase (39 bytes) 40 java.lang.String::toLowerCase (436 bytes) # # A fatal error has been detected by the Java Runtime Environment: # # Internal Error (os_linux_zero.cpp:223), pid=1728, tid=1762903184 # Error: caught unhandled signal 11 # # Java VM: OpenJDK Shark VM (14.0-b08 mixed mode linux-arm ) # Distribution: Built on Debian GNU/Linux unstable (sid) # An error report file with more information is saved as: # /home/root/hs_err_pid1728.log # # If you would like to submit a bug report, please include # instructions how to reproduce the bug and visit: # http://icedtea.classpath.org/bugzilla #
This may look terrible to you, but is actually much much more than what we had the weeks before. Lets tell the story from the beginning.
As you may have read on the BugLabs blog tarent was contracted to get OpenJDK running on the Bugs. Since BugLabs uses a variant of OpenEmbedded named Poky this meant getting OpenJDK cross-compiled. This alone was an interesting and complicated thing but was eventually finished and I did a presentation at FOSDEM 2009 about this work (slides: PDF ODF).
The work on OpenJDK contained three parts:
- get it running with the Zero port
- get it running with Cacao as the VM
- get as far as possible with Zero and the Shark JIT compiler
The first two items where completed in time and showed good results. Back in February the cross-compiled Shark was based on LLVM 2.4 and could barely display “Hello World” and then crashed abruptly. In the following weeks I had no time to look at this problem. However at FOSDEM I met Xerxes Ranby who is also interested in getting OpenJDK (through IcedTea) running on his ARM devices.
This is what HelloWorld looked like:
root@beagleboard:~# java HelloWorld Hello World! java: /home/rob/oe/beagle/tmp/work/armv7a-angstrom-linux-gnueabi/llvm-2.4-r0/llvm-2.4/include/llvm/CodeGen/MachineOperand.h:251: int64_t llvm::MachineOperand::getImm() const: Assertion `isImm() && "Wrong MachineOperand accessor"' failed. Aborted
Things started moving again last monday (23rd). Efforts to find out what is wrong with LLVM 2.4 eventually culminated in using the next release 2.5 since the method in which the error occured was already removed.
To my pleasure the update had the immediate result that the major Java enterprise application (aka HelloWorld) worked flawlessly:
root@beagleboard:~# java -XX:+PrintCompilation HelloWorld 1 java.lang.String::equals (88 bytes) Hello World!
The line above “Hello World!” indicates that Shark has compiled a method and run it. Nice!
Yet, lesser known Java applications like Azureus had a little trouble:
root@beagleboard:~# ./azureus 1 java.lang.String::equals (88 bytes) 2 java.lang.String::hashCode (60 bytes) 3 java.lang.String::indexOf (151 bytes) file:/usr/share/java/Azureus2.jar ; file:/usr/share/java/swt-gtk-3.4.jar ; 4file:/home/root/ ! sun.nio.cs.US_ASCII$Encoder::encodeArrayLoop (279 bytes) 5 java.lang.String::lastIndexOf (156 bytes) 6 java.lang.String::charAt (33 bytes) 7 java.util.Properties$LineReader::readLine (452 bytes) 8 java.util.Properties::loadConvert (505 bytes) Cannot yet select: 0x8ed18: i32,ch = AtomicCmpSwap 0x8e2f4, 0x8ea70, 0x8eeb0, 0xdf2a8 <0x11844c:0> <volatile> alignment=4
Aborted
This time the reason is to be found in the last line. It tells you that it cannot generate machine code for “AtomicCmpSwap”.
At first I tried my luck getting this support into LLVM. However I am not the compiler guy and had my difficulties understanding how that should be done. I am sure that someone with the neccessary knowledge could do it in a few minutes …
Nevertheless Xerxes Ranby had the cool idea to try something different. The use of the “AtomicCmpSwap” comes from the Shark implementation itself. The function is a built-in or intrinsic in LLVM and really can be considered to be like a function. Xerxes’ idea now was to replace the use of “AtomicCmpSwap” with a call to a function that does exactly the same and is implemented within Zero. When I came home today Xerxes already had a patch for me to try out. I rebuilt Shark and after installing it on my Beagleboard started Azureus. The result is what I called the state of the union above.
Since it is clear we are on a winning streak work on this is continuing right now. For all the mentioned experiments we where using IcedTea 1.4 and 1.4.1 which are more than 4 weeks old. In the meantime a lot of changes have been applied to Shark. Keep your fingers crossed that I can soon show you some nice screenshots of a Java app running on Shark.
PS: LLVM’s MIPS backend is also missing atomic operations support and our approach to it, will work there as well.
Great work Robert and Xerces! It was great to meet you both in person at FOSDEM, and am looking forward to more news on LLVM+OpenJDK!
Nice work! One little thing though:
Not exactly…
PrintCompilationprints when it starts compiling the method, so for Hello World the VM exited before the compilation completed. You need to useSharkTraceInstallsif you want to see when the compiled methods are inserted.