[Mono-list] JVM performance: JVM as a basis for CLR

Fergus Henderson fjh@cs.mu.oz.au
Thu, 26 Jul 2001 15:24:47 +1000


On 25-Jul-2001, Jay Freeman saurik" <saurik@saurik.com> wrote:
> First off, I would like to make the point that I wasn't taking about .NET
> being usable to construct faster code by giving end users more language
> features.  I agree that .NET is better there; sorry about the oversight.  I
> was working under the impression that this thread was trying to show that
> there is something that, given two programs that had the same logic, allowed
> a compiler and a JIT for the CLR to operate faster than the a compiler and a
> JIT for a JVM.

If users can use the new features to write more efficient code, then compilers
can do the same.

> I am not looking at things like value types as those are
> things that the user of the system needs to deal with, not the compiler, and
> leads to a program with different basic logic.

That's not necessarily true at all.
If you write your source program in C#, using value types,
or in Eiffel, using "Expanded types", or in Ada,
using records, that doesn't prevent it from being compiled to the JVM.
In fact, I think there are already Ada->JVM and Eiffel->JVM compilers around.

So when using these languages, the source code and the program logic will
remain unchanged regardless of which VM you compile it to, but if you
compile it to the CLR, then these source language constructs will be
mapped to value types, whereas when you compile it the CLR, they will
map to heap allocation, which IMHO is likely to be less efficient.

The JVM will probably be just as good as the CLR for programs written in Java,
but for programs written in languages that differ from Java, the CLR is likely
to be faster.

> Same with function pointer
> types, that is something the end user can use, but it isn't something about
> the file format that the compiler can use to make the JIT work better
> without the developer explicitely doing it,

That's not true.  For example, the Mercury->CLR compiler uses function pointers
to implement nondeterminism (backtracking).  For the Mercury->JVM compiler,
we'll have to use heap-allocated objects with virtual functions instead.

The Mercury programmer will write nondeterministic Mercury code that
doesn't make any use of function pointers or higher-order functions or
anything like that, and for the CLR the Mercury compiler will compile
that to something which happens to use function pointers.  The Mercury
programmer may well be completely unaware that the Mercury compiler is
using function pointers.

> rather it allows you to
> drastically change how the program works.  It _is_ a good point however, it
> allows you to directly support more languages,

Not really, since anything you can do with function pointers, you can also
do with heap-allocated objects with virtual functions.  It's just that
the latter approach may be less efficient.

> OK, talking Java here, as the CLR does _need_ tail. for the reasons you
> mentioned:
...
> you should be able to do this all of the time without any issue
> of safety (under the assumption the code you are going to doesn't have more
> trust, of course, in which case you can't do this, but that is a case that
> you notice immediately while doing code generation) or any complex detection
> operation: if you see a "call", "calli", or "callvirt" instruction
> immediately followed by a "ret"
> (...) turn it into a tail call.

That is safe so long as you can't take the address of local variables,
which is true for Java.

So I agree that the JVM doesn't need any special "tail call" instruction
in order for the JIT to be *able* to optimize tail calls.

However, the problem is two-fold:

	(1) Some languages need a *guarantee* that tail call optimization will be
	    done.  The JVM doesn't provide that.

	(2) Even though JITs may be able to optimize tail calls,
	    in practice most (all?) current JITs don't do so,
	    except for the unimportant easy case of direct tail recursion.
	    So even for languages which don't need a guarantee,
	    this approach doesn't work in practice on current JVM implementations.

Problem (2) could be solved without adding any new JVM instructions, just by
improving existing JVM implementations, but that would still leave problem (1).

-- 
Fergus Henderson <fjh@cs.mu.oz.au>  |  "I have always known that the pursuit
The University of Melbourne         |  of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh>  |     -- the last words of T. S. Garp.