# Thursday, 05 September 2002
No Title

Generics

Yesterday, Microsoft Research released a beta version of Gyro, which is their implementation of generics for Rotor.

I downloaded it this morning and played with it, and I must say, it's great! This is going to be the killer feature for .NET (once the commercial platform gets it). Unlike the platform that starts with a J, this is actually done right. The Java generics proposal that was floated for 1.4 and then withdrawn was an ugly (nay, disgusting) hack. Gyro is beautiful, I have no other word for it.

I can't wait for this to appear in the commercial platform!

Thursday, 05 September 2002 18:43:29 (W. Europe Daylight Time, UTC+02:00)  #    Comments [3]
# Tuesday, 03 September 2002
No Title

I did some work to get my database server app working. I implemented rudimentary socket support and some very lame AWT stuff. My database server now runs (including its lame GUI). Also fixed a few bugs (among others, support for long & double volatiles, thanks to Richard Birkby for pointing this out to me).

Since I built the AWT in C#, linking it against classpath.dll, building is becoming a little more tricky. Hopefully I'll be able to make the build process more straight forward in the future, but for the time being you'll have to suffer ;-)

Updated the binaries and source snaphots.

Tuesday, 03 September 2002 19:19:30 (W. Europe Daylight Time, UTC+02:00)  #    Comments [0]
# Friday, 30 August 2002
No Title

Jamie commented:

I've just tried to run 'vjslib.dll' (the J# Java packages) through netexp. I'm getting a NotImplementedException: System.Boolean on line 355.

I forgot to implement support for literal boolean fields.

I was wondering if this library could be used in place of the 'classpath.dll' one. In particular I was looking to see if the AWT would work.

It's unlikely this will work (without major effort).

Does your classloader look for classes in the 'classpath.dll' library before or after ones on the classpath? Can this behaviour be easily changed?

