Optimisation work on Zero/ARM
Edward Nevill
enevill at arm.com
Fri Jul 10 02:46:01 PDT 2009
>I quickly tested to run your compiled binaries on a ARMV5TE
>Sheeva-plugcomputer running Ubuntu Jaunty and it worked as expected!
>Gave me instantly a 3.3 X improvement on the jython test in the dacapo
>benchmark.
>http://www.dacapo-bench.org/
Good. Thats what I like to hear. I have added dacapo to my benchmark suite.
>I am thrilled to try combine your work with the LLVM based Shark JIT.
At the moment the assembler interpreter does not pay any attention to
UseCompiler. If UseCompiler is set the assembler interpreter will in
fact just call the C interpreter instead. This is done once on init
so if UseCompiler is set on init it reverts completely back to C.
(There is also a backdoor if you ever want to run the C interpreter,
Specify -XX:+PrintCommandLineFlags on the command line and it will
revert completely to C).
It is possible to make the asm interpreter pay attention to UseCompiler
(its not that difficult and should have little impact on performance).
What does Shark use for profiling, does it use CountCompiledCalls and
UseLoopCounter? - or something else).
The asm interpreter maintains the same frame structure. I have added
one word at offset 28 from the lowest address of the frame (ie istate)
This is ISTATE_SAVED_ISTATE where it saves the previous istate. This
Is overlaid with the ISATE_MSG which the asm interpreter does not use.
I am not clear how Shark (or any JIT for that matter) replaces a
threaded method (ie if you are executing say, SieveAtom, how does
it hijack control from the interpreter?). And how does it replace
methods which might be lower down on the machine stack. I can see
how you might do this non portably by grubbing around on the
machine stack. It could also be done more portably by using
say setcontext() and getcontext() in the interpreter so the
compiler can unwind the interpreter and then continue executing
in compiled code (at the location corresponding to the saved byte
code pointers).
Is there any docs to describe how this is done? Or pointers to where
I should look?
>I peeked at the sourcecode and it looks great!
>Your changes are most portable for inclusion into Icedtea6/OpenJDK since
>they are already contained in separate patches against the Icedtea6 tree
>from 23 june 2009 in the debian/patches directory, fantastic.
Would you be happy to review the changes for inclusion into IcedTea.
There are 3 diff files in debian/patches relating to the asm interpreter,
the rest of them all relate to the debian port. The 3 diffs are
=== zero-notice-safepoints.diff
This is the only change to the shared code and is a single line change
to change the definition of notice_safepoints() and ignore_safepoints()
in cppInterpreter.hpp to a declaration. This is currently conditionalised
on PRODUCT && HOTSPOT_ASM but it might make more sense to conditionalise
it on say something like CPP_INTERPRETER_NOTICES_SAFEPOINTS. Alternatively
it could be changed unconditionally as it seems pointless to me at least
to have a definition in a shared header file so that it cannot be
overridden by any code that actually wants to use it. What is the point
of the function call in the first place if there is just a null
implementation in its header file.
=== zero-asm-port.diff
This contains the diffs to the ports/... part of IcedTea. The diffs are
quite small (141 line) and are there mainly to provide hooks for the asm
interpreter. The files affected are
- zero.make
Adds cppInterpreter_arm.o and rules to build it.
- bytecodes_zero.cpp
Adds definitions for bytecode pairs and fast version of invoke and getfield.
- bytecodes_zero.hpp
Declarations for the above
- cppInterpreter_zero.cpp
Adds a single call to 'asm_generate_method_entry(...)'. This is
conditionalised on PRODUCT and HOTSPOT_ASM and is called
if (!UseCompiler && !TaggedStackInterpreter && !JvmtiExport... &&
!PrintCommandLineFlags) {
asm_entry = asm_generate_method_entry(kind);
if (asm_entry)
return(this->generate_entry(asm_entry));
}
So, if the asm interpreter can execute this 'kind' of method it returns
the entrypoint, otherwise NULL and the CPP interpreter returns its
entrypoint instead.
- os_linux_zero.cpp
This adds a hook to allow the asm interpreter to detect Null pointers
using SIGSEGV and does, in the signal handler
if (sig == SIGSEGV) {
if (asm_check_null(uc)) return 1;
}
Ie. if the assembler interpreter can handle it because it was one of its
null pointer checks it just returns 1 and continues execution (the asm
interpreter has updated the PC to point to 'null_pointer_exception'.
=== zero-asm-newfiles.diff
This diff contains the new files for the asm interpreter. These all go into
ports/hotspot/src/cpu/zero/vm. The files are
bc.def - The bytecode definition file
bytecodes.s - generated (manually) by 'mkbc' from bc.def
cppInterpreter_asm.S - support code for bytecodes.s
mkbc.c - The bytecode interpreter generator source
Note: At the moment the bytecode interpreter generator is not integrated
into the build, you have to manually do
gcc -o mkbc mkbc.c
mkbc bc.def bytecodes.s
This is why bytecodes.s is also check in. Obviously it would be more
desirable to integrate 'mkbc' into the build so we do not have generated
files checked in.
I have tried to keep the actual diffs (where existing files are
modified), especially any which involve changes to shared code as these
need to be merged into OpenJDK.
BTW: I have signed the SCA so it is OK for any of these changes to be
checked into OpenJDK. ARM has disclaimed copyright interest as per
GPLv2 (although I have yet to get this in writing:-(). I have also
requested the JCK from Sun so hopefully should be in a positions to
verify it as Java Compliant.
Best Regards,
Ed.
More information about the zero-dev
mailing list