harmony-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Xiao-Feng Li" <xiaofeng...@gmail.com>
Subject Re: [drlvm] Helper inlining in JIT
Date Sun, 13 Aug 2006 13:29:46 GMT
Rana, good arguments. :-) Based on my experience in developing JIT and
GC in Java, I think there are two issues, or two levels of issues.

1. Runtime services inlining.

The word "helper" is not a widely-used term. I think the idea is to
enable JIT to inline the frequently accessed routines of JVM into Java
application jitted code. These routines are runtime services provided
by the components of JVM, including GC, threading, etc. In a C-written
JVM, they are native methods accessed by jitted code through JNI or
fast JNI or raw native interface, hence the performance could be a
problem, because a) the generated code sequence depends on the
compiler that compiled the JVM, b) the call/ret instructions and
parameter passing etc. have negative performance impact.

DRLVM is using and used manually-written machine code sequence or
specially-defined IR to solve this problem, so that the runtime
runtines code sequences are guaranteed or can be inlined. In order to
reduce the labor work and maintenance efforts, only the fast path of
the runtime service routines are manually written in machine code or
low-level IR.

This kind of code sequences are called "helpers" in DRLVM because they
are provided by the VM core to help JIT compilation. This design has a
problem that some of the runtime services actually are provided by
other components than VM core, such as GC. If GC changes, the code
sequence may be required to change accordingly. But the design goes
this way to pursue the JVM modularity: JIT only needs to query the VM
core for all the fast path services, and its VM core's role to
coordinate JIT compilation and other components.

It's desirable for respective components to provide their own services
and they are inlined by the JIT.  We can let GC to provide the object
allocation fast-path code sequence or low-level IR.  Then we need an
additional set of interfaces to talk about IR inlining besides current
simple C functions. For example, we can write the routine fast-path in
Java, so that the JIT compiler can inline them naturally, and what we
need is to define the Java interfaces for those services.

For example, the object allocation sequence can be written in Java in
a way like:
in Class GC_X,
Reference object_alloc(int size, Address vtable )
       Reference result = ThreadLocalBlock().alloc(size);
       if( ! free.isNull() ){
            result.setAddressAtOffset(vtable, VTABLE_OFFSET_IN_OBJECT);
            return result;

       //native slow path
       return object_alloc_slowpath(size, vtable);

This function is preformance critical. Its inlining can be achieved
automatically if a) the gc_alloc interface is known to JIT and b) the
JIT optimization inlines small size methods. (If JIT doesn't inline
it, annotation can be used to give instruction.)

These are obvious, and no special tricks are needed if all the methods
in the fast path are written in Java. It is not necessary for all the
methods in runtime service routines' fast-path to be written in Java.
They still can be supported by the idea of "helper" if that's
desirable. (For engineering purpose, native methods can be used as
well.) But how about if we still want to use Java to write them? Then
it comes to the second issue, a lower level issue.

2. Inlining of unsafe or low-level operations.

Java is not enough to write all runtime service routines. Because of
its safety property and platform independence, Java has no direct
memory access, no address arithmetics, and no direct platform-specific
operations. For example, Reference.setAddressAtOffset() is to store a
memory address into an offset position of a reference.
ThreadLocalBlock() is to retrieve thread local allocation block for
non-contended bump-pointer allocation, which needs OS specific
thread-local-storage access.  The alloc() invocation on
ThreadLocalBlock needs to do address arithmetic and memory access as

These routines are not able to be written in direct Java. We need to
tweak the Java language if we want to inline them. The tweaked Java
language is actually just to borrow Java syntax as the IR to denote
the unsafe or low-level operations. The advantage is we don't need any
other compiler, the JIT compiler understands JVM bytecode.

