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.
3:57:52 PM Comments
|