Browse Source

Type caching simplified;

Fixed a bug for AppDomains - the AppDomain for threads can change

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@4521 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
David Srbecký 17 years ago
parent
commit
ac76eaa009
  1. 18
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/StackFrame.cs
  2. 14
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Thread.cs
  3. 2
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Internal/ManagedCallback.cs
  4. 14
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Metadata/DebugType-Helpers.cs
  5. 118
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Metadata/DebugType.cs
  6. 4
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Wrappers/CorDebug/Autogenerated/ICorDebugType.cs
  7. 3
      src/AddIns/Misc/Debugger/Debugger.Tests/Project/Debugger.Tests.csproj
  8. 82
      src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/AppDomains.cs

18
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/StackFrame.cs

@ -5,13 +5,15 @@ @@ -5,13 +5,15 @@
// <version>$Revision$</version>
// </file>
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Debugger.MetaData;
using Debugger.Expressions;
using Debugger.MetaData;
using Debugger.Wrappers.CorDebug;
using Debugger.Wrappers.CorSym;
using Debugger.Wrappers.MetaData;
namespace Debugger
{
@ -22,6 +24,7 @@ namespace Debugger @@ -22,6 +24,7 @@ namespace Debugger
public class StackFrame: DebuggerObject
{
Thread thread;
AppDomain appDomain;
Process process;
ICorDebugILFrame corILFrame;
@ -35,7 +38,7 @@ namespace Debugger @@ -35,7 +38,7 @@ namespace Debugger
/// <summary> The process in which this stack frame is executed </summary>
[Debugger.Tests.Ignore]
public AppDomain AppDomain {
get { return thread.AppDomain; }
get { return appDomain; }
}
[Debugger.Tests.Ignore]
@ -91,16 +94,21 @@ namespace Debugger @@ -91,16 +94,21 @@ namespace Debugger
{
this.process = thread.Process;
this.thread = thread;
this.appDomain = process.AppDomains[corILFrame.Function.Class.Module.Assembly.AppDomain];
this.corILFrame = corILFrame;
this.corILFramePauseSession = process.PauseSession;
this.corFunction = corILFrame.Function;
this.chainIndex = chainIndex;
this.frameIndex = frameIndex;
MetaDataImport metaData = thread.Process.Modules[corFunction.Class.Module].MetaData;
ICorDebugType[] genArgs = corILFrame.CastTo<ICorDebugILFrame2>().EnumerateTypeParameters().ToList().ToArray();
Array.Resize(ref genArgs, metaData.GetGenericParamCount(corFunction.Class.Token));
DebugType debugType = DebugType.Create(
this.AppDomain,
corFunction.Class,
corILFrame.CastTo<ICorDebugILFrame2>().EnumerateTypeParameters().ToList().ToArray()
genArgs
);
this.methodInfo = debugType.GetMethod(corFunction.Token);
}
@ -266,7 +274,7 @@ namespace Debugger @@ -266,7 +274,7 @@ namespace Debugger
/// </summary>
public Value GetThisValue()
{
return new Value(thread.AppDomain, new ThisReferenceExpression(), GetThisCorValue());
return new Value(appDomain, new ThisReferenceExpression(), GetThisCorValue());
}
ICorDebugValue GetThisCorValue()
@ -303,7 +311,7 @@ namespace Debugger @@ -303,7 +311,7 @@ namespace Debugger
/// <param name="index"> Zero-based index </param>
public Value GetArgumentValue(int index)
{
return new Value(thread.AppDomain, new ParameterIdentifierExpression(this.MethodInfo, index), GetArgumentCorValue(index));
return new Value(appDomain, new ParameterIdentifierExpression(this.MethodInfo, index), GetArgumentCorValue(index));
}
ICorDebugValue GetArgumentCorValue(int index)

14
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Thread.cs

@ -17,7 +17,7 @@ namespace Debugger @@ -17,7 +17,7 @@ namespace Debugger
{
public partial class Thread: DebuggerObject
{
AppDomain appDomain;
// AppDomain for thread can be changing
Process process;
uint id;
@ -37,11 +37,6 @@ namespace Debugger @@ -37,11 +37,6 @@ namespace Debugger
public event EventHandler<ThreadEventArgs> NameChanged;
public event EventHandler<ThreadEventArgs> Exited;
[Debugger.Tests.Ignore]
public AppDomain AppDomain {
get { return appDomain; }
}
[Debugger.Tests.Ignore]
public Process Process {
get { return process; }
@ -88,10 +83,9 @@ namespace Debugger @@ -88,10 +83,9 @@ namespace Debugger
}
}
internal Thread(AppDomain appDomain, ICorDebugThread corThread)
internal Thread(Process process, ICorDebugThread corThread)
{
this.appDomain = appDomain;
this.process = appDomain.Process;
this.process = process;
this.corThread = corThread;
this.id = CorThread.ID;
}
@ -166,7 +160,7 @@ namespace Debugger @@ -166,7 +160,7 @@ namespace Debugger
process.AssertPaused();
ICorDebugValue corValue = this.CorThread.Object;
return new Value(appDomain, new EmptyExpression(), corValue);
return new Value(process.AppDomains[this.CorThread.AppDomain], new EmptyExpression(), corValue);
}
}

2
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Internal/ManagedCallback.cs

@ -367,7 +367,7 @@ namespace Debugger @@ -367,7 +367,7 @@ namespace Debugger
// and we continue from this callback anyway
EnterCallback(PausedReason.Other, "CreateThread " + pThread.ID, pAppDomain);
process.Threads.Add(new Thread(process.AppDomains[pAppDomain], pThread));
process.Threads.Add(new Thread(process, pThread));
ExitCallback();
}

