Skip to content

Commit ede9fdb

Browse files
authored
Merge pull request #99 from mono/bug52333
Bug 52333 - Debugger applies rounding when casting float values to int
2 parents ccfaec4 + 7753f24 commit ede9fdb

File tree

1 file changed

+48
-80
lines changed

1 file changed

+48
-80
lines changed

Mono.Debugging.Soft/SoftDebuggerAdaptor.cs

Lines changed: 48 additions & 80 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)
@@ -391,46 +398,7 @@ public override object TryCast (EvaluationContext ctx, object val, object type)
391398
if (val == null)
392399
return null;
393400

394-
object res;
395-
396-
try {
397-
if (tt == typeof (bool))
398-
res = System.Convert.ToBoolean (val);
399-
else if (tt == typeof (byte))
400-
res = System.Convert.ToByte (val);
401-
else if (tt == typeof (sbyte))
402-
res = System.Convert.ToSByte (val);
403-
else if (tt == typeof (char))
404-
res = System.Convert.ToChar (val);
405-
else if (tt == typeof (short))
406-
res = System.Convert.ToInt16 (val);
407-
else if (tt == typeof (ushort))
408-
res = System.Convert.ToUInt16 (val);
409-
else if (tt == typeof (int))
410-
res = System.Convert.ToInt32 (val);
411-
else if (tt == typeof (uint))
412-
res = System.Convert.ToUInt32 (val);
413-
else if (tt == typeof (long))
414-
res = System.Convert.ToInt64 (val);
415-
else if (tt == typeof (ulong))
416-
res = System.Convert.ToUInt64 (val);
417-
else if (tt == typeof (float))
418-
res = System.Convert.ToSingle (val);
419-
else if (tt == typeof (double))
420-
res = System.Convert.ToDouble (val);
421-
else if (tt == typeof (decimal))
422-
res = System.Convert.ToDecimal (val);
423-
else if (tt == typeof (string))
424-
res = System.Convert.ToString (val);
425-
else if (tt == typeof (DateTime))
426-
res = System.Convert.ToDateTime (val);
427-
else
428-
res = val;
429-
} catch {
430-
res = DynamicCast (val, tt);
431-
}
432-
433-
return CreateValue (ctx, res);
401+
return CreateValue (ctx, DynamicCast (val, tt));
434402
}
435403

436404
fromType = (TypeMirror) ForceLoadType (ctx, ((Type) valueType).FullName);

0 commit comments

Comments
 (0)