~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to src/addins/MonoDevelop.Debugger.Soft/Mono.Debugging.Soft/SoftDebuggerAdaptor.cs

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
// 
2
2
// SoftDebuggerAdaptor.cs
3
3
//  
4
 
// Author:
5
 
//       Lluis Sanchez Gual <lluis@novell.com>
 
4
// Authors: Lluis Sanchez Gual <lluis@novell.com>
 
5
//          Jeffrey Stedfast <jeff@xamarin.com>
6
6
// 
7
7
// Copyright (c) 2009 Novell, Inc (http://www.novell.com)
 
8
// Copyright (c) 2011,2012 Xamain Inc. (http://www.xamarin.com)
8
9
// 
9
10
// Permission is hereby granted, free of charge, to any person obtaining a copy
10
11
// of this software and associated documentation files (the "Software"), to deal
72
73
                        
73
74
                        if (obj is StringMirror)
74
75
                                return ((StringMirror)obj).Value;
75
 
                        else if (obj is EnumMirror) {
76
 
                                EnumMirror eob = (EnumMirror) obj;
77
 
                                return eob.StringValue;
78
 
                        }
79
 
                        else if (obj is PrimitiveValue)
 
76
 
 
77
                        if (obj is EnumMirror)
 
78
                                return ((EnumMirror) obj).StringValue;
 
79
 
 
80
                        if (obj is PrimitiveValue)
80
81
                                return ((PrimitiveValue)obj).Value.ToString ();
81
 
                        else if (obj is PointerValue)
 
82
 
 
83
                        if (obj is PointerValue)
82
84
                                return string.Format ("0x{0:x}", ((PointerValue)obj).Address);
