Skip to content

Commit 7753f24

Browse files
author
David Karlaš
committed
Added caching of GenerateTypeCastDelegate call
1 parent f443755 commit 7753f24

File tree

1 file changed

+47
-40
lines changed

1 file changed

+47
-40
lines changed

Mono.Debugging.Soft/SoftDebuggerAdaptor.cs

Lines changed: 47 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -202,53 +202,60 @@ public override object TryConvert (EvaluationContext ctx, object obj, object tar
202202
return null;
203203
}
204204

205+
static Dictionary<string, TypeCastDelegate> typeCastDelegatesCache = new Dictionary<string, TypeCastDelegate> ();
205206
static TypeCastDelegate GenerateTypeCastDelegate (string methodName, Type fromType, Type toType)
206207
{
207-
var argTypes = new [] { typeof (object) };
208-
var method = new DynamicMethod (methodName, typeof (object), argTypes, true);
209-
ILGenerator il = method.GetILGenerator ();
210-
ConstructorInfo ctorInfo;
211-
MethodInfo methodInfo;
212-
OpCode conv;
213-
214-
il.Emit (OpCodes.Ldarg_0);
215-
il.Emit (OpCodes.Unbox_Any, fromType);
216-
217-
if (fromType.IsSubclassOf (typeof (Nullable))) {
218-
PropertyInfo propInfo = fromType.GetProperty ("Value");
219-
methodInfo = propInfo.GetGetMethod ();
220-
221-
il.Emit (OpCodes.Stloc_0);
222-
il.Emit (OpCodes.Ldloca_S);
223-
il.Emit (OpCodes.Call, methodInfo);
224-
225-
fromType = methodInfo.ReturnType;
226-
}
208+
lock(typeCastDelegatesCache) {
209+
TypeCastDelegate cached;
210+
if (typeCastDelegatesCache.TryGetValue (methodName, out cached))
211+
return cached;
212+
var argTypes = new [] { typeof (object) };
213+
var method = new DynamicMethod (methodName, typeof (object), argTypes, true);
214+
ILGenerator il = method.GetILGenerator ();
215+
ConstructorInfo ctorInfo;
216+
MethodInfo methodInfo;
217+
OpCode conv;
218+
219+
il.Emit (OpCodes.Ldarg_0);
220+
il.Emit (OpCodes.Unbox_Any, fromType);
221+
222+
if (fromType.IsSubclassOf (typeof (Nullable))) {
223+
PropertyInfo propInfo = fromType.GetProperty ("Value");
224+
methodInfo = propInfo.GetGetMethod ();
225+
226+
il.Emit (OpCodes.Stloc_0);
227+
il.Emit (OpCodes.Ldloca_S);
228+
il.Emit (OpCodes.Call, methodInfo);
227229

228-
if (!convertOps.TryGetValue (toType, out conv)) {
229-
argTypes = new [] { fromType };
230+
fromType = methodInfo.ReturnType;
231+
}
230232

231-
if (toType == typeof (string)) {
232-
methodInfo = fromType.GetMethod ("ToString", new Type[0]);
233-
il.Emit (OpCodes.Call, methodInfo);
234-
} else if ((methodInfo = toType.GetMethod ("op_Explicit", argTypes)) != null) {
235-
il.Emit (OpCodes.Call, methodInfo);
236-
} else if ((methodInfo = toType.GetMethod ("op_Implicit", argTypes)) != null) {
237-
il.Emit (OpCodes.Call, methodInfo);
238-
} else if ((ctorInfo = toType.GetConstructor (argTypes)) != null) {
239-
il.Emit (OpCodes.Call, ctorInfo);
233+
if (!convertOps.TryGetValue (toType, out conv)) {
234+
argTypes = new [] { fromType };
235+
236+
if (toType == typeof (string)) {
237+
methodInfo = fromType.GetMethod ("ToString", new Type [0]);
238+
il.Emit (OpCodes.Call, methodInfo);
239+
} else if ((methodInfo = toType.GetMethod ("op_Explicit", argTypes)) != null) {
240+
il.Emit (OpCodes.Call, methodInfo);
241+
} else if ((methodInfo = toType.GetMethod ("op_Implicit", argTypes)) != null) {
242+
il.Emit (OpCodes.Call, methodInfo);
243+
} else if ((ctorInfo = toType.GetConstructor (argTypes)) != null) {
244+
il.Emit (OpCodes.Call, ctorInfo);
245+
} else {
246+
// No idea what else to try...
247+
throw new InvalidCastException ();
248+
}
240249
} else {
241-
// No idea what else to try...
242-
throw new InvalidCastException ();
250+
il.Emit (conv);
243251
}
244-
} else {
245-
il.Emit (conv);
246-
}
247252

248-
il.Emit (OpCodes.Box, toType);
249-
il.Emit (OpCodes.Ret);
250-
251-
return (TypeCastDelegate) method.CreateDelegate (typeof (TypeCastDelegate));
253+
il.Emit (OpCodes.Box, toType);
254+
il.Emit (OpCodes.Ret);
255+
cached = (TypeCastDelegate)method.CreateDelegate (typeof (TypeCastDelegate));
256+
typeCastDelegatesCache [methodName] = cached;
257+
return cached;
258+
}
252259
}
253260

254261
static object DynamicCast (object value, Type target)

0 commit comments

Comments
 (0)