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?