# Wednesday, 29 August 2007
New Snapshot

One more snapshot before release candidate 1 with a couple of fixes:

  • Windows x64 specific binaries are now included (in the ikvm\bin-x64 directory).
  • Enabled workaround for x64 tail call optimization.
  • Implemented clearing of SoftReferences. They're still not guaranteed to be cleared before an OutOfMemoryError, but the new behavior is hopefully more reasonable than never clearing them.
  • Fixed code generator bug that could cause AbstractMethodError to be thrown when subclassing a .NET type that has an explicit interface method implementation.
  • Integrated IcedTea updates to support PBEwithMD5andDES.

Binaries available here: ikvmbin-openjdk-0.35.2796.zip.

Wednesday, 29 August 2007 08:26:12 (W. Europe Daylight Time, UTC+02:00)  #    Comments [0]
# Tuesday, 28 August 2007
MS07-045 bug

We interrupt our regularly scheduled programming for some Microsoft idiocy. If you have a classic ASP website that instantiates .NET classes via COM interop that suddenly stopped working after installing MS07-045 and you're now getting the dreaded 0x8000FFFF Catastrophic failure aka E_UNEXPECTED, you can fix that by allowing Everyone Read access to HKEY_USERS\S-1-5-20\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Zones or by running MS07-045-patch (.NET 2.0 required) to make the registry permission changes for you (you need admin rights to make the changes or run the executable).

Tuesday, 28 August 2007 11:38:35 (W. Europe Daylight Time, UTC+02:00)  #    Comments [2]
# Friday, 24 August 2007
First OpenJDK Snapshot

Several things conspired to make me realise that it would be a good idea to make an official release based on OpenJDK. While it is technically still a hybrid with GNU Classpath (it uses the AWT / Swing implementation from GNU Classpath 0.95), I don't consider this a big problem due to the fact that AWT support in OpenJDK itself still has holes in it as well (due to the "encumbrances") and the fact that IKVM never officially supported AWT / Swing (and still doesn't). This snapshot has been well tested and the disclaimers no longer apply. Please download it, play with it and report any issues you find (either here in the comments, on the mailing list or to me directly). I will hopefully release the first 0.36 release candidate at the end of next week.

In the past I was never able to give a list of the areas of GNU Classpath that worked or not, because I simply was't familiar enough with the large code base to know which parts were of good quality / compatibility and which weren't. With OpenJDK I can at least say where IKVM diverges from the OpenJDK code. So I've made a list of packages / classes that are not fully implemented or not supported.

com.sun.security.auth.module        Not implemented.
java.applet GNU Classpath implementation. Not supported.
java.awt GNU Classpath implementation. Not supported.
java.io.Console Not implemented.
java.lang.instrument Not implemented.
java.lang.management Not implemented.
java.lang.ref.SoftReference Soft references are never cleared.
java.lang.SecurityManager Deprecated methods not implemented:
classDepth(String), inClass(String), classLoaderDepth(), currentLoadedClass(), currentClassLoader(), inClassLoader()
java.net No IPv6 support implemented.
java.net.ProxySelector Getting the default system proxy for a URL is not implemented.
java.security Not supported.
java.text.Bidi GNU Classpath implementation. Not supported.
java.util.zip Partially based on GNU Classpath implementation.
javax.crypto IcedTea implementation. Not supported.
javax.imageio.plugins.jpeg Not implemented.
javax.management Not implemented.
javax.print Not implemented.
javax.script Not implemented.
javax.security Not supported.
javax.smartcardio Not implemented.
javax.sound Not implemented.
javax.swing GNU Classpath implementation. Not supported.
javax.tools Not implemented.
org.ietfs.jgss Not implemented.
sun.jdbc.odbc Not implemented.
sun.net.www.content.audio Audio content handlers not implemented.
sun.net.www.content.image Image content handlers not implemented.

The entire public API is available, so "Not implemented." for javax.print, for example, means that the API is there but there is no backend to provide the actual printing support. "Not supported." means that the code is there and probably works at least somewhat, but that I'm less likely to fix bugs reported in these areas.

In addition to the issues listed above, the extended charset providers are not included (the ones in charsets.jar in the JRE) and enabling assertions is not implemented.

