# Tuesday, 25 January 2011
New Development Snapshot

A new snapshot with OpenJDK 6 b21 integrated. If you want to build from cvs, from now on you'll need the OpenJDK 6 b21 sources (available in the zip linked below).

Changes:

  • Integrated OpenJDK 6 b21.
  • IKVM.Reflection: Mark modules as executable when running on Mono.

Binaries available here: ikvmbin-0.45.4042.zip

OpenJDK 6 b21 stripped sources: openjdk6-b21-stripped.zip

Tuesday, 25 January 2011 06:07:07 (W. Europe Standard Time, UTC+01:00)  #    Comments [0]
# Monday, 24 January 2011
New Development Snapshot

More IKVM.Reflection fixes to support mcs. Many thanks to Marek for his work.

OpenJDK 6 b21 has been released, so after this snapshot that needs to be integrated and we start preparing for the 0.46 release.

Changes:

  • Several AWT fixes.
  • Image improvements.
  • Added ikvm.runtime.Startup.addBootClassPathAssemby() API.
  • Added -Xreference: option to ikvm.
  • Fix scope id in IPv6 server socket accepted connections.
  • Added support for loading resources from assemblies loaded in the LoadFrom context.
  • Treat unrecognized ikvmc options as errors, instead of warnings.
  • Added ikvm.internal.NotYetImplementedError and throw that instread of sun.reflect.generics.reflectiveObjects.NotImplementedException.
  • Fixed bug that caused reflecting on a field of an unfinished type to throw an exception.
  • IKVM.Reflection: Fix for big endian systems. Thanks to Marek Safar for reporting this.
  • IKVM.Reflection: Add support for NETCF in rendering pseudo DllImportAttribute (i.e. skip fields that don't exist).
  • IKVM.Reflection: Changed __ReadTypeName() to __TryReadTypeName() because it should fail when the type is a nested type (because the name of a nested type cannot be expressed by namespace + name).
  • IKVM.Reflection: Type.Namespace property should not returned escaped string.
  • IKVM.Reflection: Added Type.__Name and Type.__Namespace properties to allow the real (from the ECMA CLI point of view) namespace and names of types to be queried (for TypeDef and TypeBuilder only).
  • IKVM.Reflection: Fixed a bunch of type name escaping bugs.
  • IKVM.Reflection: Added support for nested types that use a namespace.
  • IKVM.Reflection: Type.Name/Namespace/FullName fixes to make everything more compatible (including bugs) with .NET reflection.
  • IKVM.Reflection: Added ModuleBuider.__DefineType() and TypeBuilder.__DefineNestedType() APIs.
  • IKVM.Reflection: Prevent external subclassing. It's not part of the design to support that, now it is also enforced.
  • IKVM.Reflection: Fixed copy/paste bug. A TypeRef pointing to ModuleRef should resolve the type in that module, not the assembly.
  • IKVM.Reflection: Fixed Type.GetNestedType() and be more compatible with .NET reflection (i.e. ignore the namespace).
  • IKVM.Reflection: Added Universe.CreateMissingAssembly() to create an assembly that automatically resolves any type that it is supposed to contain.
  • IKVM.Reflection: Added Type.__IsMissing and Type.__ContainsMissingType properties to detect missing types.
  • IKVM.Reflection: Patch by Marek Safar to implement framework unification for managed implementation of Universe.CompareAssemblyIdentity().
  • IKVM.Reflection: Improved partial trust support.
  • IKVM.Reflection: Added support for saving to a stream instead of a file.
  • IKVM.Reflection: Fixed type resolution to match namespace and name separately, like Mono and the CLR do.
  • IKVM.Reflection: Added Universe.EnableMissingTypeResolution() to enable missing type resolution in all assemblies.
  • IKVM.Reflection: Various fixes to improve support for building mscorlib.

Binaries available here: ikvmbin-0.45.4041.zip

Monday, 24 January 2011 07:08:30 (W. Europe Standard Time, UTC+01:00)  #    Comments [8]
# Monday, 27 December 2010
New Development Snapshot

Several IKVM bug fixes as well as more IKVM.Reflection bug fixes and a couple of new APIs for issues found by Marek during his Mono C# compiler work.

I've also modified the build process to generate a stub jar for the IKVM.NET specific Java APIs, to remove the need to run ikvmstub on IKVM.OpenJDK.Core.dll. The stubs are now available in the binaries zip file (ikvm/lib/ikvm-api.jar).

  • Fixed ikvmstub to not mark abstract methods as native.
  • Changed registry access (for java.util.prefs) on Windows to be more compatible with JDK and UAC aware.
  • Added support for encoding incorrect annotation values and reporting the exception back when the annotation is queried.
  • Fixed ikvmstub encoding of boolean annotation method defaults.
  • System.mapLibraryName() should throw NPE for null arg.
  • Ported parts of fdlibm to C# to use for StrictMath methods tan, cbrt, floor, pow, hypot, expm1 and log1p.
  • Several awt fixes.
  • Added ikvmstub -out: option and improved usage message.
  • Added ikvmstub -namespace: option to only process types in the specified namespace(s).
  • Generate lib/ikvm-api.jar to expose the ikvm API more easily to java code (by shipping this jar as part of ikvmbin.zip).
  • Fix for NullReferenceException in ClassLoaderWrapper.LoadGenericClass() if type parameter type cannot be loaded.
  • IKVM.Reflection: Delay creation of tokens for base type and interfaces until CreateType, to avoid problems when a non yet completely defined type is used as a base type or interface.
  • IKVM.Reflection: Don't clear properties and events fields during CreateType.
  • IKVM.Reflection: Call CreateType on TypeBuilder created by DefineInitializedData.
  • IKVM.Reflection: Emit Param table records is correct order.
  • IKVM.Reflection: HashAlgId in assembly manifest record turns out to be useless (SHA1 is always used).
  • IKVM.Reflection: Custom attributes applied to GenericTypeParameterBuilder were attached to the type token, instead of the type parameter token.
  • IKVM.Reflection: Added support for reading decimal parameter default values with ParamterInfo.RawDefaultValue.
  • IKVM.Reflection: Added support for emitting assemblies with non-existing cultures.
  • IKVM.Reflection: Fixed several ILGenerator bugs when __CleverExceptionBlockAssistance is used.
  • IKVM.Reflection: Removed NotImplementedException for unsorted GenericParam table, because we don't really care.
  • IKVM.Reflection: Exception block end label should be marked regardless of exception assistance mode.
  • IKVM.Reflection: The end label of an exception block should always be marked, because you can also backward branch to it.
  • IKVM.Reflection: Don't emit unnecessary leave instructions in "clever" mode.
  • IKVM.Reflection: Added ModuleBuilder.__AddAssemblyReference() API to explicitly add assembly references. This can be used in conjunction with AssemblyBuilder.__AddModule() to add the assemblies referenced by the module to the assembly manifest module. It's not clear to me whether this is required, but Microsoft does it and Assembly.GetReferencedAssemblies() only returns the assemblies referenced from the manifest module.
  • IKVM.Reflection: Added Module.__GetReferencedAssemblies() API.
  • IKVM.Reflection: Sort PropertyMap table. Not required by the spec, but .NET does it and Mono requires it.
  • IKVM.Reflection: Made CustomAttributeData more lazy (when all custom attributes are queried, regardless of type).
  • IKVM.Reflection: Added CustomAttributeData.__ReadTypeName() to get the type name without resolving it.
  • IKVM.Reflection: Fixed copy/paste bug in AssemblyBuilder.GetTypeImpl(). The modules list was iterated twice instead of looking through both modules and addedModules.
  • IKVM.Reflection: AssemblyResolve event should fire before resolving to AssemblyBuilder.
  • IKVM.Reflection: Don't create duplicate ClassLayout table records when using the DefineType overload that specifies the size and also applying a StructLayoutAttribute.

Binaries available here: ikvmbin-0.45.4013.zip

Monday, 27 December 2010 06:53:23 (W. Europe Standard Time, UTC+01:00)  #    Comments [0]
# Wednesday, 01 December 2010
New Development Snapshot

Several bug fixes. I also figured out a way to workaround an annoying .NET 4 x64 JIT bug without any significant performance impact. Marek Safar has started on porting gmcs to IKVM.Reflection and that triggered some IKVM.Reflection bug fixes and improvements.

  • Fixed regression in Throwable.printStackTrace(). Exception cause in stack trace should use Throwable.toString() not System.Exception.ToString().
  • Add support for serializing .NET exceptions in Java. We don't serialize the actual object, but a placeholder instead, to avoid having to implement full .NET serialization interop.
  • File.lastModified() should return 0 for non-existing files. Fix for #3111432. Thanks to Stephen White for the patch.
  • Added workaround for .NET 4 x64 JIT bug.
  • Optimized thread creation.
  • Optimized ProtectionDomains created for .NET assemblies to be more lazy.
  • Made assembly Java class loader construction lazy.
  • Removed trace messages that don't add much value but do cause the tracer to needlessly read configuration data early in initialization.
  • Fixed AccessController.doPrivileged() bug that caused context to be ignored.
  • Removed implementation specific methods from top of stack trace for threads started from Java.
  • UnauthorizedAccessException caused by already existing file or directory should cause createFileExclusively() to return false instead of throwing an exception.
  • File.canWrite() should always return true for directories (on Windows).
  • Fixed regression. Don't call GetIPv6Properties() if IPv6 isn't available.
  • AWT fixes.
  • IKVM.Reflection: Added IKVM.Reflection.Missing type. Thanks to Marek Safar for pointing this out.
  • IKVM.Reflection: Fixed ParameterInfo.RawDefaultValue to return Missing.Value if the parameter is optional, but doesn't have a default and to return null, if the parameter isn't optional (and doesn't have a default).
  • IKVM.Reflection: Added AssemblyBuilder.__DefineIconResource() API.
  • Added -win32icon:<file> option to ikvmc.
  • IKVM.Reflection: Added ModuleBuilder.__Save() to support -target:module option better.
  • Changed ikvmc to use new ModuleBuilder.__Save() instead of workaround of deleting the manifest module after saving the assembly.
  • Added support for assembly custom attributes in combination with -target:module.
  • IKVM.Reflection: Added AssemblyBuilder.__AddModule() to allow pre-existing modules to be linked in.
  • IKVM.Reflection: Fixed RawModule.GetReferencedAssemblies() to work for non-manifest modules as well.
  • IKVM.Reflection: Added API to query placeholder assembly custom attributes in a module.
  • Fixed Thread.stop() race condition.
  • Implemented java.awt.Font.createFont().
  • Fixed .NET 4 security attribute regressions.

Binaries available here: ikvmbin-0.45.3987.zip

Wednesday, 01 December 2010 09:46:41 (W. Europe Standard Time, UTC+01:00)  #    Comments [0]
# Sunday, 21 November 2010
How to Detect if a Method is Overridden

Suppose you want to know if (the class of) a particular object overrides a virtual method. For an example of this see OpenJDK's Thread.isCCLOverriden() (line 1573).

In Java the obvious way to do this would be to use reflection. On the CLR there is another way that is both more accurate1 and more efficient.

Here's the MSIL method from IKVM's java.lang.Thread.isCCLOverridden() implementation:

.method private hidebysig static bool isCCLOverridden(class java.lang.Thread A_0) cil managed
{
  ldftn      instance class java.lang.ClassLoader java.lang.Thread::getContextClassLoader()
  ldarg.0
  ldvirtftn  instance class java.lang.ClassLoader java.lang.Thread::getContextClassLoader()
  ceq
  ldftn      instance void java.lang.Thread::setContextClassLoader(class java.lang.ClassLoader)
  ldarg.0
  ldvirtftn  instance void java.lang.Thread::setContextClassLoader(class java.lang.ClassLoader)
  ceq
  and
  ldc.i4.0
  ceq
  ret
}

Instead of running a zillion instructions and accessing a lot of cold data for reflection, this simply leverages the information the JIT already has about virtual methods.

Here's the x86 code this turns into:

  push        ebp 
  mov         ebp,esp 
  push        esi 
  push        ebx 
  mov         esi,ecx 
  push        258F58h 
  mov         ecx,esi 
  mov         edx,259240h 
  call        JIT_VirtualFunctionPointer
  mov         edx,25DCA0h 
  cmp         eax,edx 
  sete        bl 
  movzx       ebx,bl 
  push        2591A0h 
  mov         ecx,esi 
  mov         edx,259240h 
  call        JIT_VirtualFunctionPointer
  mov         edx,25DCB0h 
  cmp         eax,edx 
  sete        al 
  movzx       eax,al 
  and         ebx,eax 
  sete        al 
  movzx       eax,al 
  pop         ebx 
  pop         esi 
  pop         ebp 
  ret

To get an idea what JIT_VirtualFunctionPointer does, take a look at the Shared Source CLI.

On the CLR, in the common case it only executes about 40 instructions.

The downside to this method is that it only works if you have an object instance. Although you could use FormatterServices.GetUninitializedObject() to create an instance.

Why Optimize This?

In the OpenJDK code, isCCLOverridden() is only called if a SecurityManager is installed, but I wanted to use it always to avoid calling getContextClassLoader() during thread construction, because that would trigger the system class loader to be constructed and I my long term goal for IKVM is to make initialization more lazy to reduce the huge startup overhead.


1This method is more accurate (on the CLR) because you don't need to worry about non-virtual methods or virtual methods that are new (and hence don't override the base class virtual method) or explicit overrides that override a method but have a different name.

Update: See this article for a caveat.

Sunday, 21 November 2010 11:36:21 (W. Europe Standard Time, UTC+01:00)  #    Comments [2]
# Wednesday, 17 November 2010
New Development Snapshot

Time for a new snapshot.

Changes:

  • Added support for using MethodImplAttribute as a Java annotation.
  • Fixed class name resolution for xml remapping instructions.
  • Many AWT fixes.
  • Fixed xml remapper to interpret empty sig attribute on call as zero length argument list.
  • Added memory barrier after volatile stores.
  • Added optimization to remove redundant memory barriers.
  • Changed default assembly class loader instantiation to avoid security manager check.
  • Fixed ikvm.exe -D property name parsing to accept properties with equals sign in the name.
  • Fixed JdbcOdbc provider to use Invariant Culture for Decimal/BigDecimal conversion.
  • Fixed column type mapping bugs in JdbcOdbcResultSetMetaData.
  • Fixed resource (and virtual class file) loading regression that caused loading resources from assemblies with an underscore in the name to fail.

Binaries available here: ikvmbin-0.45.3973.zip

Wednesday, 17 November 2010 09:08:33 (W. Europe Standard Time, UTC+01:00)  #    Comments [2]
# Thursday, 11 November 2010
IKVM.NET 0.36 Update 3

On request of an IKVM.NET user still stuck on .NET 1.1 the memory model fix has been backported to 0.36.

Changes:

  • Changed version to 0.36.0.14.
  • Emit a memory barrier after volatile stores.

Binaries available here: ikvmbin-0.36.0.14.zip
Sources (+ binaries): ikvm-0.36.0.14.zip

Thursday, 11 November 2010 07:09:06 (W. Europe Standard Time, UTC+01:00)  #    Comments [0]
# Monday, 01 November 2010
C# Async CTP

Last week at the PDC Microsoft released a CTP of the upcoming C# (and VB.NET) async feature. When you install the Async CTP and run the code below with the current IKVM.NET release you'll see something like this:

7
Downloaded 64803 bytes
13

This means that after the async operation completed the method resumed on another thread. However, if you get the current IKVM.NET code from cvs, you'll see:

7
Downloaded 64803 bytes
7

Via the magic of SynchronizationContext the method now resumes on the AWT event thread, if the await happened on that thread.

Here's the demo:

using System;
using System.Threading;
using System.Net;
using java.awt;
using java.awt.@event;

class AsyncDemo : Frame, ActionListener
{
  AsyncDemo()
  {
    var button = new Button("Click Me");
    button.addActionListener(this);
    add(button);
    pack();
    setVisible(true);
  }

  public async void actionPerformed(ActionEvent ae)
  {
    Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
    var wc = new WebClient();
    var data = await wc.DownloadDataTaskAsync("http://weblog.ikvm.net/");
    Console.WriteLine("Downloaded {0} bytes", data.Length);
    Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
  }

  static void Main()
  {
    new AsyncDemo();
  }
}

Monday, 01 November 2010 15:57:38 (W. Europe Standard Time, UTC+01:00)  #    Comments [2]
# Tuesday, 26 October 2010
How to Hack Your Own JIT Intrinsic

Yesterday I wrote about Thread.MemoryBarrier() and some of its performance characteristics. I wanted to do some benchmarking to see whether mfence really is faster than a locked memory operation, but instead of writing a microbenchmark (which I had already done) I wanted to run code that was a little bit more "real". So I came with a hack to allow mfence to be used in managed code. Please note that this is a hack and not something you should use outside of an experimental context. The code is available here.

The code includes a microbenchmark, but not the "real" benchmark (based on LinkedBlockingQueue) that I used.

I also tested a Pentium 4 class machine and a Core i7. On the Pentium 4 and my Core 2 Duo the mfence wins out signicantly, but on the Core i7 mfence is significantly slower, oddly enough.

How the Hack Works

The MemoryBarrierHack.cs file contains two classes, __Hack__DoNotUse and Program. The __Hack__DoNotUse class contains the MemoryBarrier method and a static constructor to patch the MemoryBarrier method. The MemoryBarrier method is patched to patch the call site of its caller and replace the call with an mfence and a mov al,imm8 as a filler. This means that when you want a memory barrier, you simply call the static method and when that call executes, the first time it will act as a memory barrier (because of the locked memory operation) and also patch the call so that the next time it will be an mfence instruction.

I built a modified IKVM runtime that uses this trick and used that to benchmark the LinkedBlockingQueue. On my system it showed a performance improvement of about 7% with mfence versus .NET 4.0's MemoryBarrier instrinsic.

Tuesday, 26 October 2010 11:50:03 (W. Europe Daylight Time, UTC+02:00)  #    Comments [2]
# Monday, 25 October 2010
Memory Model Fix

In last week's 0.44.0.6 update I fixed a memory model bug. In retrospect it was a pretty dumb bug, but in my defence, even the easy parts of memory models are still pretty subtle and when I started IKVM.NET both the Java and CLR memory models were not very well documented.

First of all, I should thank Staffan Ulfberg for filing an exceptionally high quality bug report.

Finding the Problem

After spending some quality time in Windbg looking at the crash dump and with the java.util.concurrent sources, I was eventually able to reproduce the problem on a single CPU quad core Xeon (but not on my Core 2 laptop). After it was reproducable I started pruning the repro to find the troublespot and eventually found this method:

java.util.concurrent.AbstractQueuedSynchronizer.java
public final boolean release(int arg) {
  if (tryRelease(arg)) {
    Node h = head;
    if (h != null && h.waitStatus != 0)
      unparkSuccessor(h);
    return true;
  }
  return false;
}

My pruned version looked like this:

public final void release() {
  state = 0;
  Node h = head;
  if (h != null && h.waitStatus != 0)
    unparkSuccessor(h);
}

Both state and head are volatile fields. With this modified version the hang usually happened with in a second and I had also added a timeout to park so the problem could be seen repeatedly without restarting the process. After seeing this and thinking about it for a bit, I realized that if the read of head could be reordered with the write of state, that could cause the observed hang. To test that theory, I used Windbg to patch the running code to add an sfence instruction after the state = 0 store. That did indeed make the problem go away and replacing the sfence with three nop instructions made it reappear.

Time to read up on the memory models.

Java Memory Model

For the Java memory model, the JSR 133 Cookbook is a good place to start. It has a nice table that confirms that the reordering isn't allowed in Java:

Can Reorder 2nd operation
1st operation Normal Load
Normal Store
Volatile Load
MonitorEnter
Volatile Store
MonitorExit
Normal Load
Normal Store


No
Volatile Load
MonitorEnter
No No No
Volatile store
MonitorExit

No No

The yellow box clearly says No :-)

