Browse Source

Guarantee type identity if names are equal

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@5168 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
David Srbecký 16 years ago
parent
commit
aa57ee9b77
  1. 35
      src/AddIns/Misc/Debugger/Debugger.Core/AppDomain.cs
  2. 162
      src/AddIns/Misc/Debugger/Debugger.Core/MetaData/DebugType.cs
  3. 2
      src/AddIns/Misc/Debugger/Debugger.Core/Module.cs
  4. 4
      src/AddIns/Misc/Debugger/Debugger.Core/NRefactory/Visitors/ExpressionEvaluator.cs
  5. 4
      src/AddIns/Misc/Debugger/Debugger.Core/Process.cs
  6. 2
      src/AddIns/Misc/Debugger/Debugger.Tests/Tests/ExpressionEvaluator_Tests.cs

35
src/AddIns/Misc/Debugger/Debugger.Core/AppDomain.cs

@ -6,8 +6,9 @@ @@ -6,8 +6,9 @@
// </file>
using System;
using Debugger.MetaData;
using Debugger.Interop.CorDebug;
using Debugger.MetaData;
using System.Collections.Generic;
namespace Debugger
{
@ -17,6 +18,8 @@ namespace Debugger @@ -17,6 +18,8 @@ namespace Debugger
ICorDebugAppDomain corAppDomain;
internal Dictionary<ICorDebugType, DebugType> DebugTypeCache = new Dictionary<ICorDebugType, DebugType>();
public Process Process {
get { return process; }
}
@ -43,34 +46,8 @@ namespace Debugger @@ -43,34 +46,8 @@ namespace Debugger
}
}
DebugType objectType;
public DebugType ObjectType {
get {
if (objectType == null)
objectType = DebugType.CreateFromType(this.Mscorlib, typeof(object));
return objectType;
}
}
DebugType valueType;
public DebugType ValueType {
get {
if (valueType == null)
valueType = DebugType.CreateFromType(this.Mscorlib, typeof(ValueType));
return valueType;
}
}
DebugType voidType;
public DebugType VoidType {
get {
if (voidType == null)
voidType = DebugType.CreateFromType(this.Mscorlib, typeof(void));
return voidType;
}
internal DebugType ObjectType {
get { return DebugType.CreateFromType(this.Mscorlib, typeof(object)); }
}
internal ICorDebugAppDomain CorAppDomain {

162
src/AddIns/Misc/Debugger/Debugger.Core/MetaData/DebugType.cs

@ -50,9 +50,6 @@ namespace Debugger.MetaData @@ -50,9 +50,6 @@ namespace Debugger.MetaData
Dictionary<string, List<MemberInfo>> membersByName = new Dictionary<string, List<MemberInfo>>();
Dictionary<int, MemberInfo> membersByToken = new Dictionary<int, MemberInfo>();
// Stores all DebugType instances. FullName is the key
static Dictionary<ICorDebugType, DebugType> loadedTypes = new Dictionary<ICorDebugType, DebugType>();
internal ICorDebugType CorType {
get { return corType; }
}
@ -702,7 +699,7 @@ namespace Debugger.MetaData @@ -702,7 +699,7 @@ namespace Debugger.MetaData
// ValueType and Enum are exceptions and are threated as classes
return this.FullName != typeof(ValueType).FullName &&
this.FullName != typeof(Enum).FullName &&
this.IsSubclassOf(this.AppDomain.ValueType);
this.IsSubclassOf(DebugType.CreateFromType(this.AppDomain.Mscorlib, typeof(ValueType)));
}
/// <inheritdoc/>
@ -840,6 +837,9 @@ namespace Debugger.MetaData @@ -840,6 +837,9 @@ namespace Debugger.MetaData
if (type.GetGenericArguments().Length > 0)
throw new DebuggerException("Generic arguments not allowed in this overload");
if (module.LoadedDebugTypes.ContainsKey(type.FullName))
return module.LoadedDebugTypes[type.FullName];
DebugType declaringType = null;
if (type.DeclaringType != null)
declaringType = CreateFromType(module, type.DeclaringType);
@ -929,13 +929,8 @@ namespace Debugger.MetaData @@ -929,13 +929,8 @@ namespace Debugger.MetaData
internal static DebugType CreateFromSignature(Module module, SigType sigType, DebugType declaringType)
{
System.Type sysType = CorElementTypeToManagedType((CorElementType)(uint)sigType.ElementType);
if (sysType != null) {
if (sysType != null)
return CreateFromType(module.AppDomain.Mscorlib, sysType);
}
if (sigType.ElementType == Mono.Cecil.Metadata.ElementType.Object) {
return module.AppDomain.ObjectType;
}
if (sigType is CLASS) {
return CreateFromTypeDefOrRef(module, false, ((CLASS)sigType).Type.ToUInt(), null);
@ -983,7 +978,7 @@ namespace Debugger.MetaData @@ -983,7 +978,7 @@ namespace Debugger.MetaData
PTR ptrSig = (PTR)sigType;
DebugType elementType;
if (ptrSig.Void) {
elementType = module.AppDomain.VoidType;
elementType = DebugType.CreateFromType(module.AppDomain.Mscorlib, typeof(void));
} else {
elementType = CreateFromSignature(module, ptrSig.PtrType, declaringType);
}
@ -1064,33 +1059,40 @@ namespace Debugger.MetaData @@ -1064,33 +1059,40 @@ namespace Debugger.MetaData
/// <summary> Obtains instance of DebugType. Same types will return identical instance. </summary>
public static DebugType CreateFromCorType(AppDomain appDomain, ICorDebugType corType)
{
// Convert primitive type to class
CorElementType corElemType = (CorElementType)(corType.GetTheType());
Type primitiveType = CorElementTypeToManagedType(corElemType);
if (appDomain.DebugTypeCache.ContainsKey(corType))
return appDomain.DebugTypeCache[corType];
// Convert short-form to class-form
Type primitiveType = CorElementTypeToManagedType((CorElementType)(corType.GetTheType()));
if (primitiveType != null) {
corType = CreateFromType(appDomain.Mscorlib, primitiveType).CorType;
}
if (corElemType == CorElementType.VOID) {
corType = appDomain.VoidType.CorType;
DebugType type = CreateFromType(appDomain.Mscorlib, primitiveType);
// Use cache next time
appDomain.DebugTypeCache[corType] = type;
return type;
} else {
DebugType type = new DebugType(appDomain, corType);
// Ensure name-identity
if (type.DebugModule.LoadedDebugTypes.ContainsKey(type.FullName)) {
type = type.DebugModule.LoadedDebugTypes[type.FullName];
// corDebug cache needs to be fixed to this type - we do not want the semi-loaded type there
appDomain.DebugTypeCache[corType] = type;
} else {
type.LoadMembers();
type.DebugModule.LoadedDebugTypes[type.FullName] = type;
}
return type;
}
if (loadedTypes.ContainsKey(corType)) return loadedTypes[corType];
return new DebugType(appDomain, corType);
}
DebugType(AppDomain appDomain, ICorDebugType corType)
{
if (corType == null) throw new ArgumentNullException("corType");
System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
stopwatch.Start();
this.corType = corType;
this.corElementType = (CorElementType)corType.GetTheType();
// Loading might access the type again
loadedTypes[corType] = this;
appDomain.Process.Exited += delegate { loadedTypes.Remove(corType); };
appDomain.DebugTypeCache[corType] = this;
if (corElementType == CorElementType.ARRAY ||
corElementType == CorElementType.SZARRAY ||
@ -1110,12 +1112,9 @@ namespace Debugger.MetaData @@ -1110,12 +1112,9 @@ namespace Debugger.MetaData
this.ns = this.GetElementType().Namespace;
this.name = this.GetElementType().Name + suffix;
this.fullName = this.GetElementType().FullName + suffix;
if (corElementType == CorElementType.ARRAY || corElementType == CorElementType.SZARRAY)
LoadArrayMembers();
}
if (corElementType == CorElementType.OBJECT ||
corElementType == CorElementType.CLASS ||
if (corElementType == CorElementType.CLASS ||
corElementType == CorElementType.VALUETYPE)
{
// Get generic arguments
@ -1140,21 +1139,11 @@ namespace Debugger.MetaData @@ -1140,21 +1139,11 @@ namespace Debugger.MetaData
this.name = classProps.Name.Substring(index + 1);
}
this.fullName = GetFullClassName();
this.primitiveType = NameToManagedType(this.FullName);
LoadMembers();
this.primitiveType = GetPrimitiveType(this.FullName);
}
if (module == null)
throw new DebuggerException("Unexpected: " + corElementType);
stopwatch.Stop();
if (appDomain.Process.Options.Verbose) {
string prefix = this.IsInterface ? "interface" : "type";
appDomain.Process.TraceMessage("Loaded {0} {1} ({2} ms)", prefix, this.FullName, stopwatch.ElapsedMilliseconds);
foreach(DebugType inter in GetInterfaces()) {
appDomain.Process.TraceMessage(" - Implements {0}", inter.FullName);
}
}
}
internal static Type CorElementTypeToManagedType(CorElementType corElementType)
@ -1175,11 +1164,13 @@ namespace Debugger.MetaData @@ -1175,11 +1164,13 @@ namespace Debugger.MetaData
case CorElementType.I: return typeof(System.IntPtr);
case CorElementType.U: return typeof(System.UIntPtr);
case CorElementType.STRING: return typeof(System.String);
case CorElementType.OBJECT: return typeof(System.Object);
case CorElementType.VOID: return typeof(void);
default: return null;
}
}
static Type NameToManagedType(string fullname)
static Type GetPrimitiveType(string fullname)
{
switch (fullname) {
case "System.Boolean": return typeof(System.Boolean);
@ -1194,6 +1185,7 @@ namespace Debugger.MetaData @@ -1194,6 +1185,7 @@ namespace Debugger.MetaData
case "System.UInt64": return typeof(System.UInt64);
case "System.Single": return typeof(System.Single);
case "System.Double": return typeof(System.Double);
// String is not primitive type
default: return null;
}
}
@ -1226,52 +1218,56 @@ namespace Debugger.MetaData @@ -1226,52 +1218,56 @@ namespace Debugger.MetaData
return name.ToString();
}
void LoadArrayMembers()
{
// Arrays are special and normal loading does not work for them
DebugType iList = DebugType.CreateFromName(this.AppDomain.Mscorlib, typeof(IList<>).FullName, null, new DebugType[] { (DebugType)this.GetElementType() });
this.interfaces.Add(iList);
this.interfaces.AddRange(iList.interfaces);
}
void LoadMembers()
{
// Load interfaces
foreach(InterfaceImplProps implProps in module.MetaData.EnumInterfaceImplProps((uint)this.MetadataToken)) {
CorTokenType tkType = (CorTokenType)(implProps.Interface & 0xFF000000);
if (tkType == CorTokenType.TypeDef || tkType == CorTokenType.TypeRef) {
this.interfaces.Add(DebugType.CreateFromTypeDefOrRef(module, false, implProps.Interface, null));
} else if (tkType == CorTokenType.TypeSpec) {
this.interfaces.Add(DebugType.CreateFromTypeSpec(module, implProps.Interface, this));
} else {
throw new DebuggerException("Uknown token type for interface: " + tkType);
}
}
// Load fields
foreach(FieldProps field in module.MetaData.EnumFieldProps((uint)this.MetadataToken)) {
DebugFieldInfo fieldInfo = new DebugFieldInfo(this, field);
AddMember(fieldInfo);
};
System.Diagnostics.Stopwatch stopwatch = System.Diagnostics.Stopwatch.StartNew();
// Load methods
foreach(MethodProps m in module.MetaData.EnumMethodProps((uint)this.MetadataToken)) {
AddMember(new DebugMethodInfo(this, m));
if (corElementType == CorElementType.ARRAY || corElementType == CorElementType.SZARRAY) {
// Arrays are special and normal loading does not work for them
DebugType iList = DebugType.CreateFromName(this.AppDomain.Mscorlib, typeof(IList<>).FullName, null, new DebugType[] { (DebugType)this.GetElementType() });
this.interfaces.Add(iList);
this.interfaces.AddRange(iList.interfaces);
} else {
// Load interfaces
foreach(InterfaceImplProps implProps in module.MetaData.EnumInterfaceImplProps((uint)this.MetadataToken)) {
CorTokenType tkType = (CorTokenType)(implProps.Interface & 0xFF000000);
if (tkType == CorTokenType.TypeDef || tkType == CorTokenType.TypeRef) {
this.interfaces.Add(DebugType.CreateFromTypeDefOrRef(module, false, implProps.Interface, null));
} else if (tkType == CorTokenType.TypeSpec) {
this.interfaces.Add(DebugType.CreateFromTypeSpec(module, implProps.Interface, this));
} else {
throw new DebuggerException("Uknown token type for interface: " + tkType);
}
}
// Load fields
foreach(FieldProps field in module.MetaData.EnumFieldProps((uint)this.MetadataToken)) {
DebugFieldInfo fieldInfo = new DebugFieldInfo(this, field);
AddMember(fieldInfo);
};
// Load methods
foreach(MethodProps m in module.MetaData.EnumMethodProps((uint)this.MetadataToken)) {
AddMember(new DebugMethodInfo(this, m));
}
// Load properties
foreach(PropertyProps prop in module.MetaData.EnumPropertyProps((uint)this.MetadataToken)) {
DebugPropertyInfo propInfo = new DebugPropertyInfo(
this,
prop.GetterMethod != 0x06000000 ? GetMethod(prop.GetterMethod) : null,
prop.SetterMethod != 0x06000000 ? GetMethod(prop.SetterMethod) : null
);
if (propInfo.GetGetMethod() != null)
((DebugMethodInfo)propInfo.GetGetMethod()).IsPropertyAccessor = true;
if (propInfo.GetSetMethod() != null)
((DebugMethodInfo)propInfo.GetSetMethod()).IsPropertyAccessor = true;
AddMember(propInfo);
}
}
// Load properties
foreach(PropertyProps prop in module.MetaData.EnumPropertyProps((uint)this.MetadataToken)) {
DebugPropertyInfo propInfo = new DebugPropertyInfo(
this,
prop.GetterMethod != 0x06000000 ? GetMethod(prop.GetterMethod) : null,
prop.SetterMethod != 0x06000000 ? GetMethod(prop.SetterMethod) : null
);
if (propInfo.GetGetMethod() != null)
((DebugMethodInfo)propInfo.GetGetMethod()).IsPropertyAccessor = true;
if (propInfo.GetSetMethod() != null)
((DebugMethodInfo)propInfo.GetSetMethod()).IsPropertyAccessor = true;
AddMember(propInfo);
}
if (this.Process.Options.Verbose)
this.Process.TraceMessage("Loaded {0} ({1} ms)", this.FullName, stopwatch.ElapsedMilliseconds);
}
void AddMember(MemberInfo member)

2
src/AddIns/Misc/Debugger/Debugger.Core/Module.cs

@ -28,6 +28,8 @@ namespace Debugger @@ -28,6 +28,8 @@ namespace Debugger
ISymUnmanagedReader symReader;
MetaDataImport metaData;
internal Dictionary<string, DebugType> LoadedDebugTypes = new Dictionary<string, DebugType>();
public event EventHandler<ModuleEventArgs> SymbolsLoaded;
protected virtual void OnSymbolsLoaded(ModuleEventArgs e)

4
src/AddIns/Misc/Debugger/Debugger.Core/NRefactory/Visitors/ExpressionEvaluator.cs

@ -172,7 +172,7 @@ namespace ICSharpCode.NRefactory.Visitors @@ -172,7 +172,7 @@ namespace ICSharpCode.NRefactory.Visitors
// Try to get the value from cache
// (the cache is cleared when the process is resumed)
TypedValue val;
if (context.Process.CachedExpressions.TryGetValue(expression, out val)) {
if (context.Process.ExpressionsCache.TryGetValue(expression, out val)) {
if (val == null || !val.Value.IsInvalid)
return val;
}
@ -197,7 +197,7 @@ namespace ICSharpCode.NRefactory.Visitors @@ -197,7 +197,7 @@ namespace ICSharpCode.NRefactory.Visitors
throw new DebuggerException("Expression \"" + expression.PrettyPrint() + "\" is invalid right after evaluation");
// Add the result to cache
context.Process.CachedExpressions[expression] = val;
context.Process.ExpressionsCache[expression] = val;
return val;
}

4
src/AddIns/Misc/Debugger/Debugger.Core/Process.cs

@ -215,7 +215,7 @@ namespace Debugger @@ -215,7 +215,7 @@ namespace Debugger
internal bool TerminateCommandIssued = false;
internal Queue<Breakpoint> BreakpointHitEventQueue = new Queue<Breakpoint>();
internal Dictionary<INode, TypedValue> CachedExpressions = new Dictionary<INode, TypedValue>();
internal Dictionary<INode, TypedValue> ExpressionsCache = new Dictionary<INode, TypedValue>();
#region Events
@ -295,7 +295,7 @@ namespace Debugger @@ -295,7 +295,7 @@ namespace Debugger
if (action == DebuggeeStateAction.Clear) {
if (debuggeeState == null) throw new DebuggerException("Debugee state already cleared");
debuggeeState = null;
this.CachedExpressions.Clear();
this.ExpressionsCache.Clear();
}
}

2
src/AddIns/Misc/Debugger/Debugger.Tests/Tests/ExpressionEvaluator_Tests.cs

@ -413,7 +413,7 @@ namespace Debugger.Tests { @@ -413,7 +413,7 @@ namespace Debugger.Tests {
<Eval> </Eval>
<TypeResulution> typeof(System.Int32*[][,]) = System.Int32*[,][] (ok)</TypeResulution>
<TypeResulution> typeof(Debugger.Tests.ExpressionEvaluator_Tests.A&lt;System.Int32&gt;.B.C&lt;System.Char&gt;[][,]) = Debugger.Tests.ExpressionEvaluator_Tests+A`1+B+C`1[System.Int32,System.Char][,][] (ok)</TypeResulution>
<TypesIdentitcal>False</TypesIdentitcal>
<TypesIdentitcal>True</TypesIdentitcal>
<TypesEqual>True</TypesEqual>
<ProcessExited />
</Test>

Loading…
Cancel
Save