This snapshot is still based on OpenJDK B13, because the closer to 1.6 the better in my opinion. After the 0.36 release, I will start tracking the OpenJDK development version more closely, but I plan on supporting 0.36 for a relatively long time (even after 0.38 and subsequent IKVM releases).

I've updated the Japi results. The scores are obviously very high now, but there are still some differences. Some differences are due to OpenJDK B13 already containing some new 1.7 APIs, some differences are in the AWT / Swing GNU Classpath code and some are Japi bugs (e.g. the java.util.concurrent differences).

Changes:

  • Renamed IKVM.Hybrid.GNU.Classpath.OpenJDK.dll to IKVM.OpenJDK.ClassLibrary.dll and made OpenJDK build the default.
  • Fixed thread creation to use AccessController.doPrivileged() to get ikvm.apartmentstate system property.
  • Fixed AccessController.getStackAccessControlContext() to use "native" method as marker on the stack for privileged operation (because the native method stub may get inlined away).
  • Added default security policy file to VFS.
  • Integrated OpenJDK java.beans package. Included OpenJDK sun.io package. Included OpenJDK sunw packages (for JDK 1.0 compatibility).
  • Don't create TypeWrapper instances for HideFromJava types.
  • Added rmi skeleton classes.
  • Integrated OpenJDK java.nio package.
  • Changed ikvmres protocol handler to be compatible with both GNU Classpath and OpenJDK url parse exception throwing convention.
  • Switched GNU Classpath AWT/Swing back to version 0.95.
  • Copied GNU Classpath version of java.text.Bidi into openjdk directory.
  • Copied and integrated GNU Classpath's pure Java zip support with OpenJDK zip classes.
  • Added GNU Classpath 0.95 compatible versions of awt\font.cs and awt\toolkit.cs.
  • Refactored system properties initialization.
  • Changed ikvm.exe class library version printing to report both GNU Classpath and OpenJDK versions.
  • Added HideFromJava to AnnotationAttribute type member that can potentially use HideFromJava types.
  • Implemented Thread.dumpThreads() and Thread.getThreads().
  • Added a couple more fake native libraries to VFS.
  • Implemented Thread.WaitUntilLastJniThread() (used by JNI method DestroyJavaVM() to wait for all non-daemon threads to end).
  • Implemented Inet4Address.isReachable().
  • Implemented path canonicalization.
  • Create java.lang.ProcessImpl streams via FileDescriptor instead of going through FileChannelImpl.
  • Added support for StructLayoutAttribute annotations.
  • New FileChannelImpl implementation based on OpenJDK.
  • Added map.xml workaround for java.net.DatagramSocket.receive() bug.
  • Implemented DatagramSocketImpl.peek() and peekData().
  • Don't add KeepAlive to constructors of objects that don't have finalizers and extend cli.System.Object.
  • Implemented sun.net.dns.ResolverConfigurationImpl "native" methods.
  • Added map.xml workaround for OpenJDK java.beans.XMLDecoder bug.
  • Fixed sun.nio.ch.DotNetSelectorImpl to make "infinite" blocking select block for Integer.MAX_VALUE instead of returning right away.
  • Fixed sun.nio.ch.Net.writeImpl() to return IOStatus.UNAVAILABLE if the socket is in non-blocking mode and the write failed because of this.
  • Added workaround for .NET 1.1 Directory.Delete() bug.
  • Updated all Java versions to 1.6.

Binaries available here: ikvmbin-openjdk-0.35.2791.zip.

Friday, 24 August 2007 09:42:45 (W. Europe Daylight Time, UTC+02:00)  #    Comments [1]
# Thursday, 09 August 2007
New Hybrid Snapshot

I did some stabilization work on the previous snapshot and I finally caved in and made floating point handling more compliant (still not fully compliant with the JVM spec, as that would be way too slow).

Changes:

  • Added support for generating access stubs in public interfaces that extend non-public interfaces.
  • Added workarounds for several OpenJDK class initialization order issues.
  • Fixed build process to include the rmi stubs and ties.
  • Renamed sun.misc.Unsafe instance field to theUnsafe, to facilitate sun.corba.Bridge which accesses the field thru reflection.
  • Changed AtomicBoolean.value field from boolean to int to be serialization compatible with JDK.
  • Fixed ArrayTypeWrapper.Finish().
  • Fixed java.lang.reflect.Array.set() to only unbox primitives when the array is a primitive array.
  • Fixed java.lang.reflect.Array.multiNewArray() to finish the array type before using it.
  • Implemented improved floating point compliance (strictfp is now honored and value set conversion is implemented).

