# Wednesday, 25 June 2008
Exception Performance Part 1

One area where IKVM performance is much worse than HotSpot is in throwing and catching exceptions. This blog is the first of three that will look into why this is the case.

We start out with two microbenchmarks to highlight the differences.

Java

public class ExceptionPerf1 {
  public static void main(String[] args) {
    long start = System.currentTimeMillis();
    for (int i = 0; i < 100000; i++) {
      try {
        Integer.parseInt(null);
      }
      catch (NumberFormatException x) {
      }
    }
    long end = System.currentTimeMillis();
    System.out.println(end - start);
  }
}

C#

using System;

class ExceptionPerf1 {
  public static void Main(string[] args) {
    int start = Environment.TickCount;
    for (int i = 0; i < 100000; i++) {
      try {
        throw new Exception();
      }
      catch (Exception) {
      }
    }
    int end = Environment.TickCount;
    Console.WriteLine(end - start);
  }
}

Results:

      HotSpot 1.6 x86     .NET 1.1 SP1     .NET 2.0 SP1 x86     Mono 1.9 x86
Java* 111 14743 3590 537
C#   11139 2605 187


*.NET/Mono results with IKVM 0.36

This shows that the situation on the CLR is pretty bad. If you care about exception throwing performance, please complain to Microsoft instead of to me. Although I expect that they'll tell you not to throw so many exceptions. ;-)

On the next episode we'll see that the above microbenchmark is actually a best case scenario for IKVM and we'll see how things can get much worse...

Wednesday, 25 June 2008 12:40:19 (W. Europe Daylight Time, UTC+02:00)  #    Comments [3]
Useful Tool

