Monday, October 09, 2006 12:45 PM bart

Tales about dynamic languages, Lightweight Code Generation and DynamicMethod

Lately I've been playing around with dynamic languages like IronPython and F# quite a bit (not to a satisfactory level yet, but still...). As usual you might wonder how these work or how you can create such tools yourself. A partial answer to this is another great .NET 2.0 feature called Lightweight Code Generation (LGC). In this short post I just want to wet your appetite for this kind of stuff and show you a rather small though interesting sample of it.

Right, so here's the code:

using System;
using
System.Reflection;
using
System.Reflection.Emit;

class
Dyn
{
   static void
Main()
   {
      DynamicMethod add = new DynamicMethod
(
            "Add"
,
            typeof(int
),
            new Type[] { typeof(int), typeof(int
) },
            typeof
(Dyn).Module
         );

      ILGenerator
gen = add.GetILGenerator();
      gen.Emit(
OpCodes
.Ldarg_0);
      gen.Emit(
OpCodes
.Ldarg_1);
      gen.Emit(
OpCodes
.Add);
      gen.Emit(
OpCodes
.Ret);

      int result = (int
) add.Invoke(
           
null
,
            BindingFlags
.ExactBinding,
            null
,
            new object
[] { 2, 3 },
            null
         );

      Console
.WriteLine(result);
   }
}

The cool thing is of course Reflection.Emit which I've been talking about in the past as well. However, in this case we're not spitting out an assembly on disk or so, instead we use the DynamicMethod class that allows to create a method (i.e. a sequence of IL instructions) in the GC heap memory.

The basic way it works is by having the Invoke method call into some InvokeMethodFast method on a System.RuntimeMethodHandle object that was constructed by the DynamicMethod and the associated ILGenerator. This relies on a ECall into the RuntimeMethodHandle::InvokeMethodFast implemention in reflectioninvocation.cpp (SSCLI) which calls InvokeImpl. This starts a bunch of mechanisms that allocate stack space, turns the GC out of business, copies the arguments passed in to the stack using StackStructData objects, and finally calls the method:

ret = method.CallWithValueTypes_RetArgSlot(pNewArgs);

This calls into the internals of the execution engine beast with JIT and stuff. Finally the invocation bails out and grabs the return value to pass it on to the original caller of Invoke.

Enjoy LCG and stay tuned for more of this in the so-far undefined future!

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

Filed under: ,

Comments

# re: Tales about dynamic languages, Lightweight Code Generation and DynamicMethod

Monday, October 09, 2006 9:02 PM by .NET Junkie

I personally rather see the add.Invoke call replaced by the more readable:
X a = (X)add.CreateDelegate(typeof(X));
int result = a(2, 3);
Where X is a delegate defined by:
delegate int X(int a, int b);

# re: Tales about dynamic languages, Lightweight Code Generation and DynamicMethod

Tuesday, October 10, 2006 3:05 AM by bart

I agree that's a possibility too, but only if you know the signature upfront. In upcoming posts you'll see the reason why Invoke was chosen in the first place.

# re: Tales about dynamic languages, Lightweight Code Generation and DynamicMethod

Wednesday, October 11, 2006 10:50 PM by dotNET Junkie

Great, I'm looking forward to it!

# DynCalc - Dynamic compilation illustrated - Part 1: Infix to postfix

Wednesday, December 13, 2006 6:19 AM by B# .NET Blog

Introduction A few days ago I blogged about dynamic languages and Lightweight Code Generation in .NET

# Dotnet junkie | Actorsinfo

Monday, February 18, 2013 12:30 AM by Dotnet junkie | Actorsinfo

Pingback from  Dotnet junkie | Actorsinfo