Debugger: refactor locals

git-svn-id: trunk@44207 -
This commit is contained in:
martin 2014-02-23 00:47:43 +00:00
parent 23b5437b04
commit d1cb615281
4 changed files with 605 additions and 272 deletions

View File

@ -649,38 +649,50 @@ type
******************************************************************************
******************************************************************************}
{ TLocalsBase }
// TODO: a more watch-like value object
TLocalsBase = class(TRefCountedObject)
{ TLocalsValue }
TLocalsValue = class(TDbgEntityValue)
private
FName: String;
FValue: String;
public
procedure DoAssign(AnOther: TDbgEntityValue); override;
property Name: String read FName;
property Value: String read FValue;
end;
{ TLocalsBase }
TLocalsBase = class(TDbgEntityValuesList)
private
function GetEntry(AnIndex: Integer): TLocalsValue;
function GetName(const AnIndex: Integer): String;
function GetValue(const AnIndex: Integer): String;
protected
function GetName(const AnIndex: Integer): String; virtual; abstract;
function GetStackFrame: Integer; virtual; abstract;
function GetThreadId: Integer; virtual; abstract;
function GetValue(const AnIndex: Integer): String; virtual; abstract;
function CreateEntry: TDbgEntityValue; override;
public
procedure Add(const AName, AValue: String); virtual; abstract;
procedure Clear; virtual; abstract;
procedure Add(const AName, AValue: String);
procedure SetDataValidity(AValidity: TDebuggerDataState); virtual; abstract;
function Count: Integer; virtual; abstract;
public
function Count: Integer;reintroduce; virtual;
property Entry[AnIndex: Integer]: TLocalsValue read GetEntry;
property Names[const AnIndex: Integer]: String read GetName;
property Values[const AnIndex: Integer]: String read GetValue;
property ThreadId: Integer read GetThreadId;
property StackFrame: Integer read GetStackFrame;
end;
{ TLocalsListBase }
TLocalsListBase = class
TLocalsListBase = class(TDbgEntitiesThreadStackList)
private
function GetEntry(AThreadId, AStackFrame: Integer): TLocalsBase;
function GetEntryByIdx(AnIndex: Integer): TLocalsBase;
protected
function GetEntryBase(const AThreadId: Integer; const AStackFrame: Integer): TLocalsBase; virtual; abstract;
function GetEntryByIdxBase(const AnIndex: Integer): TLocalsBase; virtual; abstract;
//function CreateEntry(AThreadId, AStackFrame: Integer): TDbgEntityValuesList; override;
public
procedure Clear; virtual; abstract;
function Count: Integer; virtual; abstract;
property EntriesByIdx[const AnIndex: Integer]: TLocalsBase read GetEntryByIdxBase;
property Entries[const AThreadId: Integer; const AStackFrame: Integer]: TLocalsBase
read GetEntryBase; default;
property EntriesByIdx[AnIndex: Integer]: TLocalsBase read GetEntryByIdx;
property Entries[AThreadId, AStackFrame: Integer]: TLocalsBase read GetEntry; default;
end;
{ TLocalsSupplier }
@ -1504,7 +1516,7 @@ type
function Evaluate(const AExpression: String; var AResult: String;
var ATypeInfo: TDBGType;
EvalFlags: TDBGEvaluateFlags = []): Boolean; // Evaluates the given expression, returns true if valid
function GetProcessList(AList: TRunningProcessInfoList): boolean; virtual;
function GetProcessList({%H-}AList: TRunningProcessInfoList): boolean; virtual;
function Modify(const AExpression, AValue: String): Boolean; // Modifies the given expression, returns true if valid
function Disassemble(AAddr: TDbgPtr; ABackward: Boolean; out ANextAddr: TDbgPtr;
out ADump, AStatement, AFile: String; out ALine: Integer): Boolean; deprecated;
@ -1712,6 +1724,65 @@ begin
end;
end;
{ TLocalsValue }
procedure TLocalsValue.DoAssign(AnOther: TDbgEntityValue);
begin
inherited DoAssign(AnOther);
FName := TLocalsValue(AnOther).FName;
FValue := TLocalsValue(AnOther).FValue;
end;
{ TLocalsListBase }
function TLocalsListBase.GetEntry(AThreadId, AStackFrame: Integer): TLocalsBase;
begin
Result := TLocalsBase(inherited Entry[AThreadId, AStackFrame]);
end;
function TLocalsListBase.GetEntryByIdx(AnIndex: Integer): TLocalsBase;
begin
Result := TLocalsBase(inherited EntryByIdx[AnIndex]);
end;
{ TLocalsBase }
function TLocalsBase.GetEntry(AnIndex: Integer): TLocalsValue;
begin
Result := TLocalsValue(inherited Entry[AnIndex]);
end;
function TLocalsBase.GetName(const AnIndex: Integer): String;
begin
Result := Entry[AnIndex].Name;
end;
function TLocalsBase.GetValue(const AnIndex: Integer): String;
begin
Result := Entry[AnIndex].Value;
end;
function TLocalsBase.CreateEntry: TDbgEntityValue;
begin
Result := TLocalsValue.Create;
end;
procedure TLocalsBase.Add(const AName, AValue: String);
var
v: TLocalsValue;
begin
assert(not Immutable, 'TLocalsBase.Add Immutable');
v := TLocalsValue(CreateEntry);
v.FName := AName;
v.FValue := AValue;
inherited Add(v);
end;
function TLocalsBase.Count: Integer;
begin
Result := inherited Count;
end;
{ TWatchesBase }
function TWatchesBase.GetItemBase(const AnIndex: Integer): TWatchBase;