For example, the Reference class can be defined in this way:
Class Reference {
      int address;
      void setIntValueAtOffset(int value, int offset){
           // JIT to generate code of: *((int *)(address + offset) = value;
      // other methods

The method body is left empty intentionally for JIT to generate
whatever proper code sequence for its execution platform, which
requires the JIT understand the method as compiler intrinsics.
Annotations can be used to instruct the JIT compiler.

This kind of unsafe/lowlevel operations are not many, can be
categorized and well-defined. Any JIT that wants to inline the Java
fast-path has to understand them. (btw, this kind of tweaks is called
VMMagic in JikesRVM as I know. ) Well since the inlining is only a
performance optimization, we need consider if DRLVM wants to work with
a JIT not knowing the Java services.

WIth these two issues clarified,  this "helper inlining" proposal can
be seperate into two tasks. One is to develop unsafe/low-level Java
intrinsics; the other is to develop runtime service routines'
fast-path in Java (using native methods first, then Java intrinsics).

Then back to your question, when we have the service routines written
in Java, we can let JIT to compile and inline them automatically; when
the unsafe Java intrinsics are ready, we can achieve good performance
with both supports. No need to expose registers to Java level in
either task. :-)


On 8/12/06, Rana Dasgupta <rdasgupt@gmail.com> wrote:
> MIkhail,
>   I have some questions, or just arguments :-) First, though it is nice to
> talk of an open helper inlining framework to call VM/GC helpers, isn't the
> set of helpers used in  JVM's more or less well known and standardized? In
> other words, is a framework absolutely necessary, can't the jit just
> generate code inline for the known fastpath of the helper algorithm? For
> example if we replaced the DRLVM gc with gc_new , how many new helpers do
> you think we would introduce?
> Also, please see below for some inline comments...
> On 8/11/06, Mikhail Fursov <mike.fursov@gmail.com> wrote:
> >
> >
> > >Even this simple helper reveals a lot of features to support:
> >
> > >1) Access to TLS is required. It could be fs:[14h] on Windows or helper
> > call
> > >on Linux (depends on kernel (?) ). Even if we have an access to TLS we
> > need
> > >to know the offsets of our slots: 'current' and 'ceiling' in example.
> > >So we need to have a way to pass these values to JIT. May be a 'private
> > >static final' variables in the helper's class with special runtime
> > >annotations could be used to pass the values to JIT?
> So basically, every new VM would need to implement the helper in an almost
> identical way or at least using identical final variables...I wonder how
> much flexibility that leaves ..
> >2) Calls support is needed. Both for "slow" helper version and to access
> > >TLS.
> > >This means also that calling convention support is needed. Runtime level
> > >annotations for helper calls could be used here. E.g. create a magic
> > method
> > >'slow_alloc' and teach JIT to call real helper instead of it. Get the
> > >calling convention info from annotation (?)
> Is it not possible for the fastpath helper to just return a failure so that
> the jit generated conventional helper callpath can kick in. In other words,
> does the slow helper have to be called from the fast helper?
> >3) Do we really want to expose native regs to Java: EAX, ECX... I vote do
> > >not to use them when writing helpers in Java and to allow to JIT to
> > optimize
> > >unboxed operations (allocate registers by itself)
> This again goes back to my original question...if the JIT knew the standard
> fastpath, it could generate code optimally for it anyway with the best use
> of registers?
> These are just arguments before we set off developing a framework. I would
> like to know if helpers vary a lot across VM implementations, seems to me
> they need to do the same old things. Even if a framework is needed, it seems
> that we will land up inventing a language with unboxed primitives,  virtual
> register access and special calling conventions for it to work optimally.
> And then we want every VM to use this language to code fastpath helpers and
> also to code the slower helpers in the conventional way. Maybe we should ask
> VM developers to vote on how open this is....
> Thanks,
> Rana

Terms of use : http://incubator.apache.org/harmony/mailing.html
To unsubscribe, e-mail: harmony-dev-unsubscribe@incubator.apache.org
For additional commands, e-mail: harmony-dev-help@incubator.apache.org

View raw message