1 Introduction

In this post I attempt to explore an important component of the JIT
execution environment The Marshalling Wrappers.

The intention here is not to exhaust all eventualities and
practicalities concerning marshalling wrappers. The goal is to
merely explore a not too complex facet of the same. This I would do
by considering a simple example.

Before we move ahead with the example, let’s see how a dictionary
defines the word – Marshal (v). The following description fits our
current purpose.

2 Example Assembly

3 JIT Execute Assembly

$ mono CommandLine.exe HelloWorld

As the runtime prepares to call in to the entry point method of
CommandLine.exe, it parses the shell command line and sets up the
caller side stack exactly as the Main () expects it. It then invokes
the the target method – Main () in the loaded assembly.

The later invocation happens via a Method Wrapper called Runtime Invoke Wrapper. We will come to this Wrapper shortly.

3.1 Parameter Marshalling

In this step, the runtime ‘constructs’ the Main’s args of typestring[] using the argc , argv[] pair passed to it as part of
the c-runtime.

It is worth noting that the Memory pointed to by MonoArray*args and MonoStringarg in the above given trace are first
class CLR objects. These are ‘managed’ and hence would be Garbage
Collected by the Mono Runtime itself. On the other hand, the memory
pointed to by gchar*str comes from the unmanaged pool and has
to be explitictly freed.

3.2 Target Method Invocation

Once the paramters are marshalled, the next step is to invoke the
target method. This happens in four distinct steps –

3.2.1 Build a Runtime Invoke Wrapper

The Runtime Invoke wrapper for the invocation of the Main () is
generated by the runtime on the fly. The method is built using
Method Builder Interface within the runtime and is subsequently
JIT compiled.

Please note that the Runtime Invoke Wrapper, in addition to
calling the target method also surrounds it with a a
behind-the-scene try-filter block2. The filter block makes it’s
filtering decision based on whether or not the caller provided a
‘exc’ reference to it. The handler block does some special case
handling for ThreadAbortException thrown by the target method.

Additional Note: CIL code is also made more interesting for it
exposes some of the Mono’s private opcodes that are used withing
the the runtime. We would have time to explore these opcodes –mono_ldpt, mono_not_taken, mono_icall –
in the context of a possibly different post.

For the utterly curious, the corresponding native code looks like
this. For now it is sufficient to make a mental note of how a
compiled try-filter-handler block looks like. We would have a chance
to examine the try blocks while exploring Exception Handling in the
runtime.

Footnotes:

2 At this point in time, I am unable to explain the purpose of this
try-filter block. I am sure the very purpose of the Invoke Wrapper
is to provide a place holder for this special case handling of
exceptions thrown from the invoked routines.