83
 
                        else if ((obj is StructMirror) && ((StructMirror)obj).Type.IsPrimitive) {
 
85
 
 
86
                        if ((obj is StructMirror) && ((StructMirror)obj).Type.IsPrimitive) {
84
87
                                // Boxed primitive
85
88
                                StructMirror sm = (StructMirror) obj;
86
89
                                if (sm.Fields.Length > 0 && (sm.Fields[0] is PrimitiveValue))
87
90
                                        return ((PrimitiveValue)sm.Fields[0]).Value.ToString ();
88
 
                        }
89
 
                        else if ((obj is ObjectMirror) && cx.Options.AllowTargetInvoke) {
 
91
                        } else if ((obj is ObjectMirror) && cx.Options.AllowTargetInvoke) {
90
92
                                ObjectMirror ob = (ObjectMirror) obj;
91
93
                                MethodMirror method = OverloadResolve (cx, "ToString", ob.Type, new TypeMirror[0], true, false, false);
92
94
                                if (method != null && method.DeclaringType.FullName != "System.Object") {
93
95
                                        StringMirror res = cx.RuntimeInvoke (method, obj, new Value[0]) as StringMirror;
94
96
                                        return res != null ? res.Value : null;
95
97
                                }
96
 
                        }
97
 
                        else if ((obj is StructMirror) && cx.Options.AllowTargetInvoke) {
 
98
                        } else if ((obj is StructMirror) && cx.Options.AllowTargetInvoke) {
98
99
                                StructMirror ob = (StructMirror) obj;
99
100
                                MethodMirror method = OverloadResolve (cx, "ToString", ob.Type, new TypeMirror[0], true, false, false);
100
101
                                if (method != null && method.DeclaringType.FullName != "System.ValueType") {
246
247
                                                return cx.RuntimeInvoke (method, obj, new Value[0]);
247
248
                                }
248
249
 
249
 
                                if (fromType.IsGenericType && fromType.FullName.StartsWith ("System.Nullable`")) {
 
250
                                if (fromType.IsGenericType && fromType.FullName.StartsWith ("System.Nullable`1", StringComparison.Ordinal)) {
250
251
                                        method = OverloadResolve (cx, "get_Value", fromType, new TypeMirror[0], true, false, false);
251
252
                                        if (method != null) {
252
253
                                                obj = cx.RuntimeInvoke (method, obj, new Value[0]);
333
334
                        TypeMirror t = (TypeMirror) type;
334
335
                        
335
336
                        TypeMirror[] types = new TypeMirror [args.Length];
336
 
                        for (int n=0; n<args.Length; n++)
337
 
                                types [n] = ToTypeMirror (ctx, GetValueType (ctx, args [n]));
338
 
                        
339
337
                        Value[] values = new Value[args.Length];
340
 
                        for (int n=0; n<args.Length; n++)
341
 
                                values[n] = (Value) args [n];
 
338
                        for (int n = 0; n < args.Length; n++) {
 
339
                                types[n] = ToTypeMirror (ctx, GetValueType (ctx, args[n]));
 
340
                                values[n] = (Value) args[n];
 
341
                        }
342
342
                        
343
343
                        MethodMirror ctor = OverloadResolve (cx, ".ctor", t, types, true, true, true);
344
344
                        if (ctor == null)
361
361
                        return val;
362
362
                }
363
363
 
 
364
                public override bool NullableHasValue (EvaluationContext ctx, object type, object obj)
 
365
                {
 
366
                        ValueReference hasValue = GetMember (ctx, type, obj, "has_value");
 
367
 
 
368
                        return (bool) hasValue.ObjectValue;
 
369
                }
 
370
 
 
371
                public override ValueReference NullableGetValue (EvaluationContext ctx, object type, object obj)
 
372
                {
 
373
                        return GetMember (ctx, type, obj, "value");
 
374
                }
 
375
 
364
376
                public override object GetEnclosingType (EvaluationContext ctx)
365
377
                {
366
378
                        SoftEvaluationContext cx = (SoftEvaluationContext) ctx;
381
393
 
382
394
                public override ValueReference GetIndexerReference (EvaluationContext ctx, object target, object[] indices)
383
395
                {
384
 
                        TypeMirror targetType = GetValueType (ctx, target) as TypeMirror;
 
396
                        object valueType = GetValueType (ctx, target);
 
397
                        TypeMirror targetType = null;
 
398
 
 
399
                        if (valueType is Type)
 
400
                                targetType = (TypeMirror) ForceLoadType (ctx, ((Type) valueType).FullName);
 
401
                        else if (valueType is TypeMirror)
 
402
                                targetType = (TypeMirror) valueType;
 
403
                        else
 
404
                                return null;
385
405
                        
386
406
                        Value[] values = new Value [indices.Length];
387
407
                        TypeMirror[] types = new TypeMirror [indices.Length];
449
469
                
450
470
                static bool IsHoistedThisReference (FieldInfoMirror field)
451
471
                {
452
 
                        // mcs is "<>f__this"
 
472
                        // mcs is "<>f__this" or "$this" (if in an async compiler generated type)
453
473
                        // csc is "<>4__this"
454
 
                        return field.Name.StartsWith ("<>") && field.Name.EndsWith ("__this");
 
474
                        return field.Name == "$this" ||
 
475
                                (field.Name.StartsWith ("<>", StringComparison.Ordinal) &&
 
476
                                 field.Name.EndsWith ("__this", StringComparison.Ordinal));
455
477
                }
456
478
                
457
479
                static bool IsClosureReferenceField (FieldInfoMirror field)
458
480
                {
459
481
                        // mcs is "<>f__ref"
460
482
                        // csc is "CS$<>"
461
 
                        return field.Name.StartsWith ("CS$<>") || field.Name.StartsWith ("<>f__ref");
 
483
                        return field.Name.StartsWith ("CS$<>", StringComparison.Ordinal) ||
 
484
                                field.Name.StartsWith ("<>f__ref", StringComparison.Ordinal);
462
485
                }
463
486
                
464
487
                static bool IsClosureReferenceLocal (LocalVariable local)
465
488
                {
466
489
                        if (local.Name == null)
467
490
                                return false;
468
 
                        
469
 
                        return
470
 
                                // mcs
471
 
                                local.Name.Length == 0 || local.Name[0] == '<' || local.Name.StartsWith ("$locvar")
472
 
                                // csc
473
 
                                || local.Name.StartsWith ("CS$<>");
 
491
 
 
492
                        // mcs is "$locvar" or starts with '<'
 
493
                        // csc is "CS$<>"
 
494
                        return local.Name.Length == 0 || local.Name[0] == '<' || local.Name.StartsWith ("$locvar", StringComparison.Ordinal) ||
 
495
                                local.Name.StartsWith ("CS$<>", StringComparison.Ordinal);
474
496
                }
475
497
                
476
498
                static bool IsGeneratedTemporaryLocal (LocalVariable local)
477
499
                {
478
 
                        return local.Name != null && local.Name.StartsWith ("CS$");
 
500
                        return local.Name != null && local.Name.StartsWith ("CS$", StringComparison.Ordinal);
479
501
                }
480
502
                
481
503
                static string GetHoistedIteratorLocalName (FieldInfoMirror field)
482
504
                {
483
505
                        //mcs captured args, of form <$>name
484
 
                        if (field.Name.StartsWith ("<$>")) {
 
506
                        if (field.Name.StartsWith ("<$>", StringComparison.Ordinal)) {
485
507
                                return field.Name.Substring (3);
486
508
                        }
487
509
                        
488
510
                        // csc, mcs locals of form <name>__0
489
 
                        if (field.Name.StartsWith ("<")) {
 
511
                        if (field.Name.StartsWith ("<", StringComparison.Ordinal)) {
490
512
                                int i = field.Name.IndexOf ('>');
491
513
                                if (i > 1) {
492
514
                                        return field.Name.Substring (1, i - 1);
516
538
                                        list.AddRange (GetHoistedLocalVariables (cx, new FieldValueReference (cx, field, val, type)));
517
539
                                        continue;
518
540
                                }
519
 
                                if (field.Name.StartsWith ("<")) {
 
541
                                if (field.Name.StartsWith ("<", StringComparison.Ordinal)) {
520
542
                                        if (isIterator) {
521
543
                                                var name = GetHoistedIteratorLocalName (field);
522
544
                                                if (!string.IsNullOrEmpty (name)) {
559
581
                // if the local does not have a name, constructs one from the index
560
582
                static string GetLocalName (SoftEvaluationContext cx, LocalVariable local)
561
583
                {
562
 
                        var name = local.Name;
563
584
                        if (!string.IsNullOrEmpty (local.Name) || cx.SourceCodeAvailable)
564
 
                                return name;
 
585
                                return local.Name;
565
586
                        return "loc" + local.Index;
566
587
                }
567
588
                
574
595
                        try {
575
596
                                LocalVariable local = null;
576
597
                                if (!cx.SourceCodeAvailable) {
577
 
                                        if (name.StartsWith ("loc")) {
 
598
                                        if (name.StartsWith ("loc", StringComparison.Ordinal)) {
578
599
                                                int idx;
579
600
                                                if (int.TryParse (name.Substring (3), out idx))
580
601
                                                        local = cx.Frame.Method.GetLocals ().FirstOrDefault (loc => loc.Index == idx);
587
608
                                if (local != null) {
588
609
                                        return new VariableValueReference (ctx, GetLocalName (cx, local), local);
589
610
                                }
590
 
                                return FindByName (OnGetLocalVariables (ctx), v => v.Name, name, ctx.CaseSensitive);;
 
611
                                return FindByName (OnGetLocalVariables (ctx), v => v.Name, name, ctx.CaseSensitive);
591
612
                        } catch (AbsentInformationException) {
592
613
                                return null;
593
614
                        }
650
671
                        return false;
651
672
                }
652
673
 
 
674
                static bool IsAnonymousType (TypeMirror type)
 
675
                {
 
676
                        return type.Name.StartsWith ("<>__AnonType", StringComparison.Ordinal);
 
677
                }
 
678
 
653
679
                protected override ValueReference GetMember (EvaluationContext ctx, object t, object co, string name)
654
680
                {
655
 
                        TypeMirror type = (TypeMirror) t;
 
681
                        TypeMirror type = t as TypeMirror;
656
682
 
657
683
                        while (type != null) {
658
 
                                FieldInfoMirror field = FindByName (type.GetFields(), f => f.Name, name, ctx.CaseSensitive);
 
684
                                FieldInfoMirror field = FindByName (type.GetFields (), f => f.Name, name, ctx.CaseSensitive);
659
685
                                if (field != null && (field.IsStatic || co != null))
660
686
                                        return new FieldValueReference (ctx, field, co, type);
661
687
 
662
 
                                PropertyInfoMirror prop = FindByName (type.GetProperties(), p => p.Name, name, ctx.CaseSensitive);
 
688
                                PropertyInfoMirror prop = FindByName (type.GetProperties (), p => p.Name, name, ctx.CaseSensitive);
663
689
                                if (prop != null && (IsStatic (prop) || co != null)) {
664
690
                                        // Optimization: if the property has a CompilerGenerated backing field, use that instead.
665
691
                                        // This way we avoid overhead of invoking methods on the debugee when the value is requested.
666
 
                                        string cgFieldName = string.Format ("<{0}>k__BackingField", prop.Name);
 
692
                                        string cgFieldName = string.Format ("<{0}>{1}", prop.Name, IsAnonymousType (type) ? "" : "k__BackingField");
667
693
                                        if ((field = FindByName (type.GetFields (), f => f.Name, cgFieldName, true)) != null && IsCompilerGenerated (field))
668
694
                                                return new FieldValueReference (ctx, field, co, type, prop.Name, ObjectValueFlags.Property);
669
695
 
701
727
                                string n = getName (t);
702
728
                                if (n == name) 
703
729
                                        return t;
704
 
                                else if (!caseSensitive && n.Equals (name, StringComparison.CurrentCultureIgnoreCase))
 
730
                                if (!caseSensitive && n.Equals (name, StringComparison.CurrentCultureIgnoreCase))
705
731
                                        best = t;
706
732
                        }
707
733
                        return best;
780
806
                        HashSet<string> namespaces = new HashSet<string> ();
781
807
                        string namspacePrefix = namspace.Length > 0 ? namspace + "." : "";
782
808
                        foreach (TypeMirror type in cx.Session.GetAllTypes ()) {
783
 
                                if (type.Namespace == namspace || type.Namespace.StartsWith (namspacePrefix)) {
 
809
                                if (type.Namespace == namspace || type.Namespace.StartsWith (namspacePrefix, StringComparison.InvariantCulture)) {
784
810
                                        namespaces.Add (type.Namespace);
785
811
                                        types.Add (type.FullName);
786
812
                                }
804
830
                                
805
831
                        foreach (LocalVariable var in locals) {
806
832
                                if (var.IsArg) {
807
 
                                        string name = !string.IsNullOrEmpty (var.Name) || cx.SourceCodeAvailable ? var.Name : "arg" + var.Index;
 
833
                                        string name = !string.IsNullOrEmpty (var.Name) ? var.Name : "arg" + var.Index;
808
834
                                        yield return new VariableValueReference (ctx, name, var);
809
835
                                }
810
836
                        }
815
841
                        SoftEvaluationContext cx = (SoftEvaluationContext) ctx;
816
842
                        if (InGeneratedClosureOrIteratorType (cx))
817
843
                                return GetHoistedThisReference (cx);
818
 
                        else
819
 
                                return GetThisReference (cx);
 
844
 
 
845
                        return GetThisReference (cx);
820
846
                }
821
847
                
822
848
                ValueReference GetThisReference (SoftEvaluationContext cx)
871
897
                                object[] types = new object [names.Count];
872
898
                                for (int n=0; n<names.Count; n++) {
873
899
                                        string tn = names [n];
874
 
                                        if (tn.StartsWith ("["))
 
900
                                        if (tn.StartsWith ("[", StringComparison.Ordinal))
875
901
                                                tn = tn.Substring (1, tn.Length - 2);
876
902
                                        types [n] = GetType (ctx, tn);
877
903
                                        if (types [n] == null)
933
959
                        return null;
934
960
                }
935
961
 
 
962
                public override object GetParentType (EvaluationContext ctx, object type)
 
963
                {
 
964
                        TypeMirror tm = type as TypeMirror;
 
965
 
 
966
                        if (tm != null) {
 
967
                                int plus = tm.FullName.LastIndexOf ('+');
 
968
 
 
969
                                return plus != -1 ? GetType (ctx, tm.FullName.Substring (0, plus)) : null;
 
970
                        }
 
971
 
 
972
                        return ((Type) type).DeclaringType;
 
973
                }
 
974
 
936
975
                public override IEnumerable<object> GetNestedTypes (EvaluationContext ctx, object type)
937
976
                {
938
977
                        TypeMirror t = (TypeMirror) type;
940
979
                                yield return nt;
941
980
                }
942
981
                
943
 
                public override string GetTypeName (EvaluationContext ctx, object val)
 
982
                public override string GetTypeName (EvaluationContext ctx, object type)
944
983
                {
945
 
                        TypeMirror tm = val as TypeMirror;
 
984
                        TypeMirror tm = type as TypeMirror;
946
985
                        if (tm != null) {
947
986
                                if (IsGeneratedType (tm)) {
948
987
                                        // Return the name of the container-type.
950
989
                                }
951
990
                                
952
991
                                return tm.FullName;
953
 
                        } else
954
 
                                return ((Type)val).FullName;
 
992
                        }
 
993
 
 
994
                        return ((Type)type).FullName;
955
995
                }
956
996
                
957
997
                public override object GetValueType (EvaluationContext ctx, object val)
970
1010
                                PrimitiveValue pv = (PrimitiveValue) val;
971
1011
                                if (pv.Value == null)
972
1012
                                        return typeof(Object);
973
 
                                else
974
 
                                        return pv.Value.GetType ();
 
1013
 
 
1014
                                return pv.Value.GetType ();
975
1015
                        }
976
1016
 
977
1017
                        throw new NotSupportedException ();
981
1021
                {
982
1022
                        if (type is TypeMirror)
983
1023
                                return ((TypeMirror)type).BaseType;
984
 
                        else
985
 
                                return null;
 
1024
 
 
1025
                        return null;
986
1026
                }
987
1027
 
988
1028
                public override bool HasMethod (EvaluationContext gctx, object targetType, string methodName, object[] argTypes, BindingFlags flags)
1024
1064
                        return val is ArrayMirror;
1025
1065
                }
1026
1066
 
 
1067
                public override bool IsValueType (object type)
 
1068
                {
 
1069
                        TypeMirror t = type as TypeMirror;
 
1070
                        return t != null && t.IsValueType;
 
1071
                }
 
1072
 
1027
1073
                public override bool IsClass (object type)
1028
1074
                {
1029
1075
                        TypeMirror t = type as TypeMirror;
1116
1162
                        }
1117
1163
                        return default(T);
1118
1164
                }
1119
 
                
1120
 
                public override object ForceLoadType (EvaluationContext gctx, string typeName)
1121
 
                {
1122
 
                        // Shortcut to avoid a target invoke in case the type is already loaded
1123
 
                        object t = GetType (gctx, typeName);
1124
 
                        if (t != null)
1125
 
                                return t;
1126
 
                        
1127
 
                        SoftEvaluationContext ctx = (SoftEvaluationContext) gctx;
1128
 
                        if (!ctx.Options.AllowTargetInvoke)
1129
 
                                return null;
1130
 
                        
1131
 
                        TypeMirror tm = (TypeMirror) ctx.Thread.Type.GetTypeObject ().Type;
1132
 
                        TypeMirror stype = ctx.Session.GetType ("System.String");
1133
 
                        if (stype == null) {
1134
 
                                // If the string type is not loaded, we need to get it in another way
1135
 
                                StringMirror ss = ctx.Thread.Domain.CreateString ("");
1136
 
                                stype = ss.Type;
1137
 
                        }
1138
 
                        
1139
 
                        TypeMirror[] ats = new TypeMirror[] { stype };
1140
 
                        MethodMirror met = OverloadResolve (ctx, "GetType", tm, ats, false, true, true);
1141
 
                        
 
1165
 
 
1166
                public override bool IsTypeLoaded (EvaluationContext gctx, string typeName)
 
1167
                {
 
1168
                        SoftEvaluationContext ctx = (SoftEvaluationContext) gctx;
 
1169
                        
 
1170
                        return ctx.Session.GetType (typeName) != null;
 
1171
                }
 
1172
                
 
1173
                public override bool IsTypeLoaded (EvaluationContext ctx, object type)
 
1174
                {
 
1175
                        TypeMirror tm = (TypeMirror) type;
 
1176
 
 
1177
                        if (tm.VirtualMachine.Version.AtLeast (2, 23))
 
1178
                                return tm.IsInitialized;
 
1179
 
 
1180
                        return IsTypeLoaded (ctx, tm.FullName);
 
1181
                }
 
1182
                
 
1183
                public override bool ForceLoadType (EvaluationContext gctx, object type)
 
1184
                {
 
1185
                        SoftEvaluationContext ctx = (SoftEvaluationContext) gctx;
 
1186
                        TypeMirror tm = (TypeMirror) type;
 
1187
 
 
1188
                        if (!tm.VirtualMachine.Version.AtLeast (2, 23))
 
1189
                                return IsTypeLoaded (gctx, tm.FullName);
 
1190
 
 
1191
                        if (tm.IsInitialized)
 
1192
                                return true;
 
1193
 
 
1194
                        if (!tm.Attributes.HasFlag (TypeAttributes.BeforeFieldInit))
 
1195
                                return false;
 
1196
 
 
1197
                        MethodMirror cctor = OverloadResolve (ctx, ".cctor", tm, new TypeMirror[0], false, true, false);
 
1198
                        if (cctor == null)
 
1199
                                return true;
 
1200
 
1142
1201
                        try {
1143
 
                                tm.InvokeMethod (ctx.Thread, met, new Value[] {(Value) CreateValue (ctx, typeName)}, InvokeOptions.DisableBreakpoints | InvokeOptions.SingleThreaded);
 
1202
                                tm.InvokeMethod (ctx.Thread, cctor, new Value[0], InvokeOptions.DisableBreakpoints | InvokeOptions.SingleThreaded);
1144
1203
                        } catch {
1145
 
                                return null;
 
1204
                                return false;
1146
1205
                        } finally {
1147
1206
                                ctx.Session.StackVersion++;
1148
1207
                        }
1149
 
                        
1150
 
                        return GetType (ctx, typeName);
 
1208
 
 
1209
                        return true;
1151
1210
                }
1152
 
 
1153
1211
                
1154
1212
                static T BuildAttribute<T> (CustomAttributeDataMirror attr)
1155
1213
                {
1292
1350
                static MethodMirror OverloadResolve (SoftEvaluationContext ctx, string typeName, string methodName, TypeMirror[] argtypes, List<MethodMirror> candidates, bool throwIfNotFound)
1293
1351
                {
1294
1352
                        if (candidates.Count == 0) {
1295
 
                                if (throwIfNotFound)
 
1353
                                if (throwIfNotFound) {
 
1354
                                        if (methodName == null)
 
1355
                                                throw new EvaluatorException ("Indexer not found in type `{0}'.", typeName);
 
1356
 
1296
1357
                                        throw new EvaluatorException ("Method `{0}' not found in type `{1}'.", methodName, typeName);
1297
 
                                else
 
1358
                                } else
1298
1359
                                        return null;
1299
1360
                        }
1300
1361
 
1389
1450
                                return ((PrimitiveValue)obj).Value;
1390
1451
                        } else if (obj is PointerValue) {
1391
1452
                                return new IntPtr (((PointerValue)obj).Address);
1392
 
                        } else if ((obj is StructMirror) && ((StructMirror)obj).Type.IsPrimitive) {
1393
 
                                // Boxed primitive
 
1453
                        } else if (obj is StructMirror) {
1394
1454
                                StructMirror sm = (StructMirror) obj;
1395
 
                                if (sm.Type.FullName == "System.IntPtr")
1396
 
                                        return new IntPtr ((long)((PrimitiveValue)sm.Fields[0]).Value);
1397
 
                                if (sm.Fields.Length > 0 && (sm.Fields[0] is PrimitiveValue))
1398
 
                                        return ((PrimitiveValue)sm.Fields[0]).Value;
 
1455
 
 
1456
                                if (sm.Type.IsPrimitive) {
 
1457
                                        // Boxed primitive
 
1458
                                        if (sm.Type.FullName == "System.IntPtr")
 
1459
                                                return new IntPtr ((long)((PrimitiveValue)sm.Fields[0]).Value);
 
1460
                                        if (sm.Fields.Length > 0 && (sm.Fields[0] is PrimitiveValue))
 
1461
                                                return ((PrimitiveValue)sm.Fields[0]).Value;
 
1462
                                } else if (sm.Type.FullName == "System.Decimal") {
 
1463
                                        SoftEvaluationContext ctx = (SoftEvaluationContext) gctx;
 
1464
                                        MethodMirror method = OverloadResolve (ctx, "GetBits", sm.Type, new TypeMirror[1] { sm.Type }, false, true, false);
 
1465
                                        if (method != null) {
 
1466
                                                ArrayMirror array;
 
1467
                                                
 
1468
                                                try {
 
1469
                                                        array = sm.Type.InvokeMethod (ctx.Thread, method, new Value[1] { sm }, InvokeOptions.DisableBreakpoints | InvokeOptions.SingleThreaded) as ArrayMirror;
 
1470
                                                } catch {
 
1471
                                                        array = null;
 
1472
                                                } finally {
 
1473
                                                        ctx.Session.StackVersion++;
 
1474
                                                }
 
1475
                                                
 
1476
                                                if (array != null) {
 
1477
                                                        int[] bits = new int [4];
 
1478
                                                        for (int i = 0; i < 4; i++)
 
1479
                                                                bits[i] = (int) TargetObjectToObject (gctx, array[i]);
 
1480
                                                        
 
1481
                                                        return new decimal (bits);
 
1482
                                                }
 
1483
                                        }
 
1484
                                }
1399
1485
                        }
1400
1486
                        return base.TargetObjectToObject (gctx, obj);
1401
1487
                }