CLR Memory Model

The CLR memory model is summarized nicely in this blog post by Joe Duffy and he explicitly calls out: "With this model, the only true case where you’d truly need the strength of a full-barrier provided by Rule 4 is to prevent reordering in the case where a store is followed by a volatile load. Without the barrier, the instructions may reorder."

So that confirmed that I did indeed need to emit a memory barrier between a volatile store and a subsequent load. I modified the bytecode compiler to emit a call to Thread.MemoryBarrier() after every volatile store.

CLI Memory Model

I explicitly chose not to support the CLI memory model, because it is not very well specified and is impossible to test against. I don't know what memory model Mono implements, but I did find that Thread.MemoryBarrier() was not implemented for x86.

Thread.MemoryBarrier() Implementation Issues

I picked Thread.MemoryBarrier() for 0.44 because it was the easiest and lowest risk fix. An alternative would be to use Interlocked.Exchange() to write to a volatile field. On .NET 2.0, Thread.MemoryBarrier() is implemented as a native method that does more work than just the memory barrier, it also polls for GC and acts as a safe point. On .NET 4.0 it has been turned into a JIT intrinsic and the overhead is lower. Unfortunately, on my system, the .NET 4.0 memory barrier is still significantly slower than the HotSpot memory barrier (which uses mfence), but apparently the trade-off between mfence and a locked instruction is not trivial.

