Browse Source

PersistentValue stored in Values - lifetime of Values increased

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@1551 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
David Srbecký 20 years ago
parent
commit
940fd46818
  1. 34
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/Function.cs
  2. 55
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/ArrayValue.cs
  3. 312
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/ObjectValue.cs
  4. 54
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/PersistentValue.cs
  5. 6
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/PropertyVariable.cs
  6. 29
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Value.cs
  7. 29
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Variable.cs
  8. 3
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/VariableCollection.cs

34
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/Function.cs

@ -105,27 +105,17 @@ namespace Debugger
} }
} }
} }
public Value ThisValue { ICorDebugValue ThisCorValue {
get { get {
if (IsStatic) { if (IsStatic) throw new DebuggerException("Static method does not have 'this'.");
throw new DebuggerException("Static method does not have 'this'."); if (this.HasExpired) throw new CannotGetValueException("Function has expired");
} else { try {
if (this.HasExpired) { return CorILFrame.GetArgument(0);
return new UnavailableValue(debugger, "Function has expired"); } catch (COMException e) {
} else { // System.Runtime.InteropServices.COMException (0x80131304): An IL variable is not available at the current native IP. (See Forum-8640)
try { if ((uint)e.ErrorCode == 0x80131304) throw new CannotGetValueException("Not available in the current state");
return new ObjectValue(debugger, new PersistentValue(debugger, CorILFrame.GetArgument(0)), ContaingClass); throw;
} 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;
}
}
}
} }
} }
} }
@ -383,7 +373,7 @@ namespace Debugger
if (!IsStatic) { if (!IsStatic) {
yield return new Variable(debugger, yield return new Variable(debugger,
"this", "this",
new PersistentValue(delegate { return ThisValue; })); new PersistentValue(debugger, delegate { return ThisCorValue; }));
} }
foreach(Variable var in ArgumentVariables) { foreach(Variable var in ArgumentVariables) {
yield return var; yield return var;
@ -401,7 +391,7 @@ namespace Debugger
get { get {
// TODO: Should work for static // TODO: Should work for static
if (!IsStatic) { 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; yield return var;
} }
} }

55
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/ArrayValue.cs

@ -51,8 +51,9 @@ namespace Debugger
public override string AsString { public override string AsString {
get { get {
string txt = "{" + ElementsType + "["; string txt = "{" + ElementsType + "[";
for (int i = 0; i < rank; i++) for (int i = 0; i < rank; i++) {
txt += dimensions[i].ToString() + ","; txt += dimensions[i].ToString() + ",";
}
txt = txt.TrimEnd(new char[] {','}) + "]}"; txt = txt.TrimEnd(new char[] {','}) + "]}";
return txt; return txt;
} }
@ -67,11 +68,21 @@ namespace Debugger
lenght = CorArrayValue.Count; lenght = CorArrayValue.Count;
dimensions = new uint[rank]; dimensions = new uint[rank];
fixed (void* pDimensions = dimensions) fixed (void* pDimensions = dimensions) {
CorArrayValue.GetDimensions(rank, new IntPtr(pDimensions)); 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] { public Variable this[uint index] {
get { get {
return this[new uint[] {index}]; return this[new uint[] {index}];
@ -92,11 +103,11 @@ namespace Debugger
public Variable this[uint[] indices] { public Variable this[uint[] indices] {
get { 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(); uint[] indices = (uint[])itemIndices.Clone();
@ -109,20 +120,14 @@ namespace Debugger
return new Variable(debugger, return new Variable(debugger,
elementName, 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 (!IsCorValueCompatible) throw new CannotGetValueException("Value is not the same array");
if (this.IsEquivalentValue(updatedVal)) { fixed (void* pIndices = indices) {
unsafe { return CorArrayValue.GetElement(rank, new IntPtr(pIndices));
fixed (void* pIndices = indices) {
return updatedVal.CorArrayValue.GetElement(rank, new IntPtr(pIndices));
}
}
} else {
throw new CannotGetValueException("Value is not array");
} }
} }
@ -132,32 +137,22 @@ namespace Debugger
} }
} }
public override IEnumerable<Variable> GetSubVariables(PersistentValue pValue) public override IEnumerable<Variable> GetSubVariables()
{ {
uint[] indices = new uint[rank]; uint[] indices = new uint[rank];
while(true) { // Go thought all combinations while(true) { // Go thought all combinations
for (uint i = rank - 1; i >= 1; i--) for (uint i = rank - 1; i >= 1; i--)
if (indices[i] >= dimensions[i]) if (indices[i] >= dimensions[i]) {
{
indices[i] = 0; indices[i] = 0;
indices[i-1]++; indices[i-1]++;
} }
if (indices[0] >= dimensions[0]) break; // We are done if (indices[0] >= dimensions[0]) break; // We are done
yield return GetItem(indices, pValue); yield return GetItem(indices);
indices[rank - 1]++; 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;
}
} }
} }

312
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/ObjectValue.cs

@ -18,54 +18,24 @@ namespace Debugger
{ {
public class ObjectValue: Value public class ObjectValue: Value
{ {
ICorDebugClass corClass; Module finalCorClassModule;
ICorDebugModule corModule; uint finalCorClassToken;
MetaData metaData;
ICorDebugModule corModuleSuperclass;
ObjectValue baseClass;
Module module;
ICorDebugClass corClass;
TypeDefProps classProps; TypeDefProps classProps;
public override string AsString { protected ICorDebugObjectValue CorObjectValue {
get {
return "{" + Type + "}";
}
}
public ObjectValue BaseClassObject {
get { get {
ObjectValue baseClass = this; return this.CorValue.CastTo<ICorDebugObjectValue>();
while (baseClass.HasBaseClass) {
baseClass = baseClass.BaseClass;
}
return baseClass;
} }
} }
IEnumerable<MethodProps> Methods { public override string AsString {
get {
return this.Module.MetaData.EnumMethods(this.ClassToken);
}
}
/*
// May return null
public Eval ToStringEval {
get { get {
ObjectValue baseClassObject = this.BaseClassObject; return "{" + Type + "}";
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");
} }
} }
*/
public override string Type { public override string Type {
get{ get{
@ -75,7 +45,7 @@ namespace Debugger
public Module Module { public Module Module {
get { 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<ICorDebugObjectValue>().Class; InitObjectValue(this.CorObjectValue.Class);
InitObjectVariable();
} }
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; InitObjectValue(corClass);
InitObjectVariable();
} }
void InitObjectVariable () void InitObjectValue(ICorDebugClass corClass)
{ {
corModule = corClass.Module; this.finalCorClassModule = debugger.GetModule(this.CorObjectValue.Class.Module);
metaData = Module.MetaData; this.finalCorClassToken = this.CorObjectValue.Class.Token;
classProps = metaData.GetTypeDefProps(corClass.Token);
corModuleSuperclass = corModule; 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<MethodProps> Methods {
get {
return this.Module.MetaData.EnumMethods(this.ClassToken);
}
} }
public override bool MayHaveSubVariables { public override bool MayHaveSubVariables {
@ -111,24 +120,24 @@ namespace Debugger
} }
} }
public override IEnumerable<Variable> GetSubVariables(PersistentValue pValue) public override IEnumerable<Variable> GetSubVariables()
{ {
if (HasBaseClass) { if (HasBaseClass) {
yield return GetBaseClassVariable(pValue); yield return GetBaseClassVariable();
} }
foreach(Variable var in GetFieldVariables(pValue)) { foreach(Variable var in GetFieldVariables()) {
yield return var; yield return var;
} }
foreach(Variable var in GetPropertyVariables(pValue)) { foreach(Variable var in GetPropertyVariables()) {
yield return var; yield return var;
} }
} }
public IEnumerable<Variable> GetFieldVariables(PersistentValue pValue) public IEnumerable<Variable> GetFieldVariables()
{ {
foreach(FieldProps f in metaData.EnumFields(ClassToken)) { foreach(FieldProps f in Module.MetaData.EnumFields(ClassToken)) {
FieldProps field = f; // One per scope/delegate FieldProps field = f; // One per scope/delegate
if (field.IsStatic && field.IsLiteral) continue; // Skip field if (field.IsStatic && field.IsLiteral) continue; // Skip field
if (!field.IsStatic && CorValue == null) continue; // Skip field if (!field.IsStatic && CorValue == null) continue; // Skip field
@ -136,19 +145,32 @@ namespace Debugger
field.Name, field.Name,
field.IsStatic, field.IsStatic,
field.IsPublic, 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 (!IsCorValueCompatible) throw new CannotGetValueException("Object type changed");
if (updatedVal is UnavailableValue) throw new CannotGetValueException(updatedVal.AsString);
if (!this.IsEquivalentValue(updatedVal)) throw new CannotGetValueException("Object type changed"); // Current frame is used to resolve context specific static values (eg. ThreadStatic)
return GetCorValue(updatedVal, field); ICorDebugFrame curFrame = null;
if (debugger.IsPaused && debugger.SelectedThread != null && debugger.SelectedThread.LastFunction != null && debugger.SelectedThread.LastFunction.CorILFrame != null) {
curFrame = debugger.SelectedThread.LastFunction.CorILFrame.CastTo<ICorDebugFrame>();
}
try {
if (field.IsStatic) {
return corClass.GetStaticFieldValue(field.Token, curFrame);
} else {
return CorObjectValue.GetFieldValue(corClass, field.Token);
}
} catch {
throw new CannotGetValueException();
}
} }
public IEnumerable<Variable> GetPropertyVariables(PersistentValue pValue) public IEnumerable<Variable> GetPropertyVariables()
{ {
foreach(MethodProps m in Methods) { foreach(MethodProps m in Methods) {
MethodProps method = m; // One per scope/delegate MethodProps method = m; // One per scope/delegate
@ -157,149 +179,101 @@ namespace Debugger
method.Name.Remove(0, 4), method.Name.Remove(0, 4),
method.IsStatic, method.IsStatic,
method.IsPublic, 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 (!IsCorValueCompatible) return null;
if (updatedVal is UnavailableValue) {
return null; ICorDebugFunction evalCorFunction = Module.CorModule.GetFunctionFromToken(method.Token);
} return new Eval(debugger, evalCorFunction, delegate { return GetArgsForEval(method); });
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<ICorDebugValue>()};
} 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;
} }
ICorDebugValue GetCorValue(Value val, FieldProps field) ICorDebugValue[] GetArgsForEval(MethodProps method)
{ {
// Current frame is used to resolve context specific static values (eg. ThreadStatic) if (!IsCorValueCompatible) return null;
ICorDebugFrame curFrame = null;
if (debugger.IsPaused && debugger.SelectedThread != null && debugger.SelectedThread.LastFunction != null && debugger.SelectedThread.LastFunction.CorILFrame != null) {
curFrame = debugger.SelectedThread.LastFunction.CorILFrame.CastTo<ICorDebugFrame>();
}
try { if (method.IsStatic) {
if (field.IsStatic) { return new ICorDebugValue[] {};
return corClass.GetStaticFieldValue(field.Token, curFrame); } else {
if (this.SoftReference != null) {
return new ICorDebugValue[] {this.SoftReference.CastTo<ICorDebugValue>()};
} else { } else {
return (val.CorValue.CastTo<ICorDebugObjectValue>()).GetFieldValue(corClass, field.Token); return new ICorDebugValue[] {this.CorValue};
} }
} catch {
throw new CannotGetValueException();
} }
} }
public Variable GetBaseClassVariable(PersistentValue pValue) public Variable GetBaseClassVariable()
{ {
if (HasBaseClass) { if (HasBaseClass) {
return new Variable(debugger, return new Variable(debugger,
"<Base class>", "<Base class>",
new PersistentValue(delegate { return GetBaseClassValue(pValue); })); new PersistentValue(debugger, delegate { return GetBaseClassValue(); }));
} else { } else {
return null; return null;
} }
} }
Value GetBaseClassValue(PersistentValue pValue) Value GetBaseClassValue()
{ {
Value updatedVal = pValue.Value; if (!IsCorValueCompatible) return new UnavailableValue(debugger, "Object type changed");
if (updatedVal is UnavailableValue) return updatedVal;
if (this.IsEquivalentValue(updatedVal)) { return this.BaseClass;
return ((ObjectValue)updatedVal).BaseClass;
} else {
return new UnavailableValue(debugger, "Object type changed");
}
} }
public unsafe ObjectValue BaseClass { protected static ICorDebugClass GetSuperClass(NDebugger debugger, ICorDebugClass currClass)
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()
{ {
string fullTypeName = "<>"; Module currModule = debugger.GetModule(currClass.Module);
uint superToken = currModule.MetaData.GetTypeDefProps(currClass.Token).SuperClassToken;
// If referencing to external assembly
if ((classProps.SuperClassToken & 0x01000000) != 0) { // It has no base class
if ((superToken & 0x00FFFFFF) == 0x00000000) return null;
fullTypeName = metaData.GetTypeRefProps(classProps.SuperClassToken).Name;
// TypeDef - Localy defined
classProps.SuperClassToken = 0; if ((superToken & 0xFF000000) == 0x02000000) {
foreach (Module m in debugger.Modules) 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 // TODO: Does not work for nested
// see FindTypeDefByName in dshell.cpp
// TODO: preservesig // TODO: preservesig
try { try {
classProps.SuperClassToken = m.MetaData.FindTypeDefByName(fullTypeName, 0).Token; uint token = superModule.MetaData.FindTypeDefByName(fullTypeName, 0).Token;
return superModule.CorModule.GetClassFromToken(token);
} catch { } catch {
continue; continue;
} }
corModuleSuperclass = m.CorModule;
break;
} }
} }
// If it has no base class throw new DebuggerException("Superclass not found");
if ((classProps.SuperClassToken & 0x00FFFFFF) == 0) { }
throw new DebuggerException("Unable to get base class: " + fullTypeName);
} else { /*
ICorDebugClass superClass = corModuleSuperclass.GetClassFromToken(classProps.SuperClassToken); // May return null
if (corHandleValue != null) { public Eval ToStringEval {
return new ObjectValue(debugger, new PersistentValue(debugger, corHandleValue.As<ICorDebugValue>()), superClass); get {
} else { ObjectValue baseClassObject = this.BaseClassObject;
return new ObjectValue(debugger, new PersistentValue(debugger, CorValue), superClass); 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");
} }
} }
*/
} }
} }

54
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/PersistentValue.cs

@ -33,8 +33,6 @@ namespace Debugger
ValueGetter valueGetter; ValueGetter valueGetter;
IsExpiredDelegate isExpired; IsExpiredDelegate isExpired;
public ICorDebugValue initValue;
public NDebugger Debugger { public NDebugger Debugger {
get { get {
return debugger; return debugger;
@ -42,6 +40,12 @@ namespace Debugger
} }
public ICorDebugValue CorValue { public ICorDebugValue CorValue {
get {
return PersistentValue.DereferenceUnbox(RawCorValue);
}
}
ICorDebugValue RawCorValue {
get { get {
return corValueGetter(); return corValueGetter();
} }
@ -67,46 +71,53 @@ namespace Debugger
get { get {
if (this.IsExpired) throw new DebuggerException("CorValue has expired"); if (this.IsExpired) throw new DebuggerException("CorValue has expired");
if (this.initValue != null && this.initValue.Is<ICorDebugHandleValue>()) { ICorDebugValue corValue = RawCorValue;
return this.initValue.As<ICorDebugHandleValue>(); if (corValue != null && corValue.Is<ICorDebugHandleValue>()) {
} else if (this.initValue != null && this.initValue.Is<ICorDebugHeapValue2>()) { return corValue.As<ICorDebugHandleValue>();
return this.initValue.As<ICorDebugHeapValue2>().CreateHandle(CorDebugHandleType.HANDLE_WEAK_TRACK_RESURRECTION); }
corValue = PersistentValue.DereferenceUnbox(corValue);
if (corValue != null && corValue.Is<ICorDebugHeapValue2>()) {
return corValue.As<ICorDebugHeapValue2>().CreateHandle(CorDebugHandleType.HANDLE_WEAK_TRACK_RESURRECTION);
} else { } else {
return null; // Value type 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) public PersistentValue(NDebugger debugger, ICorDebugValue corValue)
{ {
this.debugger = debugger;
this.initValue = corValue;
PauseSession pauseSessionAtCreation = debugger.PauseSession; PauseSession pauseSessionAtCreation = debugger.PauseSession;
DebugeeState debugeeStateAtCreation = debugger.DebugeeState; DebugeeState debugeeStateAtCreation = debugger.DebugeeState;
this.debugger = debugger;
this.corValueGetter = delegate { this.corValueGetter = delegate {
if (this.IsExpired) throw new DebuggerException("CorValue has expired"); if (this.IsExpired) throw new CannotGetValueException("CorValue has expired");
return corValue;
return PersistentValue.DereferenceUnbox(this.initValue);
}; };
this.isExpired = delegate { this.isExpired = delegate {
if (this.initValue != null && this.initValue.Is<ICorDebugHandleValue>()) { if (corValue != null && corValue.Is<ICorDebugHandleValue>()) {
return debugeeStateAtCreation != debugger.DebugeeState; return debugeeStateAtCreation != debugger.DebugeeState;
} else { } else {
return pauseSessionAtCreation != debugger.PauseSession; return pauseSessionAtCreation != debugger.PauseSession;
} }
}; };
this.valueGetter = delegate { return CreateValue(debugger, corValue); }; this.valueGetter = delegate { return CreateValue(); };
} }
public PersistentValue(NDebugger debugger, CorValueGetter corValueGetter) 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) internal static ICorDebugValue DereferenceUnbox(ICorDebugValue corValue)
@ -134,11 +145,12 @@ namespace Debugger
return corValue; return corValue;
} }
static Value CreateValue(NDebugger debugger, ICorDebugValue corValue) Value CreateValue()
{ {
ICorDebugValue corValue = RawCorValue;
ICorDebugValue derefed = DereferenceUnbox(corValue); ICorDebugValue derefed = DereferenceUnbox(corValue);
if (derefed == null) { if (derefed == null) {
return new NullValue(debugger, new PersistentValue(debugger, corValue)); return new NullValue(debugger, this);
} }
CorElementType type = Value.GetCorType(derefed); CorElementType type = Value.GetCorType(derefed);
@ -160,16 +172,16 @@ namespace Debugger
case CorElementType.I: case CorElementType.I:
case CorElementType.U: case CorElementType.U:
case CorElementType.STRING: case CorElementType.STRING:
return new PrimitiveValue(debugger, new PersistentValue(debugger, corValue)); return new PrimitiveValue(debugger, this);
case CorElementType.ARRAY: case CorElementType.ARRAY:
case CorElementType.SZARRAY: // Short-cut for single dimension zero lower bound 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.VALUETYPE:
case CorElementType.CLASS: case CorElementType.CLASS:
case CorElementType.OBJECT: // Short-cut for Class "System.Object" 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 default: // Unknown type
return new UnavailableValue(debugger, "Unknown value type"); return new UnavailableValue(debugger, "Unknown value type");

6
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) internal PropertyVariable(NDebugger debugger, string name, bool isStatic, bool isPublic, EvalCreator evalCreator):base(debugger, name, isStatic, isPublic, null)
{ {
this.evalCreator = evalCreator; this.evalCreator = evalCreator;
this.pValue = new PersistentValue(delegate { return GetValueOfResult(); }); this.pValue = new PersistentValue(debugger, delegate { return GetValueOfResult(); });
} }
Value GetValueOfResult() Value GetValueOfResult()
@ -51,8 +51,8 @@ namespace Debugger
if (cachedEval == null || cachedEval.HasExpired) { if (cachedEval == null || cachedEval.HasExpired) {
cachedEval = evalCreator(); cachedEval = evalCreator();
if (cachedEval != null) { if (cachedEval != null) {
cachedEval.EvalStarted += delegate { OnValueChanged(); }; cachedEval.EvalStarted += delegate { OnValueChanged(this, null); };
cachedEval.EvalComplete += delegate { OnValueChanged(); }; cachedEval.EvalComplete += delegate { OnValueChanged(this, null); };
} }
} }
return cachedEval; return cachedEval;

29
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Value.cs

@ -16,7 +16,7 @@ namespace Debugger
public abstract class Value: RemotingObjectBase public abstract class Value: RemotingObjectBase
{ {
protected NDebugger debugger; protected NDebugger debugger;
PersistentValue pValue; protected PersistentValue pValue;
public event EventHandler<ValueEventArgs> ValueChanged; public event EventHandler<ValueEventArgs> ValueChanged;
@ -26,12 +26,6 @@ namespace Debugger
} }
} }
protected ICorDebugHandleValue corHandleValue {
get {
return pValue.initValue.As<ICorDebugHandleValue>();
}
}
internal ICorDebugValue CorValue { internal ICorDebugValue CorValue {
get { get {
return pValue.CorValue; return pValue.CorValue;
@ -44,6 +38,12 @@ namespace Debugger
} }
} }
protected Value FreshValue {
get {
return pValue.Value;
}
}
/// <summary> /// <summary>
/// If true than the value is no longer valid and you should obtain updated copy /// If true than the value is no longer valid and you should obtain updated copy
/// </summary> /// </summary>
@ -88,23 +88,14 @@ namespace Debugger
/// <summary> /// <summary>
/// Gets the subvariables of this value /// Gets the subvariables of this value
/// </summary> /// </summary>
/// <param name="getter">Delegate that will be called to get the up-to-date value</param> public virtual IEnumerable<Variable> GetSubVariables()
public virtual IEnumerable<Variable> GetSubVariables(PersistentValue pValue)
{ {
yield break; yield break;
} }
/// <summary>
/// Gets whether the given value is equivalent to this one. (ie it is may be just its other instance)
/// </summary>
public virtual bool IsEquivalentValue(Value val)
{
return val.GetType() == this.GetType();
}
public Variable this[string variableName] { public Variable this[string variableName] {
get { 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; if (v.Name == variableName) return v;
} }
throw new DebuggerException("Subvariable " + variableName + " does not exist"); throw new DebuggerException("Subvariable " + variableName + " does not exist");
@ -157,7 +148,7 @@ namespace Debugger
} }
/// <summary> /// <summary>
/// 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
/// </summary> /// </summary>
public bool IsInteger { public bool IsInteger {
get { get {

29
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Variable.cs

@ -19,7 +19,6 @@ namespace Debugger
VariableCollection subVariables; VariableCollection subVariables;
internal protected PersistentValue pValue; internal protected PersistentValue pValue;
internal Value cachedValue;
event EventHandler<DebuggerEventArgs> valueChanged; event EventHandler<DebuggerEventArgs> valueChanged;
public event EventHandler<VariableCollectionEventArgs> ValueRemovedFromCollection; public event EventHandler<VariableCollectionEventArgs> ValueRemovedFromCollection;
@ -55,15 +54,10 @@ namespace Debugger
/// </summary> /// </summary>
public Value Value { public Value Value {
get { get {
if (cachedValue == null || cachedValue.IsExpired) { Value val = pValue.Value;
cachedValue = pValue.Value; val.ValueChanged -= OnValueChanged;
if (cachedValue == null) throw new DebuggerException("ValueGetter returned null"); val.ValueChanged += OnValueChanged;
cachedValue.ValueChanged += delegate { OnValueChanged(); }; return val;
}
if (cachedValue.IsExpired) {
return new UnavailableValue(debugger, "The value has expired");
}
return cachedValue;
} }
} }
@ -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) { if (valueChanged != null) {
valueChanged(this, new VariableEventArgs(this)); 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) public Variable(NDebugger debugger, string name, PersistentValue pValue)
{ {
this.debugger = debugger; this.debugger = debugger;
@ -126,7 +109,7 @@ namespace Debugger
void OnSubVariablesUpdating(object sender, VariableCollectionEventArgs e) void OnSubVariablesUpdating(object sender, VariableCollectionEventArgs e)
{ {
subVariables.UpdateTo(Value.GetSubVariables(new PersistentValue(delegate{return this.Value;}))); subVariables.UpdateTo(Value.GetSubVariables());
} }
} }
} }

3
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 // Trasfer the new variable into the old one
if (oldVariable != newVariable) { if (oldVariable != newVariable) {
oldVariable.pValue = newVariable.pValue; oldVariable.pValue = newVariable.pValue;
oldVariable.cachedValue = null;
if (newVariable is ClassVariable && oldVariable is ClassVariable) { if (newVariable is ClassVariable && oldVariable is ClassVariable) {
((ClassVariable)oldVariable).isPublic = ((ClassVariable)oldVariable).isPublic; ((ClassVariable)oldVariable).isPublic = ((ClassVariable)oldVariable).isPublic;
((ClassVariable)oldVariable).isStatic = ((ClassVariable)oldVariable).isStatic; ((ClassVariable)oldVariable).isStatic = ((ClassVariable)oldVariable).isStatic;
} }
if (newVariable is PropertyVariable) { if (newVariable is PropertyVariable) {
newVariable.ValueChanged += delegate { oldVariable.OnValueChanged(); }; newVariable.ValueChanged += delegate { oldVariable.OnValueChanged(this, null); };
} }
} }
// Keep the variable in the list // Keep the variable in the list

Loading…
Cancel
Save