Andy Malakov wrote an Ant task for ikvmc. It also contains a doclet that can generate an xml mapping file that contains all the parameter names that ikvmc can then attach to the .NET methods (ikvmc already does this for methods with debugging information, but that doesn't work for abstract methods).

Good stuff!

Wednesday, 25 June 2008 09:08:54 (W. Europe Daylight Time, UTC+02:00)  #    Comments [0]
# Friday, 13 June 2008
New Development Snapshot

I've finally updated to a new drop of OpenJDK. If you want to build IKVM from source you'll need the directory resulting from a full build of OpenJDK 6 b10 on Linux AMD64 (although I suppose that if you change the paths in ikvm/openjdk/allsources.lst you'll be able to use an x86 version as well). At some point I'll release a zip file containing just the needed artifacts, but that will take some more time.

IKVM.OpenJDK.ClassLibrary.dll grew in size to 31,657,984 bytes, mostly because the character de-/encoders that live inside charsets.jar are now included as well. I know size is a big issue for many people and as previously discussed I'm still planning to split the class library assembly into several different files.

Changes since previous development snapshot:

  • Integrated OpenJDK 6 b10.
  • Fixed Method.getParameterAnnotations() bug introduced by CallerID support.
  • Changed forked AbstractQueuedSynchronizer to use AtomicReferenceFieldUpdater instead of map.xml based compareAndSet methods to reduce the number of differences between upstream and our version.
  • Fixed three String bugs found by OpenJDK string tests.

WARNING: THIS IS A DEVELOPMENT SNAPSHOT, NOT AN OFFICIAL RELEASE.

Development snapshots are intended for evaluating and keeping track of where the project is going, not for production usage. The binaries have not been extensively tested and are not strong named.

If you want to run this version on Mono, you'll need a Mono version built from recent svn, it does not work on Mono 1.9.

Binaries available here: ikvmbin-0.37.3086.zip

Friday, 13 June 2008 11:58:01 (W. Europe Daylight Time, UTC+02:00)  #    Comments [3]
# Wednesday, 04 June 2008
New Development Snapshot

Changes since previous development snapshot:

  • Code clean up and refactoring.
  • Removed security asserts in JVM.CriticalFailure, because they no longer work now that IKVM.Runtime is security transparent.
  • Implemented CallerID infrastructure.
  • Marked various methods with HasCallerID annotation.
  • Applied awt patch #1979656 by Daniel Wilson.

WARNING: THIS IS A DEVELOPMENT SNAPSHOT, NOT AN OFFICIAL RELEASE.

Development snapshots are intended for evaluating and keeping track of where the project is going, not for production usage. The binaries have not been extensively tested and are not strong named.

If you want to run this version on Mono, you'll need a Mono version built from recent svn, it does not work on Mono 1.9.

Binaries available here: ikvmbin-0.37.3077.zip

Wednesday, 04 June 2008 07:24:21 (W. Europe Daylight Time, UTC+02:00)  #    Comments [0]
# Monday, 02 June 2008
Introducing CallerID Part 3

This is the last part of a three part backward running series on the design, implementation and performance results of the CallerID feature.

How To Pass Information From Caller To Callee

The obvious solution is to use a method parameter, but in this case there is a slight complication: We can't necessarily trust the caller to provide truthful information.

The first scheme I came up with was something like this:

class CallSiteExample {
  private static CallerID __callerID;

  static void method() {
    Class.forName("...", ref __callerID);
  }
}

Here CallerID would be a value type defined in IKVM.Runtime and its content (a Class and ClassLoader reference field) would only be accessible to the runtime and core class library. Inside the callee there would be a check to see if the required field in the CallerID value had been initialized and if not, it would walk up the stack to determine the caller and store the result in the CallerID value.

The obvious downside of this scheme is that it would still require a stack walk the first time a call site does a call. A less obvious downside is that this approach makes it harder to pass the CallerID to another method. This is used in a couple of places where the callee doesn't do the actual work of looking at the caller. Take for exampe java.lang.reflect.Field.get():

@ikvm.internal.HasCallerID
public Object get(Object obj)
    throws IllegalArgumentException, IllegalAccessException
{
    return getFieldAccessor(obj, CallerID.getCallerID()).get(obj);
}

Here the actual access check is in getFieldAccessor (actually, it in turn calls another method to do the security check) and I used the CallerID.getCallerID() intrinsic to pass the implicit callerID parameter explicitly to this other method. Doing this with the value type byref approach would have made this a lot harder.

Nested Types

The design sketched above is actually fairly old, but I had never implemented it due to a nagging feeling that it wasn't quite right. I think my primary concern was that it didn't actually get rid of the stack walk, it only reduced them to at most one per caller. Last week as I was helping someone with a problem that turned out to be caused by a stack walking issue on Mono running on ARM I realized that I should get rid of the stack walk altogether and came up with the trick of using a nested type to create an unforgeable token to represent a class.

Reflection

Another instance of passing around the CallerID is found in reflection. When you call a method via reflection, the immediate caller of that method will, of course, be some VM internal method or Method.invoke() depending on the exact implementation, so the stack walking mechanism that the JDK (and previous IKVM versions) use skips all stack frames related to reflection to get to the real caller. However, with the new scheme, Method.invoke() already gets passed in the CallerID, so it would be a shame not to use this and, of course, it is trivial to pass this value along to the call stub which can then (if required) pass it along to the method being called.

Why the Explicit HasCallerID Annotation?

I could have made ikvmc add the implicit CallerID parameter to every method that calls one of the intrinsics that return the caller, but this has three downsides. The first is that it would have made compiling the core class library slower, because ikvmc would have had to check every method to see if it calls one of these intrinsics (the .NET method signature gets determined way before the method body is processed). The second is that since the additional parameter is, in a sense, part of the public API it should be a conscious decision. The third reasons is that the implicit approach doesn't work with methods that indirectly look at the caller, like the Field.get() example above, so I would have needed to add a mechanism for that anyway.

Limitations

The current implementation doesn't support adding a CallerID parameter to constructors. This is simply the result of the fact that there aren't any constructors that require CallerID that I'm aware of. Another limitation is that the HasCallerID annotation is only recognized for static methods or instance methods on final classes. This means that ClassLoader.getParent() doesn't currently have CallerID support, even though it does want to look at the caller if there is a security manager installed.

Security Considerations

While it's generally not possible to inject a nested type into an arbitrary type, it may be possible to trick another (dynamic) CLR language into creating such a type. However, I think the risk of that is sufficiently low to make it acceptable.

Another risk is that someone may steal a CallerID object from another type and try to impersonate that type. Since .NET 2.0 SP1 it is actually possible for partially trusted code to use reflection to access private fields if you have the RestrictedMemberAccess permission and both assemblies have the same security grant set. However, since this requires .NET reflection (the callerID field isn't visible from the Java reflection APIs) and there already are several ways to bypass Java's security model by directly using .NET APIs this is also a non-issue.

Finally, it is not possible for untrusted Java code to use the HasCallerID annotation, because ikvmc only recognizes the HasCallerID annotation while compiling the core class library and the IKVM runtime only recognizes CallerID methods in the core class library.

Monday, 02 June 2008 08:20:41 (W. Europe Daylight Time, UTC+02:00)  #    Comments [2]
# Sunday, 01 June 2008
Introducing CallerID Part 2

In part 1 we saw the Java source for the ForName benchmark, now let's look at some C# code that is roughly equivalent to what IKVM generates from the Java version:

class ForName  {
  private static readonly __CallerID __callerID = new __CallerID();
  private sealed class __CallerID : ikvm.@internal.CallerID { }

  public static void Main(string[] args) {
    java.lang.Class.forName("java.lang.Object", __callerID);
    long start = java.lang.System.currentTimeMillis();
    for (int i = 0; i < 100000; i++)
      java.lang.Class.forName("java.lang.Object", __callerID);
    long end = java.lang.System.currentTimeMillis();
    java.lang.System.@out.println(end - start);
  }
}

This shows that the compiler passes an extra parameter to the Class.forName() method that carries the identity of the caller's class.

The source for ikvm.internal.CallerID is available in cvs. The class is public and has a protected constructor but has no public methods (they are all internal to the IKVM.OpenJDK.ClassLibrary assembly). The intended usage is shown above, you should extend it with a private class that is nested inside the class whose identity you want to pass to a CallerID requiring API.

The example also demonstrates how you can call these methods from C# if you want to get the best performance, however I recommend using the standard versions of the APIs unless the performance difference is critical to your application.

Above we looked at the caller, now let's look at the callee. Here's the Java source for the Class.forName() method:

@ikvm.internal.HasCallerID
public static Class forName(String className)
            throws ClassNotFoundException {
  return forName0(className, true, ClassLoader.getCallerClassLoader());
}

I added the HasCallerID annotation to signal to ikvmc that it should add the implicit CallerID parameter and ClassLoader.getCallerClassLoader() has been turned into an intrinsic that calls getCallerClassLoader() on the passed in CallerID object instead. Here's the C# equivalent that ikvmc produces for the Class.forName() method:

public static java.lang.Class forName(string className, ikvm.@internal.CallerID callerID) {
  return java.lang.Class.forName0(className, truee, callerID.getCallerClassLoader());
}

[IKVM.Attributes.HideFromJava]
public static java.lang.Class forName(string className) {
  System.Diagnostics.StackFrame caller = new System.Diagnostics.StackFrame(1, false);
  return forName(className, ikvm.@internal.CallerID.create(caller));
}

In part 3 we'll look at the design decisions behind this implementation.

Sunday, 01 June 2008 10:15:18 (W. Europe Daylight Time, UTC+02:00)  #    Comments [0]
# Saturday, 31 May 2008
Introducing CallerID Part 1

In the Java API there are a number of APIs that rely on being able to walk up the call stack to determine certain properties of the immediate caller of the API. The most common scenario is determining the caller's class or class loader. This information is used to implement security checks or to use the right class loader.

Up until now IKVM used the System.Diagnostics.StackFrame .NET API to walk the stack. There are however two major issues with this API. The first issue is that it is unreliable and IKVM jumps through various hoops to make sure that the CLR doesn't inline methods it shouldn't inline or use tail call optimizations it shouldn't use. The second issue is that it is relatively slow.

I finally got around to implementing an alternative scheme that eliminates the usage of System.Diagnostics.StackFrame in most cases. In part 2 I'll describe the implementation, but for now let's just look at some performance numbers.

I've cooked up two microbenchmarks that clearly demonstrate the difference between the current approach and the new approach.

Class.forName()

In this microbenchmark we look at the Class.forName() API. It walks the call stack to determine the class loader of the immediate caller, because that is the class loader that it needs to use to load the class.

class ForName {
  public static void main(String[] args) throws Exception {
    Class.forName("java.lang.Object");
    long start = System.currentTimeMillis();
    for (int i = 0; i < 100000; i++)
      Class.forName("java.lang.Object");
    long end = System.currentTimeMillis();
    System.out.println(end - start);
  }
}

ForName results:

  x86 x64
IKVM 0.37.3063             4350     3959
IKVM 0.37.3073 45 49
JDK 1.6 138 97


(The difference between JDK 1.6 x86 and x64 is mostly due to x86 defaulting to HotSpot Client and x64 to HotSpot Server.)

Method.invoke()

The Method.invoke() API uses the caller class to perform the required access checks when you are calling a non-public method or a method in non-public class.

class Invoke {
  public static void main(String[] args) throws Exception {
    java.lang.reflect.Method m = Invoke.class.getDeclaredMethod("foo");
    long start = System.currentTimeMillis();
    for (int i = 0; i < 100000; i++)
      m.invoke(null);
    long end = System.currentTimeMillis();
    System.out.println(end - start);
  }

  private static void foo() { }
}

Invoke results:

  x86 x64
IKVM 0.37.3063             6083     5572
IKVM 0.37.3073 14 16
JDK 1.6 82 39

To be continued in part 2...

Saturday, 31 May 2008 17:20:40 (W. Europe Daylight Time, UTC+02:00)  #    Comments [2]
# Friday, 23 May 2008
Invokedynamic Proof of Concept Part 2

Rémi Forax inspired me to make my invokedynamic proof of concept a little more real, so I implemented it (still only as a proof of concept, not production quality code) in an IKVM 0.37 fork.

I used the following Java test case:

interface java_dyn_Dynamic
{
  void printSubstring(int startIndex, int length);
  int length();
}

class InvokeDynamic
{
  static
  {
    try
    {
      java.lang.reflect.Method m = InvokeDynamic.class.getDeclaredMethod("bootstrapInvokeDynamic",
                                     java.dyn.CallSite.class, Object.class, Object[].class);
      java.dyn.MethodHandle mh = java.dyn.MethodHandles.unreflect(m);
      java.dyn.Linkage.registerBootstrapMethod(InvokeDynamic.class, mh);
    }
    catch (Exception x)
    {
      x.printStackTrace();
    }
  }

  public static void main(String[] args)
  {
    java_dyn_Dynamic obj = (java_dyn_Dynamic)(Object)"invokedynamic";
    for (int i = 0; i < 3; i++)
    {
      System.out.println("len = " + obj.length());
      obj.printSubstring(3, 2);
    }
  }

  public static void printSubstring(String str, int startIndex, int length)
  {
    System.out.println(str.substring(startIndex, startIndex + length));
  }

  private static Object bootstrapInvokeDynamic(java.dyn.CallSite cs, Object receiver, Object[] args)
    throws Exception
  {
    System.out.println("bootstrapInvokeDynamic");
    if (cs.getStaticContext().getName().equals("length"))
    {
      java.lang.reflect.Method m = String.class.getMethod("length");
      cs.setTarget(java.dyn.MethodHandles.unreflect(m));
      return m.invoke(receiver);
    }
    else
    {
      Class c = cs.getStaticContext().getCallerClass();
      java.lang.reflect.Method m = c.getMethod("printSubstring", String.class, int.class, int.class);
      cs.setTarget(java.dyn.MethodHandles.unreflect(m));
      return m.invoke(null, receiver, args[0], args[1]);
    }
  }
}

After compiling this with javac I used a hex editor to patch the file (changed java_dyn_Dynamic to java/dyn/Dynamic and C0 00 03 to 00 00 00 to remove the checkcast instruction).

Current limitations:

  • java.dyn.MethodType is not implemented.
  • MethodHandles can only be created on methods with a couple of arguments and from the primitive types only int can be used as an argument or return type.
  • Not all of the IKVM specific corner cases are supported (e.g. calling .NET methods or methods on remapped types).
  • The CallSite and MethodHandle implementation objects do not have a proper class (i.e. CallSite.getClass() doesn't work).
  • Only a small subset of the MethodHandle functionality is implemented (e.g. no bound or Java method handles).

None of these limitations pose any interesting challenges, so implementing them does not add much value to this proof of concept.

Files:

Friday, 23 May 2008 15:17:04 (W. Europe Daylight Time, UTC+02:00)  #    Comments [0]
# Wednesday, 21 May 2008
Invokedynamic Proof of Concept

A few days ago the JSR 292 expert group released an early draft review for the invokedynamic instruction.

To investigate how this would work out for IKVM, I cooked up a proof of concept in C#.

class InvokeDynamicPoC
{
  private static InvokeDynamic<object, CallSite, object, object[]> __bootstrapMethod =
    bootstrapInvokeDynamic;
  private static CallSiteImpl<InvokeDynamicVoid<string, int, int>> __site1 =
    new CallSiteImpl<InvokeDynamicVoid<string, int, int>>(
      new StaticContextImpl(typeof(InvokeDynamicPoC), "printSubstring"));

  private static void Main()
  {
    for (int j = 0; j < 2; j++)
    {
      int start = Environment.TickCount;
      for (int i = 0; i < 10/*0000000/**/; i++)
      {
        string obj = "invokedynamic";
        int arg1 = 3;
        int arg2 = 2;
        MethodHandleImpl<InvokeDynamicVoid<string, int, int>> mh = __site1.mh;
        if (mh == null)
        {
          __bootstrapMethod(__site1, obj, new object[] { java.lang.Integer.valueOf(arg1),
                                                         java.lang.Integer.valueOf(arg2) });
        }
        else
        {
          mh.d(obj, arg1, arg2);
        }
      }
      int end = Environment.TickCount;
      Console.WriteLine(end - start);
    }
  }

  private static void printSubstring(string s, int startIndex, int length)
  {
    Console.WriteLine(s.Substring(startIndex, length));
  }

  private static object bootstrapInvokeDynamic(CallSite cs, object receiver, object[] arguments)
  {
    java.lang.Class c = typeof(InvokeDynamicPoC);
    java.lang.reflect.Method m = c.getDeclaredMethod(cs.getStaticContext().getName(),
                                                     typeof(string), typeof(int), typeof(int));
    MethodHandle mh = MethodHandles.unreflect(m);
    cs.setTarget(mh);
    return m.invoke(null, receiver, arguments[0], arguments[1]);
  }
}

The full (compilable and working) source is available here.

Wednesday, 21 May 2008 09:56:49 (W. Europe Daylight Time, UTC+02:00)  #    Comments [0]
New Development Snapshot

More .NET 2.0 work and bug fixing, but the biggest change is that class library initialization has been refactored (building on the property support added in the previous snaphot which allows java.lang.System to lazily initialize the I/O streams). Instead of it being an all or nothing approach (i.e. initialize all core classes at once, like in Java) the initialization dependencies have been mostly removed and each part can now be initialized on demand. This makes the code easier to follow, startup more efficient and removed the need for some ugly hacks to make initialization work correctly.

One thing isn't yet working, if you specify a Java security manager in your app.config it isn't guaranteed that the security manager will be installed immediately (currently it's only installed the first time ClassLoader.getSystemClassLoader() is called.) I'm not sure if it is worth fixing this, because using the Java security manager in this way doesn't seem to make much sense (i.e. if you are running your application as a .NET application, why would you use the Java security manager to restrict what it can do, it won't be able do a good job anyway, since it doesn't know about your non-Java .NET code that directly calls .NET Framework APIs.)

Changes since previous development snapshot:

  • Call suppressFillInStackTrace before instantiating a remapped exception in the remap implementation method.
  • Added assembly location to verbose class cast exception if the assembly fullnames matches but the locations don't.
  • Create the generic delegate type before compiling the rest of the core class library, to allow the core class library to use delegates.
  • Fixed name mangling bug. Dots in nested type names should be mangled, because they shouldn't affect the package name.
  • Include exception message in ClassCastException.
  • Added hack to support instantiating fake enums for types loaded in ReflectionOnly (to support custom attribute annotations that have enum values in ikvmstub).
  • Added -reference option to ikvmstub to load referenced assemblies from a specific location.
  • Refactored class library initialization.
  • Implemented Runtime.availableProcessor() using .NET 2.0 API.
  • Moved most java.lang.System "native" methods to the Java side.
  • Moved java.lang.Thread "native" methods to Java.
  • Implemented support for specifying Thread stack size.
  • Fix deserialization of double arrays.
  • Added more efficient float/double to/from int/long bits converters.
  • Made Double.doubleToRawLongBits/longBitsToDouble and Float.floatToRawIntBits/intBitsToFloat intrinsics.
  • Generalized the support infrastructure for adding compiler intrinsics.
  • Fixed Graphics2D.rotate() to convert rotation angle from radians (Java) to degrees (.NET).
  • Fixed libikvm-native.so build to include reference to gmodule-2.0 library.
  • Fixed build issue on Mono (gmcs implicitly references System.Core.dll and that caused a conflict with our locally defined ExtensionAttribute).
  • Fixed ikvmc not to open the key file for write access.
  • Added workarounds for mcs compiler bug (related to the mutual dependencies of IKVM assemblies).
  • Restructured code to remove (mcs) compiler warnings.

WARNING: THIS IS A DEVELOPMENT SNAPSHOT, NOT AN OFFICIAL RELEASE.

Development snapshots are intended for evaluating and keeping track of where the project is going, not for production usage. The binaries have not been extensively tested and are not strong named.

If you want to run this version on Mono, you'll need a Mono version built from recent svn, it does not work on Mono 1.9.

Binaries available here: ikvmbin-0.37.3063.zip

Wednesday, 21 May 2008 07:16:08 (W. Europe Daylight Time, UTC+02:00)  #    Comments [0]