14
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Metadata/DebugType-Helpers.cs

@ -297,23 +297,23 @@ namespace Debugger.MetaData @@ -297,23 +297,23 @@ namespace Debugger.MetaData
#endregion
private bool primitiveTypeCached = false;
private System.Type primitiveTypeCache;
private bool primitiveTypeCached;
private System.Type primitiveType;
/// <summary> Returns simple managed type coresponding to the primitive type. </summary>
[Tests.Ignore]
public System.Type PrimitiveType {
get {
if (!this.primitiveTypeCached) {
this.primitiveTypeCache = getPrimitiveType();
this.primitiveTypeCached = true;
if (!primitiveTypeCached) {
primitiveTypeCached = true;
primitiveType = GetPrimitiveType();
}
return this.primitiveTypeCache;
return primitiveType;
}
}
/// <summary> Returns simple managed type coresponding to the primitive type. </summary>
private System.Type getPrimitiveType()
private System.Type GetPrimitiveType()
{
if (corElementType == CorElementType.VALUETYPE) {
CorElementType corType;

118
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Metadata/DebugType.cs

@ -45,7 +45,7 @@ namespace Debugger.MetaData @@ -45,7 +45,7 @@ namespace Debugger.MetaData
List<MemberInfo> members = new List<MemberInfo>();
// Stores all DebugType instances. FullName is the key
static Dictionary<string, List<DebugType>> loadedTypes = new Dictionary<string, List<DebugType>>();
static Dictionary<ICorDebugType, DebugType> loadedTypes = new Dictionary<ICorDebugType, DebugType>();
void AssertClassOrValueType()
{
@ -66,9 +66,7 @@ namespace Debugger.MetaData @@ -66,9 +66,7 @@ namespace Debugger.MetaData
}
internal ICorDebugType CorType {
get {
return corType;
}
get { return corType; }
}
/// <summary>
@ -102,9 +100,7 @@ namespace Debugger.MetaData @@ -102,9 +100,7 @@ namespace Debugger.MetaData
/// <summary> Returns a string describing the type including the namespace
/// and generic arguments but excluding the assembly name. </summary>
public string FullName {
get {
return fullName;
}
get { return fullName; }
}
/// <summary> Returns the number of dimensions of an array </summary>
@ -118,9 +114,7 @@ namespace Debugger.MetaData @@ -118,9 +114,7 @@ namespace Debugger.MetaData
/// <summary> Gets a list of all interfaces that this type implements </summary>
public List<DebugType> Interfaces {
get {
return interfaces;
}
get { return interfaces; }
}
/// <summary> Return an interface with the given name </summary>
@ -290,16 +284,6 @@ namespace Debugger.MetaData @@ -290,16 +284,6 @@ namespace Debugger.MetaData
}
}
internal uint? AppDomainID {
get {
if (IsClass || IsValueType) {
return this.Module.AppDomainID;
} else {
return null;
}
}
}
/// <summary>
/// Gets the type from which this type inherits.
/// <para>
@ -356,11 +340,6 @@ namespace Debugger.MetaData @@ -356,11 +340,6 @@ namespace Debugger.MetaData
this.name = GetName(false);
}
public static DebugType Create(Module module, uint token)
{
return Create(module, token, null);
}
public static DebugType Create(Module module, uint token, DebugType declaringType)
{
CorTokenType tokenType = (CorTokenType)(token & 0xFF000000);
@ -374,11 +353,6 @@ namespace Debugger.MetaData @@ -374,11 +353,6 @@ namespace Debugger.MetaData
}
}
public static DebugType Create(Module module, byte[] sig)
{
return Create(module, sig, null);
}
/// <param name="signatureContext">Type definition to use to resolve numbered generic references</param>
public static DebugType Create(Module module, byte[] sig, DebugType declaringType)
{
@ -478,7 +452,7 @@ namespace Debugger.MetaData @@ -478,7 +452,7 @@ namespace Debugger.MetaData
throw new DebuggerException("Can not find type " + fullTypeName);
}
static public DebugType Create(AppDomain appDomain, ICorDebugClass corClass, params ICorDebugType[] typeArguments)
static public DebugType Create(AppDomain appDomain, ICorDebugClass corClass, params ICorDebugType[] genericArguments)
{
MetaDataImport metaData = appDomain.Process.Modules[corClass.Module].MetaData;
@ -495,12 +469,13 @@ namespace Debugger.MetaData @@ -495,12 +469,13 @@ namespace Debugger.MetaData
}
}
int getArgsCount = metaData.GetGenericParamCount(corClass.Token);
if (genericArguments.Length != metaData.GetGenericParamCount(corClass.Token)) {
throw new DebuggerException("Incorrect number of generic arguments");
}
Array.Resize(ref typeArguments, getArgsCount);
ICorDebugType corType = corClass.CastTo<ICorDebugClass2>().GetParameterizedType(
isValueType ? (uint)CorElementType.VALUETYPE : (uint)CorElementType.CLASS,
typeArguments
genericArguments
);
return Create(appDomain, corType);
@ -509,41 +484,23 @@ namespace Debugger.MetaData @@ -509,41 +484,23 @@ namespace Debugger.MetaData
/// <summary> Obtains instance of DebugType. Same types will return identical instance. </summary>
static public DebugType Create(AppDomain appDomain, ICorDebugType corType)
{
if (loadedTypes.ContainsKey(corType)) return loadedTypes[corType];
DateTime startTime = Util.HighPrecisionTimer.Now;
DebugType type = new DebugType(appDomain, 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);
}
// Loading of memebers might access the type again
loadedTypes[corType] = type;
// Try to find the type
foreach(DebugType loadedType in typesWithMatchingName) {
if (loadedType.Equals(type)) {
TimeSpan totalTime = Util.HighPrecisionTimer.Now - startTime;
if (appDomain.Process.Options.Verbose) {
appDomain.Process.TraceMessage("Type " + type.FullName + " was loaded already (" + totalTime.TotalMilliseconds + " ms)");
}
return loadedType; // Type was loaded before
}
}
// This has to be done before LoadMemberInfo since it might use it
typesWithMatchingName.Add(type);
// The type is not in the cache, finish loading it and add it to the cache
if (type.IsClass || type.IsValueType) {
type.LoadMemberInfo();
}
type.AppDomain.Process.Exited += delegate { typesWithMatchingName.Remove(type); };
type.AppDomain.Process.Exited += delegate { loadedTypes.Remove(corType); };
TimeSpan totalTime2 = Util.HighPrecisionTimer.Now - startTime;
string prefix = type.IsInterface ? "interface" : "type";
if (appDomain.Process.Options.Verbose) {
string prefix = type.IsInterface ? "interface" : "type";
appDomain.Process.TraceMessage("Loaded {0} {1} ({2} ms)", prefix, type.FullName, totalTime2.TotalMilliseconds);
foreach(DebugType inter in type.Interfaces) {
appDomain.Process.TraceMessage(" - Implements {0}", inter.FullName);
@ -554,13 +511,13 @@ namespace Debugger.MetaData @@ -554,13 +511,13 @@ namespace Debugger.MetaData
}
/// <summary> Returns all non-generic types defined in the given module </summary>
/// <remarks> Generic types can not be returned, because we do not how to instanciate them </remarks>
public static List<DebugType> GetDefinedTypesInModule(Module module)
{
// TODO: Generic types
List<DebugType> types = new List<DebugType>();
foreach(TypeDefProps typeDef in module.MetaData.EnumTypeDefProps()) {
if (module.MetaData.GetGenericParamCount(typeDef.Token) == 0) {
types.Add(DebugType.Create(module, typeDef.Token));
types.Add(DebugType.Create(module, typeDef.Token, null));
}
}
return types;
@ -685,48 +642,9 @@ namespace Debugger.MetaData @@ -685,48 +642,9 @@ namespace Debugger.MetaData
return (GetMembers(bindingFlags).Count > 0);
}
/// <summary> Compares two types </summary>
public override bool Equals(object obj)
{
DebugType other = obj as DebugType;
if (other != null && this.AppDomain == other.AppDomain) {
if (this.IsArray) {
return other.IsArray &&
other.GetArrayRank() == this.GetArrayRank() &&
other.ElementType.Equals(this.ElementType);
}
if (this.IsPrimitive) {
return other.IsPrimitive &&
other.PrimitiveType == this.PrimitiveType &&
other.IsValueType == this.IsValueType;
}
if (this.IsClass || this.IsValueType) {
return (other.IsClass || other.IsValueType) &&
other.Module == this.Module &&
other.Token == this.Token;
}
if (this.IsPointer) {
return other.IsPointer &&
other.ElementType.Equals(this.ElementType);
}
if (this.IsVoid) {
return other.IsVoid;
}
throw new DebuggerException("Unknown type");
} else {
return false;
}
}
/// <summary> Get hash code of the object </summary>
public override int GetHashCode()
{
return base.GetHashCode();
}
public override string ToString()
{
return string.Format("{0}", this.fullName);
return string.Format("{0}", this.FullName);
}
}
}