Binaries available here: ikvmbin-hybrid-0.35.2777.zip.

Thursday, 09 August 2007 10:16:51 (W. Europe Daylight Time, UTC+02:00)  #    Comments [0]
# Tuesday, 07 August 2007
Floating Point "Redundant" Cast Performance on the CLR

Let's start out with a simple micro benchmark:

using System;
using System.Threading;
class Program
{
public static void Main()
{

int start = Environment.TickCount;
double[] d = new double[1000];
for (int i = 0; i < 1000000; i++)
{
for (int j = 0; j < d.Length; j++)
{
d[j] = (double)(3.0 * d[j]);
}
}
int end = Environment.TickCount;
Console.WriteLine(end - start);
}
}

On my system this takes about 7 seconds when run in optimized mode (i.e. not in the debugger).

Here's the optimized x86 code generated by the 2.0 CLR JIT for the body of the inner loop:

fld   qword ptr [ecx+edx*8+8]      ; d[j]
fmul  dword ptr ds:[007B1230h]     ; * 3.0 
fstp  qword ptr [esp]              ; (double) 
fld   qword ptr [esp]              ; (double) 
fstp  qword ptr [ecx+edx*8+8]      ; d[j] = 

There first thing that jumps out is that the double cast takes two x87 instructions, a store and a load. Part of the reason the cast is expensive is because the value has to leave the FPU and go to main memory and back into the FPU. In this particular case it turns out to be very expensive, because esp happens to be not 8 byte aligned.

Making a seemingly unrelated change can make the micro benchmark much faster, just adding the following two lines at the top of the Main method will make the loop run in about 2.3 seconds on my system:

    double dv = 0.0;
Interlocked.CompareExchange(ref dv, dv, dv);

The reason for this performance improvement becomes clear when we look at the method prologue in the new situation:

push  ebp 
mov   ebp,esp 
and   esp,0FFFFFFF8h 
push  edi 
push  esi 
push  ebx 
sub   esp,14h

This results in an 8 byte aligned esp pointer. As a result the fstp/fld instructions will run much faster. It looks like a "bug" in the JIT that it doesn't align the stack in the first scenario.

Of course, the much more obvious question is: Why does the cast generate code at all, isn't a double already a double?

Before answering this question, let's first look at another minor change to the micro benchmark. Let's remove the Interlocked.CompareExchange() again and change the inner loop body to the following:

    double v = 3.0 * d[j];
d[j] = (double)v;

With this change, the loop now takes just 1 second on my system. When we look at the x86 code generated by the JIT, it becomes obvious why:

fld   qword ptr [ecx+edx*8+8] 
fmul  dword ptr ds:[002A1170h] 
fstp  qword ptr [ecx+edx*8+8]

The redundant fstp/fld instructions are gone.

Back to the question of why the cast isn't always optimized away. The reason for this lies in the fact that the x87 FPU internally uses an extended 80 bit representation for floating point numbers. When you explicitly cast to a double, the ECMA CLI specification requires that this results in a conversion from the internal representation into the IEEE 64 bit representation. Of course, in this scenario we're already storing the value in memory, so this necessarily implies a conversion to the 64 bit representation, making the extra fstp/fld unnecessary.

Finally, in x64 mode all three variations of the benchmark take 1 second on my system. This is because the x64 CLR JIT uses SSE instructions that internally work on the IEEE 64 bit representation of doubles, so the cast is optimized away in all situations here.

For completeness, here's the code generated by the x64 JIT for the inner loop body:

movsd  xmm0,mmword ptr [rcx] 
mulsd  xmm0,mmword ptr [000000C0h] 
movsd  mmword ptr [rcx],xmm0 
Tuesday, 07 August 2007 15:02:08 (W. Europe Daylight Time, UTC+02:00)  #    Comments [2]
# Monday, 06 August 2007
IKVM 0.34 Update

