Browse Source

Load debuggee metadata only once and cache it

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@2214 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
David Srbecký 19 years ago
parent
commit
4632b7aba4
  1. 12
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/Process.cs
  2. 100
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Types/DebugType.cs

12
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/Process.cs

@ -22,8 +22,6 @@ namespace Debugger
Thread selectedThread; Thread selectedThread;
PauseSession pauseSession; PauseSession pauseSession;
Dictionary<object, DebugType> debugTypeCache = new Dictionary<object, DebugType>();
bool hasExpired = false; bool hasExpired = false;
public event EventHandler Expired; public event EventHandler Expired;
@ -251,15 +249,5 @@ namespace Debugger
} }
} }
} }
internal DebugType GetDebugType(ICorDebugType corType)
{
DebugType type;
if (!debugTypeCache.TryGetValue(corType.WrappedObject, out type)) {
type = new DebugType(this, corType);
debugTypeCache.Add(corType.WrappedObject, type);
}
return type;
}
} }
} }

100
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Types/DebugType.cs

@ -14,8 +14,9 @@ namespace Debugger
{ {
/// <summary> /// <summary>
/// Represents a type in a debugee. That is, a class, array, value type or a primitive type. /// Represents a type in a debugee. That is, a class, array, value type or a primitive type.
/// <para> This class mimics the <see cref="System.Type"/> class. </para> /// This class mimics the <see cref="System.Type"/> class.
/// </summary> /// </summary>
/// <remarks> If two types are identical, the references to DebugType will also be identical </remarks>
public partial class DebugType: DebuggerObject public partial class DebugType: DebuggerObject
{ {
Process process; Process process;
@ -36,6 +37,9 @@ namespace Debugger
List<MethodInfo> methods = new List<MethodInfo>(); List<MethodInfo> methods = new List<MethodInfo>();
List<PropertyInfo> properties = new List<PropertyInfo>(); List<PropertyInfo> properties = new List<PropertyInfo>();
// Stores all DebugType instances. FullName is the key
static Dictionary<string, List<DebugType>> loadedTypes = new Dictionary<string, List<DebugType>>();
void AssertClassOrValueType() void AssertClassOrValueType()
{ {
if(!IsClass && !IsValueType) { if(!IsClass && !IsValueType) {
@ -213,7 +217,7 @@ namespace Debugger
} }
} }
internal DebugType(Process process, ICorDebugType corType) DebugType(Process process, ICorDebugType corType)
{ {
if (corType == null) throw new ArgumentNullException("corType"); if (corType == null) throw new ArgumentNullException("corType");
@ -225,8 +229,6 @@ namespace Debugger
this.corClass = corType.Class; this.corClass = corType.Class;
this.module = process.GetModule(corClass.Module); this.module = process.GetModule(corClass.Module);
this.classProps = module.MetaData.GetTypeDefProps(corClass.Token); this.classProps = module.MetaData.GetTypeDefProps(corClass.Token);
LoadType();
} }
if (this.IsClass || this.IsValueType || this.IsArray) { if (this.IsClass || this.IsValueType || this.IsArray) {
@ -238,12 +240,41 @@ namespace Debugger
this.fullName = GetFullName(); this.fullName = GetFullName();
} }
/// <summary> /// <summary> Obtains instance of DebugType. Same types will return identical instance. </summary>
/// Obtains instance of DebugType using process cache
/// </summary>
static internal DebugType Create(Process process, ICorDebugType corType) static internal DebugType Create(Process process, ICorDebugType corType)
{ {
return process.GetDebugType(corType); DateTime startTime = Util.HighPrecisionTimer.Now;
DebugType type = new DebugType(process, corType);
// Get types with matching names from cache
List<DebugType> typesWithMatchingName;
if (!loadedTypes.TryGetValue(type.FullName, out typesWithMatchingName)) {
// No types with such name - create a new list
typesWithMatchingName = new List<DebugType>(1);
loadedTypes.Add(type.FullName, typesWithMatchingName);
}
// Try to find the type
foreach(DebugType loadedType in typesWithMatchingName) {
if (loadedType.Equals(type)) {
TimeSpan totalTime = Util.HighPrecisionTimer.Now - startTime;
//process.TraceMessage("Type " + type.FullName + " was loaded already (" + totalTime.TotalMilliseconds + " ms)");
return loadedType; // Type was loaded before
}
}
// The type is not in the cache, finish loading it and add it to the cache
if (type.IsClass || type.IsValueType) {
type.LoadMemberInfo();
}
typesWithMatchingName.Add(type);
type.Process.Expired += delegate { typesWithMatchingName.Remove(type); };
TimeSpan totalTime2 = Util.HighPrecisionTimer.Now - startTime;
process.TraceMessage("Loaded type " + type.FullName + " (" + totalTime2.TotalMilliseconds + " ms)");
return type;
} }
string GetFullName() string GetFullName()
@ -269,31 +300,8 @@ namespace Debugger
} }
} }
/// <summary> Determines whether the current type is sublass of void LoadMemberInfo()
/// the the given type. That is, it derives from the given type. </summary>
/// <remarks> Returns false if the given type is same as the current type </remarks>
public bool IsSubclassOf(DebugType superType)
{
DebugType type = this.BaseType;
while (type != null) {
if (type.Equals(superType)) return true;
type = type.BaseType;
}
return false;
}
/// <summary> Determines whether the given object is instance of the
/// current type or can be implicitly cast to it </summary>
public bool IsInstanceOfType(Value objectInstance)
{
return objectInstance.Type.Equals(this) ||
objectInstance.Type.IsSubclassOf(this);
}
void LoadType()
{ {
DateTime startTime = Util.HighPrecisionTimer.Now;
// Load fields // Load fields
foreach(FieldProps field in module.MetaData.EnumFields(this.MetadataToken)) { foreach(FieldProps field in module.MetaData.EnumFields(this.MetadataToken)) {
if (field.IsStatic && field.IsLiteral) continue; // Skip static literals TODO: Why? if (field.IsStatic && field.IsLiteral) continue; // Skip static literals TODO: Why?
@ -324,9 +332,27 @@ namespace Debugger
accessors.TryGetValue("set_" + kvp.Key, out setter); accessors.TryGetValue("set_" + kvp.Key, out setter);
properties.Add(new PropertyInfo(this, getter, setter)); properties.Add(new PropertyInfo(this, getter, setter));
} }
}
TimeSpan totalTime = Util.HighPrecisionTimer.Now - startTime; /// <summary> Determines whether the current type is sublass of
process.TraceMessage("Loaded type " + this.FullName + " (" + totalTime.TotalMilliseconds + " ms)"); /// the the given type. That is, it derives from the given type. </summary>
/// <remarks> Returns false if the given type is same as the current type </remarks>
public bool IsSubclassOf(DebugType superType)
{
DebugType type = this.BaseType;
while (type != null) {
if (type.Equals(superType)) return true;
type = type.BaseType;
}
return false;
}
/// <summary> Determines whether the given object is instance of the
/// current type or can be implicitly cast to it </summary>
public bool IsInstanceOfType(Value objectInstance)
{
return objectInstance.Type.Equals(this) ||
objectInstance.Type.IsSubclassOf(this);
} }
/// <summary> Return all public fields.</summary> /// <summary> Return all public fields.</summary>
@ -369,9 +395,11 @@ namespace Debugger
public override bool Equals(object obj) public override bool Equals(object obj)
{ {
DebugType other = obj as DebugType; DebugType other = obj as DebugType;
if (other != null) { if (other != null && this.Process == other.Process) {
if (this.IsArray) { if (this.IsArray) {
throw new NotImplementedException(); // TODO return other.IsArray &&
other.GetArrayRank() == this.GetArrayRank() &&
other.GetElementType().Equals(this.GetElementType());
} }
if (this.IsPrimitive) { if (this.IsPrimitive) {
return other.IsPrimitive && return other.IsPrimitive &&

Loading…
Cancel
Save