4
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Wrappers/CorDebug/Autogenerated/ICorDebugType.cs

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
// <file>
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
@ -85,7 +85,7 @@ namespace Debugger.Wrappers.CorDebug @@ -85,7 +85,7 @@ namespace Debugger.Wrappers.CorDebug
public override int GetHashCode()
{
return base.GetHashCode();
return wrappedObject.GetHashCode();
}
public override bool Equals(object o)

3
src/AddIns/Misc/Debugger/Debugger.Tests/Project/Debugger.Tests.csproj

@ -42,6 +42,7 @@ @@ -42,6 +42,7 @@
<Compile Include="Configuration\AssemblyInfo.cs" />
<Compile Include="Src\DebuggerTests.cs" />
<Compile Include="Src\DebuggerTestsBase.cs" />
<Compile Include="Src\TestPrograms\AppDomains.cs" />
<Compile Include="Src\TestPrograms\ArrayValue.cs" />
<Compile Include="Src\TestPrograms\AstEval.cs" />
<Compile Include="Src\TestPrograms\Break.cs" />
@ -99,4 +100,4 @@ @@ -99,4 +100,4 @@
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" />
</Project>
</Project>

82
src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/AppDomains.cs

@ -0,0 +1,82 @@ @@ -0,0 +1,82 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbeck<EFBFBD>" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
namespace Debugger.Tests.TestPrograms
{
public class AppDomains
{
public static void Main()
{
int one = 1;
System.Diagnostics.Debugger.Break();
System.AppDomain appDomain = System.AppDomain.CreateDomain("myDomain");
RemoteObj printer = (RemoteObj)appDomain.CreateInstanceAndUnwrap(typeof(RemoteObj).Assembly.FullName, typeof(RemoteObj).FullName);
printer.Foo();
}
}
public class RemoteObj: MarshalByRefObject
{
public void Foo()
{
int two = 2;
string appDomainName = System.AppDomain.CurrentDomain.FriendlyName + " Id=" + System.AppDomain.CurrentDomain.Id;
System.Diagnostics.Debugger.Break();
}
}
}
#if TEST_CODE
namespace Debugger.Tests {
using Debugger.MetaData;
public partial class DebuggerTests
{
[NUnit.Framework.Test]
public void AppDomains()
{
StartTest("AppDomains.cs");
DebugType type1 = process.SelectedStackFrame.GetLocalVariableValue("one").Type;
DebugType type1b = process.SelectedStackFrame.GetLocalVariableValue("one").Type;
ObjectDump("SameDomainEqual", type1 == type1b);
process.Continue();
ObjectDump("AppDomainName", process.SelectedStackFrame.GetLocalVariableValue("appDomainName").AsString);
DebugType type2 = process.SelectedStackFrame.GetLocalVariableValue("two").Type;
ObjectDump("OtherDomainEqual", type1 == type2);
ObjectDump("AppDomainsEqual", type1.AppDomain == type2.AppDomain);
ObjectDump("AppDomainIDsEqual", type1.AppDomain.ID == type2.AppDomain.ID);
EndTest();
}
}
}
#endif
#if EXPECTED_OUTPUT
<?xml version="1.0" encoding="utf-8"?>
<DebuggerTests>
<Test
name="AppDomains.cs">
<ProcessStarted />
<ModuleLoaded>mscorlib.dll (No symbols)</ModuleLoaded>
<ModuleLoaded>AppDomains.exe (Has symbols)</ModuleLoaded>
<DebuggingPaused>Break AppDomains.cs:17,4-17,40</DebuggingPaused>
<SameDomainEqual>True</SameDomainEqual>
<ModuleLoaded>mscorlib.dll (No symbols)</ModuleLoaded>
<ModuleLoaded>AppDomains.exe (Has symbols)</ModuleLoaded>
<DebuggingPaused>Break AppDomains.cs:30,4-30,40</DebuggingPaused>
<AppDomainName>myDomain Id=2</AppDomainName>
<OtherDomainEqual>False</OtherDomainEqual>
<AppDomainsEqual>False</AppDomainsEqual>
<AppDomainIDsEqual>False</AppDomainIDsEqual>
<ProcessExited />
</Test>
</DebuggerTests>
#endif // EXPECTED_OUTPUT
Loading…
Cancel
Save