I spent some time this morning thinking about how to fix the boxing showstopper bug in RubyCLR. Here’s a simple repro:
a = ArrayList.new p = Point.new(3, 4) a.add(p)
This problem is so much harder than it looks. ArrayList.Add expects a reference type, but p contains a value type. RubyCLR respects value type semantics, so the Ruby VALUE object contains the opaque blob of data that is a Point struct.
The problem is: how do I marshal this thing to the CLR? The way you marshal a value type to the CLR is to explicitly box it. The CIL instruction sequence looks like:
ldarg_s value ldc_i4_s 16 add ldobj 'System.Point' box 'System.Point'
A Ruby VALUE object is an opaque blob of memory. Ruby and RubyCLR store some other stuff in the first 16 bytes, so I have to add that offset first before loading the value type object onto the stack.
But here’s the problem: both the ldobj and the box instructions require a type parameter. This code sequence must execute within my marshaling shim that is generated at runtime. I don’t know what the type of value is at shim generation (aka compile) time.
It looks like I have to generate specific boxing functions for each value type and cache them at runtime.
Unless someone has a better suggestion?