I made another 0.34 update, since 0.36 is probably still a ways off.

Changes:

  • Fixed handling of magic “assembly” type for assembly attribute annotations (bug #1721688).
  • LocalVariableTable robustness fix (bug #1765952).
  • Fixed handling of public interfaces extending non-public interfaces in ikvmc.
  • Fixed parameter annotations on redirected contructors.
  • Fixed casting ghost interface arrays (bug #1757889).
  • Fixed JNI NewObject method.
  • Fix to make sure all implemented interface methods on .NET types are public (so that ikvmstub generates jars that javac is happy with).

Files are available here: ikvm-0.34.0.4.zip (source + binaries) and ikvmbin-0.34.0.4.zip (binaries).

Update: I forgot to update the AWT toolkit property's assembly version. Fixed in current zips. Thanks to Ted O'Conner for pointing this out.

Monday, 06 August 2007 10:41:11 (W. Europe Daylight Time, UTC+02:00)  #    Comments [1]
# Thursday, 02 August 2007
What about AWT / Swing Support?

In the comments to the previous entry Martin asked:

Would you support AWT / Swing as the Sun Version?

I've always said that AWT / Swing are not a priority for me and that won't change. Having said that, my current idea is to have two AWT back-ends, the default one similar to the current situation, i.e. a .NET Windows Forms based partial implementation. The second (optional) one would be the OpenJDK based implementation, using the OpenJDK native libraries. However, as usual, this is all subject to change.

Andrew asked:

Okay, just wanted to clarify what you mean by 'integrating'. My understanding is you actually replace the GNU Classpath code with code copied from OpenJDK and then try and implement the necessary VM wotsits -- is that correct? If that is the case, presumably the end goal is to complete replace all the Classpath code. At the moment, that'd be a real shame because it would make IKVM more broken as lots of stuff like AWT/Swing is broken on OpenJDK.

That's not really true on IKVM. IKVM has never supported GNU Classpath's AWT/Swing implementation (it includes only the GNU Classpath implementation of the public API, the peer implementations are not used).

In case you're wondering why IKVM doesn't support the GNU Classpath peers, that's because the GNU Classpath peers don't support Windows and also because IKVM is built on top of the CLI and (almost all) the IKVM binaries are OS and CPU architecture independent, using native code is not compatible with that feature.

Thursday, 02 August 2007 09:18:13 (W. Europe Daylight Time, UTC+02:00)  #    Comments [0]
# Wednesday, 01 August 2007
New Hybrid Snapshot

Major code bloat. I've now integrated the bulk of the OpenJDK code that isn't awt or swing. As a result the IKVM.Hybrid.GNU.Classpath.OpenJDK.dll assembly size has grown to about 26 MB. API coverage compared with JDK 1.6 is now at more than 98%. Note that doesn't mean that everything will work, because some back-end implementations are stubbed out or not included.

Disclaimers apply. I haven't done a full test pass on this build.

Changes:

  • OpenJDK: Integrated javax.management package (and sub packages).
  • OpenJDK: Integrated java.lang.management package (only a stub back-end implementation though).
  • OpenJDK: Integrated javax.imageio package (excluding the jpeg support, because OpenJDK uses native code for that).
  • OpenJDK: Integrated javax.activation, javax.annotation, javax.jws, javax.lang.model, javax.tools, javax.xml.*, org.jcp.xml.dsig.internal, org.relaxng.datatype, org.w3c.dom.*, org.xml.sax.* packages.
  • OpenJDK: Integrated javax.sql.* packages.
  • OpenJDK: Integrated javax.accessibility, javax.transaction, javax.activity packages.
  • OpenJDK: Integrated javax.print.* packages (no back-end implementation and ServiceUI is stubbed.)
  • OpenJDK: Integrated org.omg.*, javax.rmi.*, javax.sound.*, org.ietfs.jgss packages.
  • Fixed JNI NewObject method to actually create an object of the requested class, instead of the class of the constructor.
  • Added method name clash handling for AOT access stub methods.

Binaries available here: ikvmbin-hybrid-0.35.2769.zip.

Wednesday, 01 August 2007 10:16:12 (W. Europe Daylight Time, UTC+02:00)  #    Comments [2]