Optimization

In the 0.45 code (where there is now an MSIL optimization step), I added an optimization to remove redundant memory barriers. If multiple volatile stores are done in succession, only the last one will get a memory barrier.

Testing

Finally, here's a small test that reproduces the problem (on my Core 2 laptop):

class Rendezvous extends java.util.concurrent.atomic.AtomicInteger {
  private static final int PARTIES = 2;

  public final void await() {
    if (incrementAndGet() == PARTIES) {
      compareAndSet(PARTIES, 0);
      return;
    }
    while (get() != 0) ;
  }
}

public class test {
  static volatile int p1;
  static volatile int p2;
  static volatile int r1;
  static volatile int r2;
  static final Rendezvous rv1 = new Rendezvous();
  static final Rendezvous rv2 = new Rendezvous();

  public static void main(String[] args) {
    Thread t = new Thread() {
      public void run() {
        for (; ; ) {
          p1 = 0;
          rv1.await();

          p1 = 1;
          r1 = p2;

          rv2.await();
        }
      }
    };
    t.start();

    for (int i = 0; i < 1000000; i++) {
      p2 = 0;
      rv1.await();

      p2 = 1;
      r2 = p1;

      rv2.await();

      if (r1 == 0 && r2 == 0)
        System.out.println("Oops! i = " + i);
    }

    t.stop();
  }
}

Monday, 25 October 2010 08:58:57 (W. Europe Daylight Time, UTC+02:00)  #    Comments [1]