I looked through the list of TODO projects for JIT [1] and decided to write a microbenchmark detecting how good interface call devirtualization works in JIT (see below)
Jitrino.OPT showed very-very slow (~2.5 times slower than JRockit (1.5/linux)). I looked through the compile-time log of Jitrino.OPT (see below) and found the reason: Jitrino.OPT did *not* hoist "interface vtable address load instruction (ldintfcvt)" above the hottest loop. At the moment, I would wait a little before hacking load hoisting since it looks more complicated than interface call devirtualization. A strange thing, "interface call devirtualization" would have boosted JRockit's performance too (I checked that with a slightly changed benchmark). So, that would be interesting to implement it! Seems like the best choice is to start from a couple of easy heuristics: * if there is only one loaded class to implement the interface, choose it * if there are more, choose the one with it's method invoked earlier (compiled by some JIT, possibly, some other JIT), * if we have many candidate methods that are compiled, choose the most frequent one (need a method-entry profile, the feature is likely to stay untouched for a while, I guess) 4 questions for now: 0. Does anybody want to participate? :))) I am always ready to help with implementation details. 1. Does anybody have some additional elegant ideas? 2. How do you like the benchmark? 3. Should I create a JIRA for the issue ASAP? :) P.S.: The benchmark: -------------------------------------------------------------------------------- import java.util.Date; interface Intfc { public void reset(); public void inc(); public int getNum(); static final long exercise = 1000000000; } class IntfcImpl implements Intfc { public IntfcImpl() { reset(); } private int num; public void inc() { num++; } public int getNum() { return num; } public void reset() { num = 0; } } class Runner { public Runner(Intfc o) { intfc_obj = o; } public void run() { intfc_obj.reset(); /* uncomment to test performance on a non-devirtualized version */ //IntfcImpl impl_obj = (IntfcImpl) intfc_obj; for (long i = 0; i < Intfc.exercise; i++ ) { intfc_obj.inc(); /* uncomment to test performance on a non-devirtualized version */ //impl_obj.inc(); } } public void measureTime() { Date before, after; before = new Date(); run(); after = new Date(); System.out.println("run: " + (after.getTime() - before.getTime())); } private Intfc intfc_obj; } public class IntfcCaller { public static void main(String[] args) { IntfcImpl obj = new IntfcImpl(); // use obj a little obj.reset(); obj.inc(); Runner runner = new Runner(obj); runner.measureTime(); runner.measureTime(); runner.measureTime(); if ( obj.getNum() != Intfc.exercise ) { System.out.println("FAIL"); System.exit(1); } } } -------------------------------------------------------------------------------- to get the compile-time log of method Runner::run() I put an extra option: -Xjit LOG=\"singlefile,root=all,method=run\" A piece of loop body: -------------------------------------------------------------------------------- Block L5: Predecessors: L4 Successors: L6 UNWIND I43:L5: I27:tauhastype t18,cls:Intfc -) t20:tau I28:ldintfcvt t18,cls:Intfc ((t19)) -) t21:vtb:cls:Intfc I29:ldvfnslot [t21.Intfc::inc] ((t19)) -) t22:method:inc I31:callimem [t22](t18) ((t19,t20)) -) GOTO L6 -------------------------------------------------------------------------------- Even the highest optimization level (option -Xjit opt::skip=off) does not help :( [1] http://mail-archives.apache.org/mod_mbox/incubator-harmony-dev/200606.mbox/[EMAIL PROTECTED] -- Egor Pasko, Intel Managed Runtime Division --------------------------------------------------------------------- Terms of use : http://incubator.apache.org/harmony/mailing.html To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]