View File

@ -9,6 +9,106 @@ uses
type
(* TDbgEntityValue are created with a refcount of 0 (zero)
*)
TDbgEntityValuesList = class;
TDbgEntitiesThreadStackList = class;
{ TDbgEntityValue
Locals, Watches, Registers
}
TDbgEntityValue = class(TRefCountedObject)
private
FOwner: TDbgEntityValuesList;
FFlags: set of (devImmutable);
function GetImmutable: Boolean;
function GetStackFrame: Integer;
function GetThreadId: Integer;
procedure SetImmutable(AValue: Boolean);
protected
procedure DoAssign({%H-}AnOther: TDbgEntityValue); virtual;
property Owner: TDbgEntityValuesList read FOwner;
public
procedure Assign({%H-}AnOther: TDbgEntityValue);
property ThreadId: Integer read GetThreadId;
property StackFrame: Integer read GetStackFrame;
property Immutable: Boolean read GetImmutable write SetImmutable; // mainly used by assert
end;
{ TDbgEntityValuesList
All Values for a specifer Thread/StackFrame
}
TDbgEntityValuesList = class(TRefCountedObject)
private
FStackFrame: Integer;
FThreadId: Integer;
FFlags: set of (devlImmutable);
FList: TRefCntObjList;
FOwner: TDbgEntitiesThreadStackList;
function GetEntry(AnIndex: Integer): TDbgEntityValue;
function GetImmutable: Boolean;
procedure SetImmutable(AValue: Boolean);
protected
function CreateEntry: TDbgEntityValue; virtual; abstract;
procedure DoAssign(AnOther: TDbgEntityValuesList); virtual; // assert other has same thread/stack
procedure DoAssignListContent(AnOther: TDbgEntityValuesList); virtual; // assert other has same thread/stack
procedure DoCleared; virtual;
procedure DoAdded({%H-}AnEntry: TDbgEntityValue); virtual;
procedure Init; virtual;
property Owner: TDbgEntitiesThreadStackList read FOwner;
public
constructor Create(AThreadId, AStackFrame: Integer);
destructor Destroy; override;
procedure Assign(AnOther: TDbgEntityValuesList); // assert other has same thread/stack
procedure Add(AnEntry: TDbgEntityValue);
procedure Clear;
function Count: Integer;
property Entry[AnIndex: Integer]: TDbgEntityValue read GetEntry;
property ThreadId: Integer read FThreadId;
property StackFrame: Integer read FStackFrame;
property Immutable: Boolean read GetImmutable write SetImmutable; // mainly used by assert
end;
TDbgValuesThreadList = record
ThreadId: Integer;
List: TRefCntObjList;
end;
{ TDbgEntitiesThreadStackList }
TDbgEntitiesThreadStackList = class(TRefCountedObject)
private
FList: array of TDbgValuesThreadList;
FFlags: set of (devtsImmutable);
function GetEntry(AThreadId, AStackFrame: Integer): TDbgEntityValuesList;
function GetEntryByIdx(AnIndex: Integer): TDbgEntityValuesList;
function GetHasEntry(AThreadId, AStackFrame: Integer): Boolean;
function GetImmutable: Boolean;
function IndexOfThread(AThreadId: Integer; ACreateSubList: Boolean = False): Integer;
procedure SetImmutable(AValue: Boolean);
protected
function CreateEntry(AThreadId, AStackFrame: Integer): TDbgEntityValuesList; virtual; abstract;
procedure DoAssign(AnOther: TDbgEntitiesThreadStackList); virtual;
procedure DoAssignListContent(AnOther: TDbgEntitiesThreadStackList); virtual;
procedure DoCleared; virtual;
procedure DoAdded({%H-}AnEntry: TDbgEntityValuesList); virtual;
public
destructor Destroy; override;
procedure Assign(AnOther: TDbgEntitiesThreadStackList);
procedure Add(AnEntry: TDbgEntityValuesList);
procedure Clear;
function Count: Integer;
property EntryByIdx[AnIndex: Integer]: TDbgEntityValuesList read GetEntryByIdx;
// Entries will automatically be created
property Entry[AThreadId, AStackFrame: Integer]: TDbgEntityValuesList read GetEntry; default;
property HasEntry[AThreadId, AStackFrame: Integer]: Boolean read GetHasEntry;
property Immutable: Boolean read GetImmutable write SetImmutable; // used by assert
end;
{ TDelayedUdateItem }
TDelayedUdateItem = class(TCollectionItem)
@ -65,6 +165,302 @@ begin
Pointer(ARefCountedObject) := nil;
end;
{ TDbgEntityValue }
function TDbgEntityValue.GetImmutable: Boolean;
begin
Result := (devImmutable in FFlags) or ((FOwner <> nil) and FOwner.Immutable);
end;
function TDbgEntityValue.GetStackFrame: Integer;
begin
Result := FOwner.StackFrame;
end;
function TDbgEntityValue.GetThreadId: Integer;
begin
Result := FOwner.ThreadId;
end;
procedure TDbgEntityValue.SetImmutable(AValue: Boolean);
begin
assert((AValue = True) or not(Immutable), 'TDbgEntityValue.SetImmutable Not allowed to set to false');
if AValue then Include(FFlags, devImmutable);
end;
procedure TDbgEntityValue.DoAssign(AnOther: TDbgEntityValue);
begin
//
end;
procedure TDbgEntityValue.Assign(AnOther: TDbgEntityValue);
begin
Assert(not Immutable, 'TDbgEntityValue.Assign Immutable');
DoAssign(AnOther);
end;
{ TDbgEntityValuesList }
function TDbgEntityValuesList.GetImmutable: Boolean;
begin
Result := devlImmutable in FFlags;
end;
function TDbgEntityValuesList.GetEntry(AnIndex: Integer): TDbgEntityValue;
begin
Result := TDbgEntityValue(FList[AnIndex]);
end;
procedure TDbgEntityValuesList.SetImmutable(AValue: Boolean);
begin
assert((AValue = True) or not(devlImmutable in FFlags), 'TDbgEntityValuesList.SetImmutable Not allowed to set to false');
if AValue then Include(FFlags, devlImmutable);
end;
procedure TDbgEntityValuesList.DoCleared;
begin
//
end;
procedure TDbgEntityValuesList.DoAdded(AnEntry: TDbgEntityValue);
begin
end;
procedure TDbgEntityValuesList.Init;
begin
//
end;
constructor TDbgEntityValuesList.Create(AThreadId, AStackFrame: Integer);
begin
inherited Create;
FFlags := [];
FThreadId := AThreadId;
FStackFrame := AStackFrame;
FList := TRefCntObjList.Create;
Init;
end;
destructor TDbgEntityValuesList.Destroy;
begin
Exclude(FFlags, devlImmutable);
Clear;
FList.Free;
inherited Destroy;
end;
procedure TDbgEntityValuesList.DoAssign(AnOther: TDbgEntityValuesList);
begin
DoAssignListContent(AnOther);
end;
procedure TDbgEntityValuesList.DoAssignListContent(AnOther: TDbgEntityValuesList);
var
e: TDbgEntityValue;
i: Integer;
begin
for i := 0 to AnOther.FList.Count - 1 do begin
e := CreateEntry;
e.FOwner := Self;
e.Assign(TDbgEntityValue(AnOther.FList[i]));
FList.Add(e);
end;
end;
procedure TDbgEntityValuesList.Assign(AnOther: TDbgEntityValuesList);
begin
Assert(not Immutable, 'TDbgEntityValuesList.Assign Immutable');
Assert((FThreadId = AnOther.FThreadId) and (FStackFrame = AnOther.FStackFrame), 'TDbgEntityValuesList.Assign same thread and stack');
Clear;
DoAssign(AnOther);
end;
procedure TDbgEntityValuesList.Add(AnEntry: TDbgEntityValue);
begin
Assert(not Immutable, 'TDbgEntityValuesList.Add Immutable');
AnEntry.FOwner := Self;
FList.Add(AnEntry);
DoAdded(AnEntry);
end;
procedure TDbgEntityValuesList.Clear;
begin
Assert(not Immutable, 'TDbgEntityValuesList.Clear Immutable');
FList.Clear;
DoCleared;
end;
function TDbgEntityValuesList.Count: Integer;
begin
Result := FList.Count;
end;
{ TDbgEntitiesThreadStackList }
function TDbgEntitiesThreadStackList.GetEntry(AThreadId, AStackFrame: Integer): TDbgEntityValuesList;
var
i, j: Integer;
begin
i := IndexOfThread(AThreadId);
if i >= 0 then begin
// TODO: binary search / need sorted list
for j := 0 to FList[i].List.Count - 1 do begin
Result := TDbgEntityValuesList(FList[i].List[j]);
if Result.StackFrame = AStackFrame then
exit;
end;
end;
if Immutable then begin
Result := nil;
exit;
end;
Result := CreateEntry(AThreadId, AStackFrame);
Add(Result);
end;
function TDbgEntitiesThreadStackList.GetEntryByIdx(AnIndex: Integer): TDbgEntityValuesList;
var
i: Integer;
begin
Result := nil;
i := 0;
while AnIndex >= FList[i].List.Count do begin
dec(AnIndex, FList[i].List.Count);
inc(i);
if i >= Length(FList) then
exit;
end;
Result := TDbgEntityValuesList(FList[i].List[AnIndex]);
end;
function TDbgEntitiesThreadStackList.GetHasEntry(AThreadId, AStackFrame: Integer): Boolean;
var
i, j: Integer;
begin
Result := False;
i := IndexOfThread(AThreadId);
if i < 0 then exit;
// TODO: binary search / need sorted list
for j := 0 to FList[i].List.Count - 1 do begin
if TDbgEntityValuesList(FList[i].List[j]).StackFrame = AStackFrame then begin
Result := True;
exit;
end;
end;
end;
function TDbgEntitiesThreadStackList.GetImmutable: Boolean;
begin
Result := devtsImmutable in FFlags;
end;
function TDbgEntitiesThreadStackList.IndexOfThread(AThreadId: Integer;
ACreateSubList: Boolean): Integer;
begin
Result := length(FList) - 1;
while (Result >= 0) and (FList[Result].ThreadId <> AThreadId) do
dec(Result);
if (Result >= 0) or (not ACreateSubList) then
exit;
Result := length(FList);
SetLength(FList, Result + 1);
FList[Result].ThreadId := AThreadId;
FList[Result].List := TRefCntObjList.Create;
end;
procedure TDbgEntitiesThreadStackList.SetImmutable(AValue: Boolean);
begin
assert((AValue = True) or not(devtsImmutable in FFlags), 'TDbgEntityValuesList.SetImmutable Not allowed to set to false');
if AValue then Include(FFlags, devtsImmutable);
end;
procedure TDbgEntitiesThreadStackList.DoCleared;
begin
//
end;
procedure TDbgEntitiesThreadStackList.DoAdded(AnEntry: TDbgEntityValuesList);
begin
//
end;
destructor TDbgEntitiesThreadStackList.Destroy;
begin
Exclude(FFlags, devtsImmutable);
Clear;
inherited Destroy;
end;
procedure TDbgEntitiesThreadStackList.DoAssign(AnOther: TDbgEntitiesThreadStackList);
begin
DoAssignListContent(AnOther);
end;
procedure TDbgEntitiesThreadStackList.DoAssignListContent(AnOther: TDbgEntitiesThreadStackList);
var
i, j: Integer;
t: Integer;
e, o: TDbgEntityValuesList;
begin
SetLength(FList, length(AnOther.FList));
for i := 0 to Length(FList) - 1 do begin
t := AnOther.FList[i].ThreadId;
FList[i].ThreadId := t;
FList[i].List := TRefCntObjList.Create;
for j := 0 to AnOther.FList[i].List.Count - 1 do begin
o := TDbgEntityValuesList(AnOther.FList[i].List[j]);
e := CreateEntry(t, o.StackFrame);
e.FOwner := Self;
e.Assign(o);
FList[i].List.Add(e);
end;
end;
end;
procedure TDbgEntitiesThreadStackList.Assign(AnOther: TDbgEntitiesThreadStackList);
begin
Assert(not Immutable, 'TDbgEntitiesThreadStackList.Assign Immutable');
Clear;
DoAssign(AnOther);
end;
procedure TDbgEntitiesThreadStackList.Add(AnEntry: TDbgEntityValuesList);
var
i: Integer;
begin
Assert(not Immutable, 'TDbgEntitiesThreadStackList.Add Immutable');
Assert((AnEntry.FOwner = nil) or (AnEntry.FOwner = Self), 'TDbgEntitiesThreadStackList.Add Entry.FThreadStackList');
AnEntry.FOwner := Self;
i := IndexOfThread(AnEntry.ThreadId, True);
FList[i].List.Add(AnEntry);
DoAdded(AnEntry);
end;
procedure TDbgEntitiesThreadStackList.Clear;
var
i: Integer;
begin
Assert(not Immutable, 'TDbgEntitiesThreadStackList.Clear Immutable');
for i := 0 to Length(FList) - 1 do
FList[i].List.Free;
SetLength(FList, 0);
DoCleared;
end;
function TDbgEntitiesThreadStackList.Count: Integer;
var
i: Integer;
begin
Result := 0;
for i := 0 to Length(FList) - 1 do
Result := Result + FList[i].List.Count;
end;
{ TDelayedUdateItem }

