# Thursday, 30 March 2006
A Micro Optimization

Yesterday I thought of a potential micro optimization for the generated CIL code. Since I'm now tracking method invocations on the this reference, it is possible to devirtualize calls to final methods or methods that are provably not overridden. I didn't expect too much from this optimization, because I assumed that the .NET JIT is capable of doing the same optimization and so the only effective difference would be the removal of the explict null check of the this reference.

After implementing the optimization I wrote a micro benchmark:

final class perf {
  public static void main(String[] args) {
    perf p = new perf();
    p.runTest();
  }
  private void runTest() {
    long start = System.currentTimeMillis();
    for (int i = 0; i < 1000000000; i++) {
      equals(null);
    }
    long end = System.currentTimeMillis();
    System.out.println(end - start);
  }
}

Here are the results:

  Time (ms)
IKVM 0.26 10806
IKVM 0.27 1883
JDK 1.1 4597
JDK 1.5 Client VM 12068
JDK 1.5 Server VM 0


Somewhat to my surprise neither JDK 1.5 Client VM nor the .NET Framework JIT realised that the virtual method invocation could be devirtualized. Unsurprisingly, HotSpot Server VM was able to deduce that the loop didn't actually do anything at all and optimize it away entirely.

I also threw in JDK 1.1, because as usual in microbenchmarks it outperforms HotSpot Client VM.

Note that the use of the equals method in the benchmark is not very significant, it's just a placeholder for a simple method that can easily be inlined. This optimization is most significant for simple property getters that can be inlined.

The code for this optimization is not yet in cvs.

Oops

On a more embarrassing note, doing this optimization also revealed a hole in the object model remapping. Throwable doesn't properly inherit all the Object methods. The code that gets generated works correctly (in most cases), but it is not verifiable. Here's an example of something that is currently broken:

public class test extends Throwable {
  public static void main(String[] args) throws Exception {
    test c = new test() {
      protected Object clone() {
        return "OK";
      }
    };
    System.out.println(c.clone());
  }
}

Running this on IKVM throws a CloneNotSupportedException instead of printing OK.

Thursday, 30 March 2006 11:08:03 (W. Europe Daylight Time, UTC+02:00)  #    Comments [1]
# Friday, 24 March 2006
Rotor 2.0 released

Microsoft released Rotor 2.0. Rotor is the Shared Source implementation of the CLI (and shares a large part of the code with the .NET Framework 2.0).

Congratulations and thanks to the Rotor team!

Friday, 24 March 2006 16:07:55 (W. Europe Standard Time, UTC+01:00)  #    Comments [0]
# Thursday, 23 March 2006
IKVM 0.26 Released

I finally got around to releasing the 0.26 bits (identical to rc2). Get them here.

Thursday, 23 March 2006 13:34:00 (W. Europe Standard Time, UTC+01:00)  #    Comments [1]
# Saturday, 11 March 2006
IKVM 0.26 rc2

A new release candidate. It turns out I was a little over enthusiastic in restructuring the class loading to move dynamic class loading into a subclass (which I did to make it easier to build a version of IKVM.Runtime.dll that doesn't support dynamic class loading, to run on the Compact Framework). java.lang.reflect.Proxy support requires that you can dynamically load classes in the bootstrap class loader, so I added back support for that (in a hacky way by delegating to a bogus instance of DynamicClassLoader). This bug was reported by Chris Keller who was also kind enough to fix two socket bugs.

Changes:

  • Restored the ability to dynamically load a class in the bootstrap class loader.
  • Changed PlainSocketImpl to throw java.net.SocketTimeoutException instead of java.io.InterruptedIOException when a timeout expires.
  • Changed PlainSocketImpl.read() to return zero instead of throwing an exception when a non-blocking socket read would block.

Files are available here: ikvm-0.26.0.1.zip (sources + binaries), ikvmbin-0.26.0.1.zip (binaries), ikvmbin-generics-0.26.0.1.zip (binaries built from generics branch)

Saturday, 11 March 2006 19:48:06 (W. Europe Standard Time, UTC+01:00)  #    Comments [0]
# Wednesday, 08 March 2006
IKVM 0.26 rc1

A new release candidate based on GNU Classpath 0.90 (the successor to 0.20). IKVM.GNU.Classpath.dll grew by more than a megabyte. A big part of this is due to the new crypto implementation that was merged into GNU Classpath. This a great improvement!

Updated japi results are available here.

  • Integrated GNU Classpath 0.90
  • Updated classpath.security with new security providers
  • Added "Windows Vista" as a possible value of os.name system property
  • Included VMObjectInputStream.currentClassLoader() fix from Classpath version
  • Fixed Float.toString() bug (1E8 would be converted to "1E+08.0" instead of "1.0E8")
  • Made some VMThread members package accessible to avoid accessor methods
  • Added copyright banners to executables (when run without command line arguments or with the -version option)
  • Added "-showversion" option to ikvm.exe
  • Fixed ikvmstub to use IKVM.Runtime.Util.GetClassFromTypeHandle() instead of IKVM.Runtime.Util.GetFriendlyClassFromType(), because that would cause problems on remapped types in mscorlib.
  • Fixed support for dynamically instantiating a class that was not loadable at method compilation time.
  • Added support for running interface static initializer when accessing a final field.
  • Moved most .NET resource reading code from IKVM.GNU.Classpath to IKVM.Runtime, to make it easier to use new resource and compression APIs on Whidbey.
  • Introduced ikvm.io.InputStreamWrapper (wraps a java.io.InputStream around a System.IO.Stream).
  • Removed undocumented -manifestResources ikvmc option. When compiled for Whidbey, resources are now always stored as manifest resources.
  • When compiled for Whidbey, resources are now compressed using DeflateStream instead of custom compression.
  • Changed SoftReference never to be cleared, since there is no reliable way to detect low memory and clearing them too eagerly breaks Eclipse.
  • Fixed ikvmstub to also export implemented interfaces that are non-public.
  • Split off dynamic class loading support from ClassLoaderWrapper.cs into new DynamicClassLoader.cs.
  • Moved static compiler support from vm.cs to new file CompilerClassLoader.cs.
  • Fixed CompiledTypeWrapper and DotNetTypeWrapper to finish base class and interfaces in their Finish method.

Files are available here: ikvm-0.26.0.0.zip (sources + binaries), ikvmbin-0.26.0.0.zip (binaries), ikvmbin-generics-0.26.0.0.zip (binaries built from generics branch)

Wednesday, 08 March 2006 11:14:37 (W. Europe Standard Time, UTC+01:00)  #    Comments [1]