<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv=Content-Type content="text/html; charset=us-ascii">
<meta name=Generator content="Microsoft Word 12 (filtered medium)">
<style>
<!--
/* Font Definitions */
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
        {font-family:Consolas;
        panose-1:2 11 6 9 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0in;
        margin-bottom:.0001pt;
        font-size:11.0pt;
        font-family:"Calibri","sans-serif";}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
        {mso-style-priority:99;
        color:purple;
        text-decoration:underline;}
span.EmailStyle17
        {mso-style-type:personal-compose;
        font-family:"Calibri","sans-serif";
        color:windowtext;}
.MsoChpDefault
        {mso-style-type:export-only;}
@page Section1
        {size:8.5in 11.0in;
        margin:1.0in 1.0in 1.0in 1.0in;}
div.Section1
        {page:Section1;}
-->
</style>
<!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]-->
</head>
<body lang=EN-US link=blue vlink=purple>
<div class=Section1>
<p class=MsoNormal>As some of you (probably very few) know, the C# port of
StringTemplate builds and caches dynamic accessors for fields and methods to
improve performance. Today I made an update that I should have made in the
past. Instead of manually building the IL for the accessors, I use the LINQ
expression trees to handle the work behind the scenes. Behind the scenes work
includes selecting the proper opcode for the call (direct vs. indirect
dispatch), optimizations for static methods, and only boxing results when
necessary. The front-end work (actually relevant to the task at hand) is now a
clean expression of the desired behavior.<o:p></o:p></p>
<p class=MsoNormal><o:p> </o:p></p>
<p class=MsoNormal>Later I’ll be updating the experimental ST compiler (only
available via the depot source for the C# port, and disabled by default) to use
expression trees instead of building IL and re-benchmarking it.<o:p></o:p></p>
<p class=MsoNormal><o:p> </o:p></p>
<p class=MsoNormal>The result looks like this:<o:p></o:p></p>
<p class=MsoNormal><o:p> </o:p></p>
<p class=MsoNormal>Before:<o:p></o:p></p>
<p class=MsoNormal><o:p> </o:p></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas;color:blue'>private static</span><span style='font-size:
8.0pt;font-family:Consolas'> <span style='color:#2B91AF'>Func</span><<span
style='color:blue'>object</span>, <span style='color:blue'>object</span>>
BuildAccessor( <span style='color:#2B91AF'>MethodInfo</span> method )<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'>{<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'> System.Reflection.Emit.<span
style='color:#2B91AF'>DynamicMethod</span> dm = <span style='color:blue'>new</span>
System.Reflection.Emit.<span style='color:#2B91AF'>DynamicMethod</span>(method.DeclaringType.Name
+ method.Name + <span style='color:#A31515'>"MethodAccessor"</span>, <span
style='color:blue'>typeof</span>(<span style='color:blue'>object</span>), <span
style='color:blue'>new</span> <span style='color:#2B91AF'>Type</span>[] { <span
style='color:blue'>typeof</span>(<span style='color:blue'>object</span>) },
method.DeclaringType);<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'> <span style='color:blue'>var</span>
gen = dm.GetILGenerator();<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'><o:p> </o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'> <span style='color:blue'>if</span>
(!method.IsStatic)<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'> {<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'>
gen.Emit(System.Reflection.Emit.<span style='color:#2B91AF'>OpCodes</span>.Ldarg_0);<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'>
gen.Emit(System.Reflection.Emit.<span style='color:#2B91AF'>OpCodes</span>.Castclass,
method.DeclaringType);<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'> }<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'><o:p> </o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'> <span style='color:blue'>if</span>
(method.IsVirtual && !method.IsFinal)<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'>
gen.EmitCall(System.Reflection.Emit.<span style='color:#2B91AF'>OpCodes</span>.Callvirt,
method, <span style='color:blue'>null</span>);<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'> <span style='color:blue'>else<o:p></o:p></span></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'>
gen.EmitCall(System.Reflection.Emit.<span style='color:#2B91AF'>OpCodes</span>.Call,
method, <span style='color:blue'>null</span>);<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'><o:p> </o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'> <span style='color:blue'>if</span>
(method.ReturnType.IsValueType)<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'>
gen.Emit(System.Reflection.Emit.<span style='color:#2B91AF'>OpCodes</span>.Box,
method.ReturnType);<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'><o:p> </o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'> gen.Emit(System.Reflection.Emit.<span
style='color:#2B91AF'>OpCodes</span>.Ret);<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'> <span style='color:blue'>return</span>
(<span style='color:#2B91AF'>Func</span><<span style='color:blue'>object</span>,
<span style='color:blue'>object</span>>)dm.CreateDelegate(<span
style='color:blue'>typeof</span>(<span style='color:#2B91AF'>Func</span><<span
style='color:blue'>object</span>, <span style='color:blue'>object</span>>));<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'>}<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'><o:p> </o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas;color:blue'>private static</span><span style='font-size:
8.0pt;font-family:Consolas'> <span style='color:#2B91AF'>Func</span><<span
style='color:blue'>object</span>, <span style='color:blue'>object</span>>
BuildAccessor( <span style='color:#2B91AF'>FieldInfo</span> field )<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'>{<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'> System.Reflection.Emit.<span
style='color:#2B91AF'>DynamicMethod</span> dm = <span style='color:blue'>new</span>
System.Reflection.Emit.<span style='color:#2B91AF'>DynamicMethod</span>(field.DeclaringType.Name
+ field.Name + <span style='color:#A31515'>"FieldAccessor"</span>, <span
style='color:blue'>typeof</span>(<span style='color:blue'>object</span>), <span
style='color:blue'>new</span> <span style='color:#2B91AF'>Type</span>[] { <span
style='color:blue'>typeof</span>(<span style='color:blue'>object</span>) },
field.DeclaringType);<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'><o:p> </o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'> <span style='color:blue'>var</span>
gen = dm.GetILGenerator();<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'> <span style='color:blue'>if</span>
(field.IsStatic)<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'> {<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'>
gen.Emit(System.Reflection.Emit.<span style='color:#2B91AF'>OpCodes</span>.Ldsfld,
field);<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'> }<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'> <span style='color:blue'>else<o:p></o:p></span></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'> {<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'>
gen.Emit(System.Reflection.Emit.<span style='color:#2B91AF'>OpCodes</span>.Ldarg_0);<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'>
gen.Emit(System.Reflection.Emit.<span style='color:#2B91AF'>OpCodes</span>.Castclass,
field.DeclaringType);<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'>
gen.Emit(System.Reflection.Emit.<span style='color:#2B91AF'>OpCodes</span>.Ldfld,
field);<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'> }<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'><o:p> </o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'> <span style='color:blue'>if</span>
(field.FieldType.IsValueType)<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'>
gen.Emit(System.Reflection.Emit.<span style='color:#2B91AF'>OpCodes</span>.Box,
field.FieldType);<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'><o:p> </o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'> gen.Emit(System.Reflection.Emit.<span
style='color:#2B91AF'>OpCodes</span>.Ret);<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'> <span style='color:blue'>return</span>
(<span style='color:#2B91AF'>Func</span><<span style='color:blue'>object</span>,
<span style='color:blue'>object</span>>)dm.CreateDelegate(<span
style='color:blue'>typeof</span>(<span style='color:#2B91AF'>Func</span><<span
style='color:blue'>object</span>, <span style='color:blue'>object</span>>));<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'>}<o:p></o:p></span></p>
<p class=MsoNormal><o:p> </o:p></p>
<p class=MsoNormal>After:<o:p></o:p></p>
<p class=MsoNormal><o:p> </o:p></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas;color:blue'>private static</span><span style='font-size:
8.0pt;font-family:Consolas'> <span style='color:#2B91AF'>Func</span><<span
style='color:blue'>object</span>, <span style='color:blue'>object</span>>
BuildAccessor(<span style='color:#2B91AF'>MethodInfo</span> method)<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'>{<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'> <span style='color:#2B91AF'>ParameterExpression</span>
obj = <span style='color:#2B91AF'>Expression</span>.Parameter(<span
style='color:blue'>typeof</span>(<span style='color:blue'>object</span>), <span
style='color:#A31515'>"obj"</span>);<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'> <span style='color:#2B91AF'>Expression</span><<span
style='color:#2B91AF'>Func</span><<span style='color:blue'>object</span>, <span
style='color:blue'>object</span>>> expr = <span style='color:#2B91AF'>Expression</span>.Lambda<<span
style='color:#2B91AF'>Func</span><<span style='color:blue'>object</span>, <span
style='color:blue'>object</span>>>(<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'> <span
style='color:#2B91AF'>Expression</span>.Convert(<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'>
<span style='color:#2B91AF'>Expression</span>.Call(<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'>
<span style='color:#2B91AF'>Expression</span>.Convert(obj,
method.DeclaringType),<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'>
method),<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'>
<span style='color:blue'>typeof</span>(<span style='color:blue'>object</span>)),<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'> obj);<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'><o:p> </o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'> <span style='color:blue'>return</span>
expr.Compile();<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'>}<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'><o:p> </o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas;color:blue'>private static</span><span style='font-size:
8.0pt;font-family:Consolas'> <span style='color:#2B91AF'>Func</span><<span
style='color:blue'>object</span>, <span style='color:blue'>object</span>>
BuildAccessor(<span style='color:#2B91AF'>FieldInfo</span> field)<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'>{<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'> <span style='color:#2B91AF'>ParameterExpression</span>
obj = <span style='color:#2B91AF'>Expression</span>.Parameter(<span
style='color:blue'>typeof</span>(<span style='color:blue'>object</span>), <span
style='color:#A31515'>"obj"</span>);<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'> <span style='color:#2B91AF'>Expression</span><<span
style='color:#2B91AF'>Func</span><<span style='color:blue'>object</span>, <span
style='color:blue'>object</span>>> expr = <span style='color:#2B91AF'>Expression</span>.Lambda<<span
style='color:#2B91AF'>Func</span><<span style='color:blue'>object</span>, <span
style='color:blue'>object</span>>>(<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'> <span
style='color:#2B91AF'>Expression</span>.Convert(<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'>
<span style='color:#2B91AF'>Expression</span>.Field(<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'>
<span style='color:#2B91AF'>Expression</span>.Convert(obj,
field.DeclaringType),<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'>
field),<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'>
<span style='color:blue'>typeof</span>(<span style='color:blue'>object</span>)),<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'> obj);<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'><o:p> </o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'> <span style='color:blue'>return</span>
expr.Compile();<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:8.0pt;
font-family:Consolas'>}<o:p></o:p></span></p>
<p class=MsoNormal><o:p> </o:p></p>
</div>
</body>
</html>