View File

@ -869,93 +869,72 @@ type
{ TLocals }
TLocals = class(TLocalsBase)
private
FLocals: TStringList;
FStackFrame: Integer;
FThreadId: Integer;
{ TIDELocals }
TIDELocals = class(TLocalsBase)
protected
function GetThreadId: Integer; override;
function GetStackFrame: Integer; override;
function GetName(const AnIndex: Integer): String; override;
function GetValue(const AnIndex: Integer): String; override;
procedure LoadDataFromXMLConfig(const AConfig: TXMLConfig;
APath: string);
procedure SaveDataToXMLConfig(const AConfig: TXMLConfig;
APath: string);
public
procedure Assign(AnOther: TLocals);
constructor Create;
constructor Create(AThreadId, AStackFrame: Integer);
constructor CreateCopy(const ASource: TLocals);
destructor Destroy; override;
procedure Add(const AName, AValue: String); override;
procedure Clear; override;
constructor CreateFromXMLConfig(const AConfig: TXMLConfig; APath: string);
procedure SetDataValidity(AValidity: TDebuggerDataState); override;
function Count: Integer; override;
public
property Names[const AnIndex: Integer]: String read GetName;
property Values[const AnIndex: Integer]: String read GetValue;
property ThreadId: Integer read FThreadId;
property StackFrame: Integer read FStackFrame;
end;
{ TLocalsList }
TLocalsList = class(TLocalsListBase)
private
FList: TList;
function GetEntry(const AThreadId: Integer; const AStackFrame: Integer): TLocals;
function GetEntryByIdx(const AnIndex: Integer): TLocals;
protected
function GetEntryBase(const AThreadId: Integer; const AStackFrame: Integer): TLocalsBase; override;
function GetEntryByIdxBase(const AnIndex: Integer): TLocalsBase; override;
function CreateEntry(const {%H-}AThreadId: Integer; const {%H-}AStackFrame: Integer): TLocals; virtual;
procedure Add(AnEntry: TLocals);
procedure LoadDataFromXMLConfig(const AConfig: TXMLConfig;
APath: string);
procedure SaveDataToXMLConfig(const AConfig: TXMLConfig;
APath: string);
public
constructor Create;
destructor Destroy; override;
procedure Assign(AnOther: TLocalsList);
procedure Clear; override;
function Count: Integer; override;
property EntriesByIdx[const AnIndex: Integer]: TLocals read GetEntryByIdx;
property Entries[const AThreadId: Integer; const AStackFrame: Integer]: TLocals
read GetEntry; default;
end;
{ TCurrentLocals }
TCurrentLocals = class(TLocals)
TCurrentLocals = class(TIDELocals)
private
FMonitor: TLocalsMonitor;
FSnapShot: TLocals;
FSnapShot: TIDELocals;
FDataValidity: TDebuggerDataState;
procedure SetSnapShot(const AValue: TLocals);
procedure SetSnapShot(const AValue: TIDELocals);
protected
property SnapShot: TLocals read FSnapShot write SetSnapShot;
property SnapShot: TIDELocals read FSnapShot write SetSnapShot;
public
constructor Create(AMonitor: TLocalsMonitor; AThreadId, AStackFrame: Integer);
function Count: Integer; override;
procedure SetDataValidity(AValidity: TDebuggerDataState); override;
end;
{ TLocalsList }
{ TIDELocalsList }
TIDELocalsList = class(TLocalsListBase)
private
function GetEntry(const AThreadId: Integer; const AStackFrame: Integer): TIDELocals;
function GetEntryByIdx(const AnIndex: Integer): TIDELocals;
protected
function CreateEntry(AThreadId, AStackFrame: Integer): TDbgEntityValuesList; override;
procedure DoAssign(AnOther: TDbgEntitiesThreadStackList); override;
procedure DoAdded(AnEntry: TDbgEntityValuesList); override;
procedure LoadDataFromXMLConfig(const AConfig: TXMLConfig;
APath: string);
procedure SaveDataToXMLConfig(const AConfig: TXMLConfig;
APath: string);
public
property EntriesByIdx[const AnIndex: Integer]: TIDELocals read GetEntryByIdx;
property Entries[const AThreadId: Integer; const AStackFrame: Integer]: TIDELocals
read GetEntry; default;
end;
{ TCurrentLocalsList }
TCurrentLocalsList = class(TLocalsList)
TCurrentLocalsList = class(TIDELocalsList)
private
FMonitor: TLocalsMonitor;
FSnapShot: TLocalsList;
procedure SetSnapShot(const AValue: TLocalsList);
FSnapShot: TIDELocalsList;
procedure SetSnapShot(const AValue: TIDELocalsList);
protected
function CreateEntry(const AThreadId: Integer; const AStackFrame: Integer): TLocals; override;
property SnapShot: TLocalsList read FSnapShot write SetSnapShot;
procedure DoCleared; override;
procedure DoAdded(AnEntry: TDbgEntityValuesList); override;
function CreateEntry(AThreadId, AStackFrame: Integer): TIDELocals; override;
property SnapShot: TIDELocalsList read FSnapShot write SetSnapShot;
public
constructor Create(AMonitor: TLocalsMonitor);
procedure Clear; override;
end;
{ TLocalsMonitor }
@ -964,7 +943,7 @@ type
private
FCurrentLocalsList: TCurrentLocalsList;
FNotificationList: TDebuggerChangeNotificationList;
function GetSnapshot(AnID: Pointer): TLocalsList;
function GetSnapshot(AnID: Pointer): TIDELocalsList;
function GetSupplier: TLocalsSupplier;
procedure SetSupplier(const AValue: TLocalsSupplier);
protected
@ -982,7 +961,7 @@ type
procedure AddNotification(const ANotification: TLocalsNotification);
procedure RemoveNotification(const ANotification: TLocalsNotification);
property CurrentLocalsList: TCurrentLocalsList read FCurrentLocalsList;
property Snapshots[AnID: Pointer]: TLocalsList read GetSnapshot;
property Snapshots[AnID: Pointer]: TIDELocalsList read GetSnapshot;
property Supplier: TLocalsSupplier read GetSupplier write SetSupplier;
end;
@ -3147,13 +3126,17 @@ end;
{ TCurrentLocalsList }
procedure TCurrentLocalsList.SetSnapShot(const AValue: TLocalsList);
procedure TCurrentLocalsList.SetSnapShot(const AValue: TIDELocalsList);
var
i: Integer;
R: TLocals;
E, R: TIDELocals;
begin
assert((FSnapShot=nil) or (AValue=nil), 'TCurrentLocalsList already have snapshot');
if FSnapShot = AValue then exit;
if FSnapShot <> nil then
FSnapShot.Immutable := True;
FSnapShot := AValue;
if FSnapShot = nil then begin
@ -3163,102 +3146,89 @@ begin
//FSnapShot.Assign(Self);
FSnapShot.Clear;
for i := 0 to Count-1 do begin
R := TLocals.Create;
E := EntriesByIdx[i];
R := TIDELocals.Create(e.ThreadId, e.StackFrame);
FSnapShot.Add(R);
TCurrentLocals(EntriesByIdx[i]).SnapShot := R;
TCurrentLocals(E).SnapShot := R;
end;
end;
end;
function TCurrentLocalsList.CreateEntry(const AThreadId: Integer;
const AStackFrame: Integer): TLocals;
var
R: TLocals;
procedure TCurrentLocalsList.DoCleared;
begin
Result := TCurrentLocals.Create(FMonitor, AThreadId, AStackFrame);
Add(Result);
FMonitor.NotifyChange(nil);
end;
procedure TCurrentLocalsList.DoAdded(AnEntry: TDbgEntityValuesList);
var
R: TIDELocals;
begin
Assert(AnEntry is TCurrentLocals, 'TCurrentLocalsList.DoAdded');
inherited DoAdded(AnEntry);
if FSnapShot <> nil
then begin
R := TLocals.Create(AThreadId, AStackFrame);
R := TIDELocals.Create(AnEntry.ThreadId, AnEntry.StackFrame);
FSnapShot.Add(R);
TCurrentLocals(Result).SnapShot := R;
TCurrentLocals(AnEntry).SnapShot := R;
end;
end;
function TCurrentLocalsList.CreateEntry(AThreadId, AStackFrame: Integer): TIDELocals;
begin
Result := TCurrentLocals.Create(FMonitor, AThreadId, AStackFrame);
end;
constructor TCurrentLocalsList.Create(AMonitor: TLocalsMonitor);
begin
FMonitor := AMonitor;
inherited Create;
end;
procedure TCurrentLocalsList.Clear;
begin
inherited Clear;
FMonitor.NotifyChange(nil);
end;
{ TLocalsList }
function TLocalsList.GetEntry(const AThreadId: Integer; const AStackFrame: Integer): TLocals;
function TIDELocalsList.GetEntry(const AThreadId: Integer; const AStackFrame: Integer): TIDELocals;
begin
Result := TIDELocals(inherited Entry[AThreadId, AStackFrame]);
end;
function TIDELocalsList.GetEntryByIdx(const AnIndex: Integer): TIDELocals;
begin
Result := TIDELocals(inherited EntryByIdx[AnIndex]);
end;
function TIDELocalsList.CreateEntry(AThreadId, AStackFrame: Integer): TDbgEntityValuesList;
begin
Result := TIDELocals.Create(AThreadId, AStackFrame);
end;
procedure TIDELocalsList.DoAssign(AnOther: TDbgEntitiesThreadStackList);
begin
inherited DoAssign(AnOther);
Immutable := not(Self is TCurrentLocalsList);
end;
procedure TIDELocalsList.DoAdded(AnEntry: TDbgEntityValuesList);
begin
inherited DoAdded(AnEntry);
//AnEntry.Immutable := not(Self is TCurrentLocalsList);
end;
procedure TIDELocalsList.LoadDataFromXMLConfig(const AConfig: TXMLConfig; APath: string);
var
i: Integer;
begin
i := FList.Count - 1;
while i >= 0 do begin
Result := TLocals(FList[i]);
if (Result.ThreadId = AThreadId) and (Result.StackFrame = AStackFrame)
then exit;
dec(i);
end;
Result := CreateEntry(AThreadId, AStackFrame);
end;
function TLocalsList.GetEntryByIdx(const AnIndex: Integer): TLocals;
begin
Result := TLocals(FList[AnIndex]);
end;
function TLocalsList.GetEntryBase(const AThreadId: Integer;
const AStackFrame: Integer): TLocalsBase;
begin
Result := TLocalsBase(GetEntry(AThreadId, AStackFrame));
end;
function TLocalsList.GetEntryByIdxBase(const AnIndex: Integer): TLocalsBase;
begin
Result := TLocalsBase(GetEntryByIdx(AnIndex));
end;
function TLocalsList.CreateEntry(const AThreadId: Integer;
const AStackFrame: Integer): TLocals;
begin
Result := nil;
end;
procedure TLocalsList.Add(AnEntry: TLocals);
begin
assert(((Self is TCurrentLocalsList) and (AnEntry is TCurrentLocals)) or ((not(Self is TCurrentLocalsList)) and not(AnEntry is TCurrentLocals)),
'TLocalsList.Add: entry and list differ (current and none current)');
FList.add(AnEntry);
end;
procedure TLocalsList.LoadDataFromXMLConfig(const AConfig: TXMLConfig; APath: string);
var
e: TLocals;
e: TIDELocals;
c, i: Integer;
begin
Clear;
c := AConfig.GetValue(APath + 'Count', 0);
APath := APath + 'LocalsEntry';
for i := 0 to c - 1 do begin
e := TLocals.Create;
e.LoadDataFromXMLConfig(AConfig, APath + IntToStr(i) + '/');
e := TIDELocals.CreateFromXMLConfig(AConfig, APath + IntToStr(i) + '/');
Add(e);
end;
end;
procedure TLocalsList.SaveDataToXMLConfig(const AConfig: TXMLConfig; APath: string);
procedure TIDELocalsList.SaveDataToXMLConfig(const AConfig: TXMLConfig; APath: string);
var
i: Integer;
begin
@ -3268,41 +3238,6 @@ begin
EntriesByIdx[i].SaveDataToXMLConfig(AConfig, APath + IntToStr(i) + '/');
end;
procedure TLocalsList.Assign(AnOther: TLocalsList);
var
i: Integer;
begin
Clear;
for i := 0 to AnOther.FList.Count-1 do
FList.Add(TLocals.CreateCopy(TLocals(AnOther.FList[i])));
end;
constructor TLocalsList.Create;
begin
FList := TList.Create;
inherited Create;
end;
destructor TLocalsList.Destroy;
begin
Clear;
inherited Destroy;
FList.Free;
end;
procedure TLocalsList.Clear;
begin
while FList.Count > 0 do begin
TRefCountedObject(FList[0]).ReleaseReference;
FList.Delete(0);
end;
end;
function TLocalsList.Count: Integer;
begin
Result := FList.Count;
end;
{ TLocalsMonitor }
function TLocalsMonitor.GetSupplier: TLocalsSupplier;
@ -3310,9 +3245,9 @@ begin
Result := TLocalsSupplier(inherited Supplier);
end;
function TLocalsMonitor.GetSnapshot(AnID: Pointer): TLocalsList;
function TLocalsMonitor.GetSnapshot(AnID: Pointer): TIDELocalsList;
begin
Result := TLocalsList(GetSnapshotObj(AnID));
Result := TIDELocalsList(GetSnapshotObj(AnID));
end;
procedure TLocalsMonitor.SetSupplier(const AValue: TLocalsSupplier);
@ -3364,9 +3299,9 @@ end;
function TLocalsMonitor.CreateSnapshot(CreateEmpty: Boolean = False): TObject;
begin
Result := TLocalsList.Create;
Result := TIDELocalsList.Create;
if not CreateEmpty
then CurrentLocalsList.SnapShot := TLocalsList(Result);
then CurrentLocalsList.SnapShot := TIDELocalsList(Result);
end;
constructor TLocalsMonitor.Create;
@ -6322,99 +6257,29 @@ end;
{ TLocals }
{ =========================================================================== }
function TLocals.Count: Integer;
begin
Result := FLocals.Count;
end;
constructor TLocals.Create;
begin
FLocals := TStringList.Create;
inherited Create;
AddReference;
end;
constructor TLocals.Create(AThreadId, AStackFrame: Integer);
begin
Create;
FThreadId := AThreadId;
FStackFrame := AStackFrame;
end;
constructor TLocals.CreateCopy(const ASource: TLocals);
begin
Create;
Assign(ASource);
end;
destructor TLocals.Destroy;
begin
inherited Destroy;
FreeAndNil(FLocals);
end;
procedure TLocals.Add(const AName, AValue: String);
begin
assert(Self is TCurrentLocals, 'TLocals.Add');
FLocals.Add(AName + '=' + AValue);
end;
procedure TLocals.Clear;
begin
assert(Self is TCurrentLocals, 'TLocals.Clear');
FLocals.Clear;
end;
procedure TLocals.SetDataValidity(AValidity: TDebuggerDataState);
procedure TIDELocals.SetDataValidity(AValidity: TDebuggerDataState);
begin
assert(Self is TCurrentLocals, 'TLocals.SetDataValidity');
end;
function TLocals.GetThreadId: Integer;
begin
Result := FThreadId;
end;
function TLocals.GetStackFrame: Integer;
begin
Result := FStackFrame;
end;
function TLocals.GetName(const AnIndex: Integer): String;
begin
Result := FLocals.Names[AnIndex];
end;
function TLocals.GetValue(const AnIndex: Integer): String;
begin
Result := FLocals[AnIndex];
Result := GetPart('=', '', Result);
end;
procedure TLocals.LoadDataFromXMLConfig(const AConfig: TXMLConfig; APath: string);
procedure TIDELocals.LoadDataFromXMLConfig(const AConfig: TXMLConfig; APath: string);
var
c, i: Integer;
begin
FLocals.Clear;
FThreadId := AConfig.GetValue(APath + 'ThreadId', -1);
FStackFrame := AConfig.GetValue(APath + 'StackFrame', -1);
c := AConfig.GetValue(APath + 'Count', 0);
APath := APath + 'Entry';
for i := 0 to c - 1 do begin
FLocals.Add(
AConfig.GetValue(APath + IntToStr(i) + '/Expression', '')
+ '=' +
AConfig.GetValue(APath + IntToStr(i) + '/Value', '')
);
Add(AConfig.GetValue(APath + IntToStr(i) + '/Expression', ''),
AConfig.GetValue(APath + IntToStr(i) + '/Value', ''));
end;
end;
procedure TLocals.SaveDataToXMLConfig(const AConfig: TXMLConfig; APath: string);
procedure TIDELocals.SaveDataToXMLConfig(const AConfig: TXMLConfig; APath: string);
var
i: Integer;
begin
AConfig.SetValue(APath + 'ThreadId', FThreadId);
AConfig.SetValue(APath + 'StackFrame', FStackFrame);
AConfig.SetValue(APath + 'ThreadId', ThreadId);
AConfig.SetValue(APath + 'StackFrame', StackFrame);
AConfig.SetDeleteValue(APath + 'Count', Count, 0);
APath := APath + 'Entry';
for i := 0 to Count - 1 do begin
@ -6423,18 +6288,21 @@ begin
end;
end;
procedure TLocals.Assign(AnOther: TLocals);
constructor TIDELocals.CreateFromXMLConfig(const AConfig: TXMLConfig; APath: string);
var
LoadThreadId, LoadStackFrame: Integer;
begin
FThreadId := AnOther.FThreadId;
FStackFrame := AnOther.FStackFrame;
FLocals.Assign(AnOther.FLocals);
LoadThreadId := AConfig.GetValue(APath + 'ThreadId', -1);
LoadStackFrame := AConfig.GetValue(APath + 'StackFrame', -1);
Create(LoadThreadId, LoadStackFrame);
LoadDataFromXMLConfig(AConfig, APath);
end;
{ =========================================================================== }
{ TCurrentLocals }
{ =========================================================================== }
procedure TCurrentLocals.SetSnapShot(const AValue: TLocals);
procedure TCurrentLocals.SetSnapShot(const AValue: TIDELocals);
begin
assert((FSnapShot=nil) or (AValue=nil), 'TCurrentLocals already have snapshot');
if FSnapShot = AValue then exit;
@ -6447,9 +6315,7 @@ constructor TCurrentLocals.Create(AMonitor: TLocalsMonitor; AThreadId, AStackFra
begin
FMonitor := AMonitor;
FDataValidity := ddsUnknown;
FThreadId := AThreadId;
FStackFrame := AStackFrame;
inherited Create;
inherited Create(AThreadId, AStackFrame);
end;
function TCurrentLocals.Count: Integer;

View File

@ -189,7 +189,7 @@ var
List: TStringList;
Item: TListItem;
S: String;
Locals: TLocals;
Locals: TIDELocals;
Snap: TSnapshot;
begin
if (ThreadsMonitor = nil) or (CallStackMonitor = nil) or (LocalsMonitor=nil) then begin