It looks in classpath.dll before it tries to load from the classpath, but at some point this will change (when I'm going to support multiple classloaders).

Friday, 30 August 2002 16:36:46 (W. Europe Daylight Time, UTC+02:00)  #    Comments [0]
# Wednesday, 28 August 2002
No Title

Added support for delegates to netexp and the VM. This enabled me to rewrite the thread startup in Java, here is a fragment from Thread.start():

ThreadStart starter = new ThreadStart(
  new ThreadStart.Method() {
    public void Invoke() {
      try {
        try {
          Thread.SetData(localSlot, Thread.this);
          setPriorityNative();
          run();
        } catch(Throwable t) {
          if(group != null) {
            group.uncaughtException(Thread.this, t);
          }
        }
      } finally {
        if(group != null) {
          group.removeThread(Thread.this);
        }
      }
  });
nativeThread = new Thread(starter);
nativeThread.Start();

The delegate appears to Java code as regular class with an inner interface named Method. The inner interface has one method named Invoke, with the signature of the delegate, and the delegate class appears to have a constructor taking a reference to the inner interface. What's nice about this scheme is that on the VM side, it is really trivial to support this. The only thing that is done, is whenever a delegate is constructed, two CIL instructions (dup & ldvirtftn) get inserted into the code stream. The Java bytecode:

  new java/lang/Thread$1 
  dup 
  aload_0 
  invokespecial Thread$1/<init>(Ljava/lang/Thread;)V> 
  invokespecial ThreadStart/<init>(LThreadStart$Method;)V>

Is compiled into:

  ldarg.0
  newobj  void Thread$1::.ctor(class java.lang.Thread)
  dup
  ldvirtftn  void ThreadStart$Method::Invoke()
  newobj  void ThreadStart::.ctor(object, native int)

So the delegate is constructed referencing the object implementing the interface.

(disclaimer: code fragments have been editted for readability, some assembly may be required)

Updated the binaries and source snaphots.

Wednesday, 28 August 2002 16:57:52 (W. Europe Daylight Time, UTC+02:00)  #    Comments [1]
# Sunday, 25 August 2002
No Title

Stuart commented:

Seems like building got a little more complicated (I don't seem to pick up your build options from your .sln file, and while before it was just a matter of turning on the unsafe option, it seems I need to do more than that now, like add some references, and I can't figure out which ones). I don't have enough time to do any serious investigation.

That might be because of zlib.dll reference. I moved that into the project directory, so the relative path should be correct now.

I'd love to play with ikvmc and netexp, though - any chance of including them in ikvmbin.zip?

Done.

Updated the binaries and source snaphots.

Sunday, 25 August 2002 11:53:49 (W. Europe Daylight Time, UTC+02:00)  #    Comments [0]
# Thursday, 22 August 2002
No Title

Stuart commented:

You can also optimize the test away (in the other direction) if it's known at compile time that the object *is* a string. Or is that unnecessary since String provides its own GetHashCode implementation that will be invokespecialed already since it's a final class (or whatever the CLR equivalent of final is)?

When you compile the Java code "foo".hashCode() it will be compiled as an invokevirtual java/lang/String/hashCode()I. When IK.VM.NET tries to compile this, it looks up the hashCode() method on String and finds that it should redirect to the static StringHelper.hashCode() method. So that's automatic. It is possible to create bytecode that does an invokevirtual java/lang/Object/hashCode() on a string reference, but Java compilers won't do this, so this is hardly worth optimizing.

Thursday, 22 August 2002 12:49:57 (W. Europe Daylight Time, UTC+02:00)  #    Comments [1]
# Wednesday, 21 August 2002
No Title

I changed java.lang.Class from being remapped to System.Type to its Java implementation.

Integrated some additional native code implementations from Stuart Ballard. Thanks Stuart!

Updated the binaries and source snaphots.

Wednesday, 21 August 2002 10:22:17 (W. Europe Daylight Time, UTC+02:00)  #    Comments [1]
# Monday, 19 August 2002
No Title
I changed the XML remapping language to support Object.hashCode() & Object.toString() twiddling (see this previous posting for more info). It is now possible to specify which CIL code sequence should be substituted for a call to a method. Here is how Object.hashCode() looks:

<method type="instance" name="hashCode" sig="()I" access="public">
 
<override name="GetHashCode" />
  
<invokespecial>
   
<call class="System.Object name="GetHashCode" />
 
</invokespecial>
 
<invokevirtual>
   
<dup />
   
<isinst class="System.String" />
   
<brfalse name="skip" />
   
<call class="StringHelper" name="hashCode" />
   
<br name="end" />
   
<label name="skip" />
   
<callvirt class="System.Object name="GetHashCode" />
   
<label name="end" />
 
</invokevirtual>
</method>

Every virtual call (the invokevirtual bytecode) is converted into a test to see if the call is being done on a string, if so it calls StringHelper.hashCode(), if not, it calls System.Object.GetHashCode(). This isn't yet how it should be, because when it is known at compile time that the reference that hashCode() is called on isn't a string, then this test shouldn't be emitted. I still have to figure out a way to support this optimization.

Updated the binaries and source snaphots.

Monday, 19 August 2002 14:53:35 (W. Europe Daylight Time, UTC+02:00)  #    Comments [1]
# Friday, 16 August 2002
No Title

I reimplemented java.io.FileDescriptor to directly use System.IO.Stream (compiling against the netexp generated mscorlib.jar). This approach seems workable. As an example of how this turns out, here is the FileDescriptor.sync() code:

 public synchronized void sync() throws SyncFailedException
 {
  if(stream == null)
  {
   throw new SyncFailedException("The handle is invalid");
  }
  try
  {
   if(false) throw new system.io.IOException();
   stream.Flush();
  }
  catch(system.io.IOException x)
  {
   throw new SyncFailedException(x.get_Message());
  }
 }

I decided (for the moment) to not have every .NET method throw Throwable, but used the if(false) throw new ... trick. Works quite well, and it doesn't generate any code. I wonder if it would be legal for the compiler to move the stream.Flush() out of the try block... Not that I think any compiler would do this.

Updated the binaries and source snapshots.

Friday, 16 August 2002 15:20:30 (W. Europe Daylight Time, UTC+02:00)  #    Comments [0]
# Thursday, 15 August 2002
No Title

Nothing spectacular, many small changes (clean up, refactoring, bug fixes, enhancements).

Updated the binaries and source snapshots.

Thursday, 15 August 2002 18:34:28 (W. Europe Daylight Time, UTC+02:00)  #    Comments [0]