From 940fd4681859ee9488cbbf8454cdf44f4ed23f14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Srbeck=C3=BD?= Date: Fri, 7 Jul 2006 12:08:13 +0000 Subject: [PATCH] PersistentValue stored in Values - lifetime of Values increased git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@1551 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Project/Src/Threads/Function.cs | 34 +- .../Project/Src/Variables/ArrayValue.cs | 55 ++- .../Project/Src/Variables/ObjectValue.cs | 312 ++++++++---------- .../Project/Src/Variables/PersistentValue.cs | 54 +-- .../Project/Src/Variables/PropertyVariable.cs | 6 +- .../Project/Src/Variables/Value.cs | 29 +- .../Project/Src/Variables/Variable.cs | 29 +- .../Src/Variables/VariableCollection.cs | 3 +- 8 files changed, 233 insertions(+), 289 deletions(-) diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/Function.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/Function.cs index ff16a059f1..3381203cc0 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/Function.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/Function.cs @@ -105,27 +105,17 @@ namespace Debugger } } } - - public Value ThisValue { + + ICorDebugValue ThisCorValue { get { - if (IsStatic) { - throw new DebuggerException("Static method does not have 'this'."); - } else { - if (this.HasExpired) { - return new UnavailableValue(debugger, "Function has expired"); - } else { - try { - return new ObjectValue(debugger, new PersistentValue(debugger, CorILFrame.GetArgument(0)), ContaingClass); - } catch (COMException e) { - // System.Runtime.InteropServices.COMException (0x80131304): An IL variable is not available at the current native IP. - // See Forum-8640 - if ((uint)e.ErrorCode == 0x80131304) { - return new UnavailableValue(debugger, "Not available in the current state"); - } else { - throw; - } - } - } + if (IsStatic) throw new DebuggerException("Static method does not have 'this'."); + if (this.HasExpired) throw new CannotGetValueException("Function has expired"); + try { + return CorILFrame.GetArgument(0); + } catch (COMException e) { + // System.Runtime.InteropServices.COMException (0x80131304): An IL variable is not available at the current native IP. (See Forum-8640) + if ((uint)e.ErrorCode == 0x80131304) throw new CannotGetValueException("Not available in the current state"); + throw; } } } @@ -383,7 +373,7 @@ namespace Debugger if (!IsStatic) { yield return new Variable(debugger, "this", - new PersistentValue(delegate { return ThisValue; })); + new PersistentValue(debugger, delegate { return ThisCorValue; })); } foreach(Variable var in ArgumentVariables) { yield return var; @@ -401,7 +391,7 @@ namespace Debugger get { // TODO: Should work for static if (!IsStatic) { - foreach(Variable var in ThisValue.GetSubVariables(new PersistentValue(delegate{return ThisValue;}))) { + foreach(Variable var in new PersistentValue(debugger, delegate{ return ThisCorValue; }).Value.GetSubVariables()) { yield return var; } } diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/ArrayValue.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/ArrayValue.cs index aa618a96be..c38f89f2bc 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/ArrayValue.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/ArrayValue.cs @@ -51,8 +51,9 @@ namespace Debugger public override string AsString { get { string txt = "{" + ElementsType + "["; - for (int i = 0; i < rank; i++) + for (int i = 0; i < rank; i++) { txt += dimensions[i].ToString() + ","; + } txt = txt.TrimEnd(new char[] {','}) + "]}"; return txt; } @@ -67,11 +68,21 @@ namespace Debugger lenght = CorArrayValue.Count; dimensions = new uint[rank]; - fixed (void* pDimensions = dimensions) + fixed (void* pDimensions = dimensions) { CorArrayValue.GetDimensions(rank, new IntPtr(pDimensions)); + } } - - + + bool IsCorValueCompatible { + get { + ArrayValue freshValue = this.FreshValue as ArrayValue; + return freshValue != null && + freshValue.ElementsType == this.ElementsType && + freshValue.Lenght == this.Lenght && + freshValue.Rank == this.Rank; + } + } + public Variable this[uint index] { get { return this[new uint[] {index}]; @@ -92,11 +103,11 @@ namespace Debugger public Variable this[uint[] indices] { get { - return GetItem(indices, new PersistentValue(delegate {return this;})); + return GetItem(indices); } } - Variable GetItem(uint[] itemIndices, PersistentValue pValue) + Variable GetItem(uint[] itemIndices) { uint[] indices = (uint[])itemIndices.Clone(); @@ -109,20 +120,14 @@ namespace Debugger return new Variable(debugger, elementName, - new PersistentValue(debugger, delegate { return GetCorValueOfItem(indices, pValue); })); + new PersistentValue(debugger, delegate { return GetCorValueOfItem(indices); })); } - ICorDebugValue GetCorValueOfItem(uint[] indices, PersistentValue pValue) + unsafe ICorDebugValue GetCorValueOfItem(uint[] indices) { - ArrayValue updatedVal = pValue.Value as ArrayValue; - if (this.IsEquivalentValue(updatedVal)) { - unsafe { - fixed (void* pIndices = indices) { - return updatedVal.CorArrayValue.GetElement(rank, new IntPtr(pIndices)); - } - } - } else { - throw new CannotGetValueException("Value is not array"); + if (!IsCorValueCompatible) throw new CannotGetValueException("Value is not the same array"); + fixed (void* pIndices = indices) { + return CorArrayValue.GetElement(rank, new IntPtr(pIndices)); } } @@ -132,32 +137,22 @@ namespace Debugger } } - public override IEnumerable GetSubVariables(PersistentValue pValue) + public override IEnumerable GetSubVariables() { uint[] indices = new uint[rank]; while(true) { // Go thought all combinations for (uint i = rank - 1; i >= 1; i--) - if (indices[i] >= dimensions[i]) - { + if (indices[i] >= dimensions[i]) { indices[i] = 0; indices[i-1]++; } if (indices[0] >= dimensions[0]) break; // We are done - yield return GetItem(indices, pValue); + yield return GetItem(indices); indices[rank - 1]++; } } - - public override bool IsEquivalentValue(Value val) - { - ArrayValue arrayVal = val as ArrayValue; - return arrayVal != null && - arrayVal.ElementsType == this.ElementsType && - arrayVal.Lenght == this.Lenght && - arrayVal.Rank == this.Rank; - } } } diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/ObjectValue.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/ObjectValue.cs index ce2f2c0118..c1a6570974 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/ObjectValue.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/ObjectValue.cs @@ -18,54 +18,24 @@ namespace Debugger { public class ObjectValue: Value { - ICorDebugClass corClass; - ICorDebugModule corModule; - MetaData metaData; - ICorDebugModule corModuleSuperclass; - ObjectValue baseClass; + Module finalCorClassModule; + uint finalCorClassToken; + Module module; + ICorDebugClass corClass; TypeDefProps classProps; - public override string AsString { - get { - return "{" + Type + "}"; - } - } - - public ObjectValue BaseClassObject { + protected ICorDebugObjectValue CorObjectValue { get { - ObjectValue baseClass = this; - while (baseClass.HasBaseClass) { - baseClass = baseClass.BaseClass; - } - return baseClass; + return this.CorValue.CastTo(); } } - IEnumerable Methods { - get { - return this.Module.MetaData.EnumMethods(this.ClassToken); - } - } - - /* - // May return null - public Eval ToStringEval { + public override string AsString { get { - ObjectValue baseClassObject = this.BaseClassObject; - foreach(MethodProps method in baseClassObject.Methods) { - if (method.Name == "ToString") { - ICorDebugValue[] evalArgs; - ICorDebugFunction evalCorFunction; - baseClassObject.Module.CorModule.GetFunctionFromToken(method.Token, out evalCorFunction); - evalArgs = new ICorDebugValue[] {this.SoftReference}; - return new Eval(debugger, evalCorFunction, evalArgs); - } - } - throw new DebuggerException("ToString method not found"); + return "{" + Type + "}"; } } - */ public override string Type { get{ @@ -75,7 +45,7 @@ namespace Debugger public Module Module { get { - return debugger.GetModule(corModule); + return module; } } @@ -85,24 +55,63 @@ namespace Debugger } } - internal unsafe ObjectValue(NDebugger debugger, PersistentValue pValue):base(debugger, pValue) + public ObjectValue BaseClass { + get { + ICorDebugClass superClass = GetSuperClass(debugger, corClass); + if (superClass == null) throw new DebuggerException("Does not have a base class"); + return new ObjectValue(debugger, pValue, superClass); + } + } + + public bool HasBaseClass { + get { + return GetSuperClass(debugger, corClass) != null; + } + } + + internal ObjectValue(NDebugger debugger, PersistentValue pValue):base(debugger, pValue) { - corClass = this.CorValue.CastTo().Class; - InitObjectVariable(); + InitObjectValue(this.CorObjectValue.Class); } - internal unsafe ObjectValue(NDebugger debugger, PersistentValue pValue, ICorDebugClass corClass):base(debugger, pValue) + internal ObjectValue(NDebugger debugger, PersistentValue pValue, ICorDebugClass corClass):base(debugger, pValue) { - this.corClass = corClass; - InitObjectVariable(); + InitObjectValue(corClass); } - void InitObjectVariable () + void InitObjectValue(ICorDebugClass corClass) { - corModule = corClass.Module; - metaData = Module.MetaData; - classProps = metaData.GetTypeDefProps(corClass.Token); - corModuleSuperclass = corModule; + this.finalCorClassModule = debugger.GetModule(this.CorObjectValue.Class.Module); + this.finalCorClassToken = this.CorObjectValue.Class.Token; + + this.module = debugger.GetModule(corClass.Module); + this.corClass = corClass; + this.classProps = Module.MetaData.GetTypeDefProps(corClass.Token); + } + + bool IsCorValueCompatible { + get { + ObjectValue freshValue = this.FreshValue as ObjectValue; + return freshValue != null && + this.finalCorClassModule == freshValue.Module && + this.finalCorClassToken == freshValue.ClassToken; + } + } + + public ObjectValue ObjectClass { + get { + ObjectValue objectClass = this; + while (objectClass.HasBaseClass) { + objectClass = objectClass.BaseClass; + } + return objectClass; + } + } + + IEnumerable Methods { + get { + return this.Module.MetaData.EnumMethods(this.ClassToken); + } } public override bool MayHaveSubVariables { @@ -111,24 +120,24 @@ namespace Debugger } } - public override IEnumerable GetSubVariables(PersistentValue pValue) + public override IEnumerable GetSubVariables() { if (HasBaseClass) { - yield return GetBaseClassVariable(pValue); + yield return GetBaseClassVariable(); } - foreach(Variable var in GetFieldVariables(pValue)) { + foreach(Variable var in GetFieldVariables()) { yield return var; } - foreach(Variable var in GetPropertyVariables(pValue)) { + foreach(Variable var in GetPropertyVariables()) { yield return var; } } - public IEnumerable GetFieldVariables(PersistentValue pValue) + public IEnumerable GetFieldVariables() { - foreach(FieldProps f in metaData.EnumFields(ClassToken)) { + foreach(FieldProps f in Module.MetaData.EnumFields(ClassToken)) { FieldProps field = f; // One per scope/delegate if (field.IsStatic && field.IsLiteral) continue; // Skip field if (!field.IsStatic && CorValue == null) continue; // Skip field @@ -136,19 +145,32 @@ namespace Debugger field.Name, field.IsStatic, field.IsPublic, - new PersistentValue(debugger, delegate { return GetCorValueOfField(field, pValue); })); + new PersistentValue(debugger, delegate { return GetCorValueOfField(field); })); } } - ICorDebugValue GetCorValueOfField(FieldProps field, PersistentValue pValue) + ICorDebugValue GetCorValueOfField(FieldProps field) { - Value updatedVal = pValue.Value; - if (updatedVal is UnavailableValue) throw new CannotGetValueException(updatedVal.AsString); - if (!this.IsEquivalentValue(updatedVal)) throw new CannotGetValueException("Object type changed"); - return GetCorValue(updatedVal, field); + if (!IsCorValueCompatible) throw new CannotGetValueException("Object type changed"); + + // Current frame is used to resolve context specific static values (eg. ThreadStatic) + ICorDebugFrame curFrame = null; + if (debugger.IsPaused && debugger.SelectedThread != null && debugger.SelectedThread.LastFunction != null && debugger.SelectedThread.LastFunction.CorILFrame != null) { + curFrame = debugger.SelectedThread.LastFunction.CorILFrame.CastTo(); + } + + try { + if (field.IsStatic) { + return corClass.GetStaticFieldValue(field.Token, curFrame); + } else { + return CorObjectValue.GetFieldValue(corClass, field.Token); + } + } catch { + throw new CannotGetValueException(); + } } - public IEnumerable GetPropertyVariables(PersistentValue pValue) + public IEnumerable GetPropertyVariables() { foreach(MethodProps m in Methods) { MethodProps method = m; // One per scope/delegate @@ -157,149 +179,101 @@ namespace Debugger method.Name.Remove(0, 4), method.IsStatic, method.IsPublic, - delegate { return CreatePropertyEval(method, pValue); }); + delegate { return CreatePropertyEval(method); }); } } } - Eval CreatePropertyEval(MethodProps method, PersistentValue pValue) + Eval CreatePropertyEval(MethodProps method) { - Value updatedVal = pValue.Value; - if (updatedVal is UnavailableValue) { - return null; - } - if (this.IsEquivalentValue(updatedVal)) { - ICorDebugFunction evalCorFunction = Module.CorModule.GetFunctionFromToken(method.Token); - - return new Eval(debugger, evalCorFunction, delegate { return GetArgsForEval(method, pValue); }); - } else { - return null; - } - } - - ICorDebugValue[] GetArgsForEval(MethodProps method, PersistentValue pValue) - { - ObjectValue updatedVal = pValue.Value as ObjectValue; - if (this.IsEquivalentValue(updatedVal)) { - if (method.IsStatic) { - return new ICorDebugValue[] {}; - } else { - if (updatedVal.SoftReference != null) { - return new ICorDebugValue[] {updatedVal.SoftReference.CastTo()}; - } else { - return new ICorDebugValue[] {updatedVal.CorValue}; - } - } - } else { - return null; - } - } - - public override bool IsEquivalentValue(Value val) - { - ObjectValue objVal = val as ObjectValue; - return objVal != null && - objVal.ClassToken == this.ClassToken; + if (!IsCorValueCompatible) return null; + + ICorDebugFunction evalCorFunction = Module.CorModule.GetFunctionFromToken(method.Token); + return new Eval(debugger, evalCorFunction, delegate { return GetArgsForEval(method); }); } - ICorDebugValue GetCorValue(Value val, FieldProps field) + ICorDebugValue[] GetArgsForEval(MethodProps method) { - // Current frame is used to resolve context specific static values (eg. ThreadStatic) - ICorDebugFrame curFrame = null; - if (debugger.IsPaused && debugger.SelectedThread != null && debugger.SelectedThread.LastFunction != null && debugger.SelectedThread.LastFunction.CorILFrame != null) { - curFrame = debugger.SelectedThread.LastFunction.CorILFrame.CastTo(); - } + if (!IsCorValueCompatible) return null; - try { - if (field.IsStatic) { - return corClass.GetStaticFieldValue(field.Token, curFrame); + if (method.IsStatic) { + return new ICorDebugValue[] {}; + } else { + if (this.SoftReference != null) { + return new ICorDebugValue[] {this.SoftReference.CastTo()}; } else { - return (val.CorValue.CastTo()).GetFieldValue(corClass, field.Token); + return new ICorDebugValue[] {this.CorValue}; } - } catch { - throw new CannotGetValueException(); } } - public Variable GetBaseClassVariable(PersistentValue pValue) + public Variable GetBaseClassVariable() { if (HasBaseClass) { return new Variable(debugger, "", - new PersistentValue(delegate { return GetBaseClassValue(pValue); })); + new PersistentValue(debugger, delegate { return GetBaseClassValue(); })); } else { return null; } } - Value GetBaseClassValue(PersistentValue pValue) + Value GetBaseClassValue() { - Value updatedVal = pValue.Value; - if (updatedVal is UnavailableValue) return updatedVal; - if (this.IsEquivalentValue(updatedVal)) { - return ((ObjectValue)updatedVal).BaseClass; - } else { - return new UnavailableValue(debugger, "Object type changed"); - } + if (!IsCorValueCompatible) return new UnavailableValue(debugger, "Object type changed"); + + return this.BaseClass; } - public unsafe ObjectValue BaseClass { - get { - if (baseClass == null) baseClass = GetBaseClass(); - if (baseClass == null) throw new DebuggerException("Object doesn't have a base class. You may use HasBaseClass to check this."); - return baseClass; - } - } - - public bool HasBaseClass { - get { - if (baseClass == null) { - try { - baseClass = GetBaseClass(); - } catch (DebuggerException) { - baseClass = null; - } - } - return (baseClass != null); - } - } - - protected ObjectValue GetBaseClass() + protected static ICorDebugClass GetSuperClass(NDebugger debugger, ICorDebugClass currClass) { - string fullTypeName = "<>"; - - // If referencing to external assembly - if ((classProps.SuperClassToken & 0x01000000) != 0) { - - fullTypeName = metaData.GetTypeRefProps(classProps.SuperClassToken).Name; - - classProps.SuperClassToken = 0; - foreach (Module m in debugger.Modules) - { + Module currModule = debugger.GetModule(currClass.Module); + uint superToken = currModule.MetaData.GetTypeDefProps(currClass.Token).SuperClassToken; + + // It has no base class + if ((superToken & 0x00FFFFFF) == 0x00000000) return null; + + // TypeDef - Localy defined + if ((superToken & 0xFF000000) == 0x02000000) { + return currModule.CorModule.GetClassFromToken(superToken); + } + + // TypeRef - Referencing to external assembly + if ((superToken & 0xFF000000) == 0x01000000) { + string fullTypeName = currModule.MetaData.GetTypeRefProps(superToken).Name; + + foreach (Module superModule in debugger.Modules) { // TODO: Does not work for nested - // see FindTypeDefByName in dshell.cpp // TODO: preservesig try { - classProps.SuperClassToken = m.MetaData.FindTypeDefByName(fullTypeName, 0).Token; + uint token = superModule.MetaData.FindTypeDefByName(fullTypeName, 0).Token; + return superModule.CorModule.GetClassFromToken(token); } catch { continue; } - corModuleSuperclass = m.CorModule; - break; } } - - // If it has no base class - if ((classProps.SuperClassToken & 0x00FFFFFF) == 0) { - throw new DebuggerException("Unable to get base class: " + fullTypeName); - } else { - ICorDebugClass superClass = corModuleSuperclass.GetClassFromToken(classProps.SuperClassToken); - if (corHandleValue != null) { - return new ObjectValue(debugger, new PersistentValue(debugger, corHandleValue.As()), superClass); - } else { - return new ObjectValue(debugger, new PersistentValue(debugger, CorValue), superClass); + + throw new DebuggerException("Superclass not found"); + } + + /* + // May return null + public Eval ToStringEval { + get { + ObjectValue baseClassObject = this.BaseClassObject; + foreach(MethodProps method in baseClassObject.Methods) { + if (method.Name == "ToString") { + ICorDebugValue[] evalArgs; + ICorDebugFunction evalCorFunction; + baseClassObject.Module.CorModule.GetFunctionFromToken(method.Token, out evalCorFunction); + evalArgs = new ICorDebugValue[] {this.SoftReference}; + return new Eval(debugger, evalCorFunction, evalArgs); + } } + throw new DebuggerException("ToString method not found"); } } + */ } } diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/PersistentValue.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/PersistentValue.cs index 5c62be1d55..1b98030d45 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/PersistentValue.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/PersistentValue.cs @@ -33,8 +33,6 @@ namespace Debugger ValueGetter valueGetter; IsExpiredDelegate isExpired; - public ICorDebugValue initValue; - public NDebugger Debugger { get { return debugger; @@ -42,6 +40,12 @@ namespace Debugger } public ICorDebugValue CorValue { + get { + return PersistentValue.DereferenceUnbox(RawCorValue); + } + } + + ICorDebugValue RawCorValue { get { return corValueGetter(); } @@ -67,46 +71,53 @@ namespace Debugger get { if (this.IsExpired) throw new DebuggerException("CorValue has expired"); - if (this.initValue != null && this.initValue.Is()) { - return this.initValue.As(); - } else if (this.initValue != null && this.initValue.Is()) { - return this.initValue.As().CreateHandle(CorDebugHandleType.HANDLE_WEAK_TRACK_RESURRECTION); + ICorDebugValue corValue = RawCorValue; + if (corValue != null && corValue.Is()) { + return corValue.As(); + } + corValue = PersistentValue.DereferenceUnbox(corValue); + if (corValue != null && corValue.Is()) { + return corValue.As().CreateHandle(CorDebugHandleType.HANDLE_WEAK_TRACK_RESURRECTION); } else { return null; // Value type } } } - public PersistentValue(ValueGetter getter) + public PersistentValue(NDebugger debugger, ValueGetter valueGetter) { - this.valueGetter = getter; + this.debugger = debugger; + this.corValueGetter = delegate { throw new CannotGetValueException("CorValue not available for custom value"); }; + this.isExpired = delegate { return false; }; + this.valueGetter = valueGetter; } public PersistentValue(NDebugger debugger, ICorDebugValue corValue) { - this.debugger = debugger; - this.initValue = corValue; PauseSession pauseSessionAtCreation = debugger.PauseSession; DebugeeState debugeeStateAtCreation = debugger.DebugeeState; + this.debugger = debugger; this.corValueGetter = delegate { - if (this.IsExpired) throw new DebuggerException("CorValue has expired"); - - return PersistentValue.DereferenceUnbox(this.initValue); + if (this.IsExpired) throw new CannotGetValueException("CorValue has expired"); + return corValue; }; this.isExpired = delegate { - if (this.initValue != null && this.initValue.Is()) { + if (corValue != null && corValue.Is()) { return debugeeStateAtCreation != debugger.DebugeeState; } else { return pauseSessionAtCreation != debugger.PauseSession; } }; - this.valueGetter = delegate { return CreateValue(debugger, corValue); }; + this.valueGetter = delegate { return CreateValue(); }; } public PersistentValue(NDebugger debugger, CorValueGetter corValueGetter) { - this.valueGetter = delegate { return CreateValue(debugger, corValueGetter()); }; + this.debugger = debugger; + this.corValueGetter = corValueGetter; + this.isExpired = delegate { return false; }; + this.valueGetter = delegate { return CreateValue(); }; } internal static ICorDebugValue DereferenceUnbox(ICorDebugValue corValue) @@ -134,11 +145,12 @@ namespace Debugger return corValue; } - static Value CreateValue(NDebugger debugger, ICorDebugValue corValue) + Value CreateValue() { + ICorDebugValue corValue = RawCorValue; ICorDebugValue derefed = DereferenceUnbox(corValue); if (derefed == null) { - return new NullValue(debugger, new PersistentValue(debugger, corValue)); + return new NullValue(debugger, this); } CorElementType type = Value.GetCorType(derefed); @@ -160,16 +172,16 @@ namespace Debugger case CorElementType.I: case CorElementType.U: case CorElementType.STRING: - return new PrimitiveValue(debugger, new PersistentValue(debugger, corValue)); + return new PrimitiveValue(debugger, this); case CorElementType.ARRAY: case CorElementType.SZARRAY: // Short-cut for single dimension zero lower bound array - return new ArrayValue(debugger, new PersistentValue(debugger, corValue)); + return new ArrayValue(debugger, this); case CorElementType.VALUETYPE: case CorElementType.CLASS: case CorElementType.OBJECT: // Short-cut for Class "System.Object" - return new ObjectValue(debugger, new PersistentValue(debugger, corValue)); + return new ObjectValue(debugger, this); default: // Unknown type return new UnavailableValue(debugger, "Unknown value type"); diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/PropertyVariable.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/PropertyVariable.cs index c7adb17594..b53b929deb 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/PropertyVariable.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/PropertyVariable.cs @@ -24,7 +24,7 @@ namespace Debugger internal PropertyVariable(NDebugger debugger, string name, bool isStatic, bool isPublic, EvalCreator evalCreator):base(debugger, name, isStatic, isPublic, null) { this.evalCreator = evalCreator; - this.pValue = new PersistentValue(delegate { return GetValueOfResult(); }); + this.pValue = new PersistentValue(debugger, delegate { return GetValueOfResult(); }); } Value GetValueOfResult() @@ -51,8 +51,8 @@ namespace Debugger if (cachedEval == null || cachedEval.HasExpired) { cachedEval = evalCreator(); if (cachedEval != null) { - cachedEval.EvalStarted += delegate { OnValueChanged(); }; - cachedEval.EvalComplete += delegate { OnValueChanged(); }; + cachedEval.EvalStarted += delegate { OnValueChanged(this, null); }; + cachedEval.EvalComplete += delegate { OnValueChanged(this, null); }; } } return cachedEval; diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Value.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Value.cs index f5332d4bb1..a27d090526 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Value.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Value.cs @@ -16,7 +16,7 @@ namespace Debugger public abstract class Value: RemotingObjectBase { protected NDebugger debugger; - PersistentValue pValue; + protected PersistentValue pValue; public event EventHandler ValueChanged; @@ -26,12 +26,6 @@ namespace Debugger } } - protected ICorDebugHandleValue corHandleValue { - get { - return pValue.initValue.As(); - } - } - internal ICorDebugValue CorValue { get { return pValue.CorValue; @@ -44,6 +38,12 @@ namespace Debugger } } + protected Value FreshValue { + get { + return pValue.Value; + } + } + /// /// If true than the value is no longer valid and you should obtain updated copy /// @@ -88,23 +88,14 @@ namespace Debugger /// /// Gets the subvariables of this value /// - /// Delegate that will be called to get the up-to-date value - public virtual IEnumerable GetSubVariables(PersistentValue pValue) + public virtual IEnumerable GetSubVariables() { yield break; } - /// - /// Gets whether the given value is equivalent to this one. (ie it is may be just its other instance) - /// - public virtual bool IsEquivalentValue(Value val) - { - return val.GetType() == this.GetType(); - } - public Variable this[string variableName] { get { - foreach(Variable v in GetSubVariables(new PersistentValue(delegate{ return this.IsExpired?new UnavailableValue(debugger, "Value has expired"):this;}))) { + foreach(Variable v in GetSubVariables()) { if (v.Name == variableName) return v; } throw new DebuggerException("Subvariable " + variableName + " does not exist"); @@ -157,7 +148,7 @@ namespace Debugger } /// - /// Returns true if the value is signed or unsigned integer of any siz + /// Returns true if the value is signed or unsigned integer of any size /// public bool IsInteger { get { diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Variable.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Variable.cs index 2e90c05ad8..9e647d4b7b 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Variable.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Variable.cs @@ -19,7 +19,6 @@ namespace Debugger VariableCollection subVariables; internal protected PersistentValue pValue; - internal Value cachedValue; event EventHandler valueChanged; public event EventHandler ValueRemovedFromCollection; @@ -55,15 +54,10 @@ namespace Debugger /// public Value Value { get { - if (cachedValue == null || cachedValue.IsExpired) { - cachedValue = pValue.Value; - if (cachedValue == null) throw new DebuggerException("ValueGetter returned null"); - cachedValue.ValueChanged += delegate { OnValueChanged(); }; - } - if (cachedValue.IsExpired) { - return new UnavailableValue(debugger, "The value has expired"); - } - return cachedValue; + Value val = pValue.Value; + val.ValueChanged -= OnValueChanged; + val.ValueChanged += OnValueChanged; + return val; } } @@ -84,9 +78,8 @@ namespace Debugger } } - protected internal virtual void OnValueChanged() + protected internal virtual void OnValueChanged(object sender, ValueEventArgs e) { - cachedValue = null; if (valueChanged != null) { valueChanged(this, new VariableEventArgs(this)); } @@ -98,16 +91,6 @@ namespace Debugger } } - public Variable(NDebugger debugger, ICorDebugValue corValue, string name):this(new PersistentValue(debugger, corValue).Value, name) - { - - } - - public Variable(Value val, string name):this(val.Debugger, name, new PersistentValue(delegate {return val;})) - { - - } - public Variable(NDebugger debugger, string name, PersistentValue pValue) { this.debugger = debugger; @@ -126,7 +109,7 @@ namespace Debugger void OnSubVariablesUpdating(object sender, VariableCollectionEventArgs e) { - subVariables.UpdateTo(Value.GetSubVariables(new PersistentValue(delegate{return this.Value;}))); + subVariables.UpdateTo(Value.GetSubVariables()); } } } diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/VariableCollection.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/VariableCollection.cs index b18b155c7d..1469048c8b 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/VariableCollection.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/VariableCollection.cs @@ -149,13 +149,12 @@ namespace Debugger // Trasfer the new variable into the old one if (oldVariable != newVariable) { oldVariable.pValue = newVariable.pValue; - oldVariable.cachedValue = null; if (newVariable is ClassVariable && oldVariable is ClassVariable) { ((ClassVariable)oldVariable).isPublic = ((ClassVariable)oldVariable).isPublic; ((ClassVariable)oldVariable).isStatic = ((ClassVariable)oldVariable).isStatic; } if (newVariable is PropertyVariable) { - newVariable.ValueChanged += delegate { oldVariable.OnValueChanged(); }; + newVariable.ValueChanged += delegate { oldVariable.OnValueChanged(this, null); }; } } // Keep the variable in the list