FPDebug: refactor circular references

git-svn-id: trunk@43862 -
This commit is contained in:
martin 2014-01-31 19:41:49 +00:00
parent d82c0c96c4
commit d4ee8f0e73
2 changed files with 163 additions and 93 deletions

View File

@ -658,7 +658,6 @@ type
// FOwnerTypeInfo: TDbgDwarfIdentifier;
FNestedTypeInfo: TDbgDwarfTypeIdentifier;
FParentTypeInfo: TDbgDwarfIdentifier;
FRefByParentCount: Integer;
FDwarfReadFlags: set of (didtNameRead, didtTypeRead, didtArtificialRead, didtIsArtifical);
function GetNestedTypeInfo: TDbgDwarfTypeIdentifier;
protected
@ -666,10 +665,7 @@ type
"self" will only set its reference to parenttype, if self has other references. *)
procedure DoReferenceAdded; override;
procedure DoReferenceReleased; override;
procedure IncRefByParentCount;
procedure DecRefByParentCount;
function RefToParentActive: Boolean; inline;
procedure RefToParentChanged; virtual;
procedure CircleBackRefActiveChanged(ANewActive: Boolean); override;
procedure SetParentTypeInfo(AValue: TDbgDwarfIdentifier); virtual;
function DoGetNestedTypeInfo: TDbgDwarfTypeIdentifier; virtual;
@ -687,7 +683,7 @@ type
protected
// TODO: InitLocationParser may fail
procedure InitLocationParser(const ALocationParser: TDwarfLocationExpression; AnObjectDataAddress: TDbgPtr = nil); virtual;
procedure InitLocationParser(const {%H-}ALocationParser: TDwarfLocationExpression; {%H-}AnObjectDataAddress: TDbgPtr = nil); virtual;
function LocationFromTag(ATag: Cardinal; out AnAddress: TDbgPtr;
AnObjectDataAddress: TDbgPtr = 0;
AnInformationEntry: TDwarfInformationEntry = nil
@ -711,6 +707,7 @@ type
TDbgDwarfValueIdentifier = class(TDbgDwarfIdentifier) // var, const, member, ...
protected
FValueObject: TDbgDwarfSymbolValue;
FMembers: TFpDbgCircularRefCntObjList;
function GetDataAddress(out AnAddress: TDbgPtr; ATargetType: TDbgDwarfTypeIdentifier = nil): Boolean; reintroduce;
procedure KindNeeded; override;
@ -906,7 +903,7 @@ DECL = DW_AT_decl_column, DW_AT_decl_file, DW_AT_decl_line
TDbgDwarfIdentifierEnum = class(TDbgDwarfTypeIdentifier)
private
FMembers: TRefCntObjList;
FMembers: TFpDbgCircularRefCntObjList;
procedure CreateMembers;
protected
procedure KindNeeded; override;
@ -969,7 +966,7 @@ DECL = DW_AT_decl_column, DW_AT_decl_file, DW_AT_decl_line
protected
procedure InitLocationParser(const ALocationParser: TDwarfLocationExpression; AnObjectDataAddress: TDbgPtr = nil); override;
procedure AddressNeeded; override;
procedure RefToParentChanged; override;
procedure CircleBackRefActiveChanged(ANewActive: Boolean); override;
procedure SetParentTypeInfo(AValue: TDbgDwarfIdentifier); override;
public
destructor Destroy; override;
@ -981,7 +978,7 @@ DECL = DW_AT_decl_column, DW_AT_decl_file, DW_AT_decl_line
TDbgDwarfIdentifierStructure = class(TDbgDwarfTypeIdentifier)
// record or class
private
FMembers: TRefCntObjList;
FMembers: TFpDbgCircularRefCntObjList;
FLastChildByName: TDbgDwarfIdentifier;
FInheritanceInfo: TDwarfInformationEntry;
procedure CreateMembers;
@ -1005,7 +1002,7 @@ DECL = DW_AT_decl_column, DW_AT_decl_file, DW_AT_decl_line
TDbgDwarfIdentifierArray = class(TDbgDwarfTypeIdentifier)
private
FMembers: TRefCntObjList;
FMembers: TFpDbgCircularRefCntObjList;
procedure CreateMembers;
protected
procedure KindNeeded; override;
@ -1810,12 +1807,12 @@ procedure TDbgDwarfIdentifierMember.SetStructureValueInfo(AValue: TDbgDwarfValue
begin
if FStructureValueInfo = AValue then Exit;
if (FStructureValueInfo <> nil) and RefToParentActive then
if (FStructureValueInfo <> nil) and CircleBackRefsActive then
FStructureValueInfo.ReleaseReference{$IFDEF WITH_REFCOUNT_DEBUG}(@FStructureValueInfo, 'FStructureValueInfo'){$ENDIF};
FStructureValueInfo := AValue;
if (FStructureValueInfo <> nil) and RefToParentActive then
if (FStructureValueInfo <> nil) and CircleBackRefsActive then
FStructureValueInfo.AddReference{$IFDEF WITH_REFCOUNT_DEBUG}(@FStructureValueInfo, 'FStructureValueInfo'){$ENDIF};
end;
@ -1854,12 +1851,12 @@ DebugLnEnter(['>>> TDbgDwarfIdentifierMember.AddressNeeded ']);
DebugLnExit(['<<< ',t]);
end;
procedure TDbgDwarfIdentifierMember.RefToParentChanged;
procedure TDbgDwarfIdentifierMember.CircleBackRefActiveChanged(ANewActive: Boolean);
begin
inherited RefToParentChanged;
inherited;
if (FStructureValueInfo = nil) then
exit;
if RefToParentActive then
if ANewActive then
FStructureValueInfo.AddReference{$IFDEF WITH_REFCOUNT_DEBUG}(@FStructureValueInfo, 'FStructureValueInfo'){$ENDIF}
else
FStructureValueInfo.ReleaseReference{$IFDEF WITH_REFCOUNT_DEBUG}(@FStructureValueInfo, 'FStructureValueInfo'){$ENDIF};
@ -1874,8 +1871,8 @@ end;
destructor TDbgDwarfIdentifierMember.Destroy;
begin
if RefToParentActive then
FStructureValueInfo.ReleaseReference{$IFDEF WITH_REFCOUNT_DEBUG}(@FStructureValueInfo, 'FStructureValueInfo'){$ENDIF};
Assert(not CircleBackRefsActive, 'CircleBackRefsActive can not be is ddestructor');
// FStructureValueInfo := nil;
inherited Destroy;
end;
@ -4027,7 +4024,7 @@ var
begin
if FMembers <> nil then
exit;
FMembers := TRefCntObjList.Create;
FMembers := TFpDbgCircularRefCntObjList.Create;
Info := FInformationEntry.FirstChild;
if Info = nil then exit;
@ -4037,7 +4034,6 @@ begin
sym := TDbgDwarfIdentifier.CreateSubClass('', Info2);
FMembers.Add(sym);
sym.ReleaseReference;
sym.IncRefByParentCount;
sym.ParentTypeInfo := self;
Info2.ReleaseReference;
end;
@ -4115,14 +4111,10 @@ destructor TDbgDwarfIdentifierEnum.Destroy;
var
i: Integer;
begin
if FMembers <> nil then begin
if FMembers <> nil then
for i := 0 to FMembers.Count - 1 do
with TDbgDwarfIdentifier(FMembers[i]) do begin
ParentTypeInfo := nil;
DecRefByParentCount;
end;
FreeAndNil(FMembers);
end;
TDbgDwarfIdentifier(FMembers[i]).ParentTypeInfo := nil;
FreeAndNil(FMembers);
inherited Destroy;
end;
@ -4343,8 +4335,12 @@ begin
else
Result := inherited GetMember(AIndex);
if Result is TDbgDwarfIdentifierMember then
if (Result <> nil) and (Result is TDbgDwarfIdentifierMember) then begin
if FMembers = nil then
FMembers := TFpDbgCircularRefCntObjList.Create;
FMembers.Add(Result);
TDbgDwarfIdentifierMember(Result).StructureValueInfo := Self;
end;
end;
function TDbgDwarfValueIdentifier.GetMemberByName(AIndex: String): TDbgSymbol;
@ -4357,8 +4353,12 @@ begin
else
Result := inherited GetMemberByName(AIndex);
if Result is TDbgDwarfIdentifierMember then
if (Result <> nil) and (Result is TDbgDwarfIdentifierMember) then begin
if FMembers = nil then
FMembers := TFpDbgCircularRefCntObjList.Create;
FMembers.Add(Result);
TDbgDwarfIdentifierMember(Result).StructureValueInfo := Self;
end;
end;
function TDbgDwarfValueIdentifier.GetMemberCount: Integer;
@ -4379,7 +4379,13 @@ begin
end;
destructor TDbgDwarfValueIdentifier.Destroy;
var
i: Integer;
begin
if FMembers <> nil then
for i := 0 to FMembers.Count - 1 do
TDbgDwarfIdentifierMember(FMembers[i]).StructureValueInfo := nil;
FreeAndNil(FMembers);
if FValueObject <> nil then begin
FValueObject.SetOwner(nil);
ReleaseRefAndNil(FValueObject);
@ -4411,7 +4417,7 @@ var
begin
if FMembers <> nil then
exit;
FMembers := TRefCntObjList.Create;
FMembers := TFpDbgCircularRefCntObjList.Create;
Info := FInformationEntry.FirstChild;
if Info = nil then exit;
@ -4423,7 +4429,6 @@ begin
sym := TDbgDwarfIdentifier.CreateSubClass('', Info2);
FMembers.Add(sym);
sym.ReleaseReference;
sym.IncRefByParentCount;
sym.ParentTypeInfo := self;
Info2.ReleaseReference;
end;
@ -4490,10 +4495,7 @@ var
begin
if FMembers <> nil then begin
for i := 0 to FMembers.Count - 1 do
with TDbgDwarfIdentifier(FMembers[i]) do begin
ParentTypeInfo := nil;
DecRefByParentCount;
end;
TDbgDwarfIdentifier(FMembers[i]).ParentTypeInfo := nil;
FreeAndNil(FMembers);
end;
inherited Destroy;
@ -4509,15 +4511,15 @@ begin
// Todo, maybe create all children?
if FLastChildByName <> nil then begin
FLastChildByName.ParentTypeInfo := nil;
FLastChildByName.DecRefByParentCount;
ReleaseRefAndNil(FLastChildByName);
FLastChildByName.ReleaseCirclularReference;
FLastChildByName := nil;
end;
Result := nil;
Ident := FInformationEntry.FindNamedChild(AIndex);
if Ident <> nil then begin
FLastChildByName := TDbgDwarfIdentifier.CreateSubClass('', Ident);
FLastChildByName.IncRefByParentCount;
FLastChildByName.MakePlainRefToCirclular;
FLastChildByName.ParentTypeInfo := self;
//assert is member ?
ReleaseRefAndNil(Ident);
@ -4539,8 +4541,6 @@ end;
procedure TDbgDwarfIdentifierStructure.InitLocationParser(const ALocationParser: TDwarfLocationExpression;
AnObjectDataAddress: TDbgPtr);
var
t: TDbgPtr;
begin
inherited InitLocationParser(ALocationParser, AnObjectDataAddress);
@ -4593,16 +4593,13 @@ begin
ReleaseRefAndNil(FInheritanceInfo);
if FMembers <> nil then begin
for i := 0 to FMembers.Count - 1 do
with TDbgDwarfIdentifier(FMembers[i]) do begin
ParentTypeInfo := nil;
DecRefByParentCount;
end;
TDbgDwarfIdentifier(FMembers[i]).ParentTypeInfo := nil;
FreeAndNil(FMembers);
end;
if FLastChildByName <> nil then begin
FLastChildByName.ParentTypeInfo := nil;
FLastChildByName.DecRefByParentCount;
ReleaseRefAndNil(FLastChildByName);
FLastChildByName.ReleaseCirclularReference;
FLastChildByName := nil;
end;
inherited Destroy;
end;
@ -4615,7 +4612,7 @@ var
begin
if FMembers <> nil then
exit;
FMembers := TRefCntObjList.Create;
FMembers := TFpDbgCircularRefCntObjList.Create;
Info := FInformationEntry.Clone;
Info.GoChild;
@ -4625,7 +4622,6 @@ begin
sym := TDbgDwarfIdentifier.CreateSubClass('', Info2);
FMembers.Add(sym);
sym.ReleaseReference;
sym.IncRefByParentCount;
sym.ParentTypeInfo := self;
Info2.ReleaseReference;
end;
@ -4832,8 +4828,6 @@ begin
include(FDwarfReadFlags, didtTypeRead);
FNestedTypeInfo := DoGetNestedTypeInfo;
// if FNestedTypeInfo <> nil then
// FNestedTypeInfo.FOwnerTypeInfo := Self;
Result := FNestedTypeInfo;
end;
@ -4841,57 +4835,32 @@ procedure TDbgDwarfIdentifier.SetParentTypeInfo(AValue: TDbgDwarfIdentifier);
begin
if FParentTypeInfo = AValue then exit;
if (FParentTypeInfo <> nil) and RefToParentActive then
if (FParentTypeInfo <> nil) and CircleBackRefsActive then
FParentTypeInfo.ReleaseReference{$IFDEF WITH_REFCOUNT_DEBUG}(@FParentTypeInfo, 'FParentTypeInfo'){$ENDIF};
FParentTypeInfo := AValue;
if (FParentTypeInfo <> nil) and RefToParentActive then
if (FParentTypeInfo <> nil) and CircleBackRefsActive then
FParentTypeInfo.AddReference{$IFDEF WITH_REFCOUNT_DEBUG}(@FParentTypeInfo, 'FParentTypeInfo'){$ENDIF};
end;
procedure TDbgDwarfIdentifier.DoReferenceAdded;
begin
inherited DoReferenceAdded;
if (RefCount = FRefByParentCount + 1) and (FParentTypeInfo <> nil) then
RefToParentChanged;
//FParentTypeInfo.AddReference{$IFDEF WITH_REFCOUNT_DEBUG}(@FParentTypeInfo, 'FParentTypeInfo'){$ENDIF};
DoPlainReferenceAdded;
end;
procedure TDbgDwarfIdentifier.DoReferenceReleased;
begin
inherited DoReferenceReleased;
if (RefCount = FRefByParentCount) and (FParentTypeInfo <> nil) then
RefToParentChanged;
//FParentTypeInfo.ReleaseReference{$IFDEF WITH_REFCOUNT_DEBUG}(@FParentTypeInfo, 'FParentTypeInfo'){$ENDIF};
DoPlainReferenceReleased;
end;
procedure TDbgDwarfIdentifier.IncRefByParentCount;
begin
inc(FRefByParentCount);
if (RefCount = FRefByParentCount) and (FParentTypeInfo <> nil) then
RefToParentChanged;
//FParentTypeInfo.ReleaseReference{$IFDEF WITH_REFCOUNT_DEBUG}(@FParentTypeInfo, 'FParentTypeInfo'){$ENDIF};
end;
procedure TDbgDwarfIdentifier.DecRefByParentCount;
begin
dec(FRefByParentCount);
if (RefCount = FRefByParentCount + 1) and (FParentTypeInfo <> nil) then
RefToParentChanged;
//FParentTypeInfo.AddReference{$IFDEF WITH_REFCOUNT_DEBUG}(@FParentTypeInfo, 'FParentTypeInfo'){$ENDIF};
end;
function TDbgDwarfIdentifier.RefToParentActive: Boolean;
begin
Result := (RefCount > FRefByParentCount);
end;
procedure TDbgDwarfIdentifier.RefToParentChanged;
procedure TDbgDwarfIdentifier.CircleBackRefActiveChanged(ANewActive: Boolean);
begin
if (FParentTypeInfo = nil) then
exit;
if RefToParentActive then
if ANewActive then
FParentTypeInfo.AddReference{$IFDEF WITH_REFCOUNT_DEBUG}(@FParentTypeInfo, 'FParentTypeInfo'){$ENDIF}
else
FParentTypeInfo.ReleaseReference{$IFDEF WITH_REFCOUNT_DEBUG}(@FParentTypeInfo, 'FParentTypeInfo'){$ENDIF};
@ -5098,12 +5067,8 @@ begin
inherited Destroy;
ReleaseRefAndNil(FInformationEntry);
ReleaseRefAndNil(FNestedTypeInfo);
if RefToParentActive then
FParentTypeInfo.ReleaseReference{$IFDEF WITH_REFCOUNT_DEBUG}(@FParentTypeInfo, 'FParentTypeInfo'){$ENDIF};
// if FNestedTypeInfo <> nil then begin
// assert((FNestedTypeInfo.FOwnerTypeInfo = nil) or (FNestedTypeInfo.FOwnerTypeInfo= self), 'FNestedTypeInfo.FOwnerTypeInfo is nil or self');
// FNestedTypeInfo.FOwnerTypeInfo := nil;
// end;
Assert(not CircleBackRefsActive, 'CircleBackRefsActive can not be is ddestructor');
// FParentTypeInfo := nil
end;
function TDbgDwarfIdentifier.StartScope: TDbgPtr;
@ -5181,7 +5146,6 @@ begin
FreeAndNil(FStateMachine);
if FSelfParameter <> nil then begin
FSelfParameter.ParentTypeInfo := nil;
FSelfParameter.DecRefByParentCount;
FSelfParameter.ReleaseReference{$IFDEF WITH_REFCOUNT_DEBUG}(@FSelfParameter, 'FSelfParameter'){$ENDIF};
end;
inherited Destroy;
@ -5340,10 +5304,7 @@ begin
then begin
Result := TDbgDwarfValueIdentifier.CreateValueSubClass('self', InfoEntry);
FSelfParameter := Result;
{$IFDEF WITH_REFCOUNT_DEBUG} // Rename the ref
FSelfParameter.AddReference(@FSelfParameter, 'FSelfParameter'); FSelfParameter.ReleaseReference;
{$ENDIF}
//FSelfParameter.IncRefByParentCount;
{$IFDEF WITH_REFCOUNT_DEBUG}FSelfParameter.DbgRenameReference(@FSelfParameter, 'FSelfParameter');{$ENDIF}
//FSelfParameter.ParentTypeInfo := Self;
debugln(['TDbgDwarfProcSymbol.GetSelfParameter ', dbgs(InfoEntry.FScope, FCU), DbgSName(Result)]);
end;
@ -5873,7 +5834,7 @@ var
Attrib: Pointer;
Form: Cardinal;
Info: TDwarfAddressInfo;
Scope, ResultScope: TDwarfScopeInfo;
Scope: TDwarfScopeInfo;
ScopeIdx: Integer;
Abbrev: TDwarfAbbrev;
begin

View File

@ -10,6 +10,38 @@ uses
type
TDbgPtr = QWord; // PtrUInt;
{ TFpDbgCircularRefCountedObject }
TFpDbgCircularRefCountedObject = class(TRefCountedObject)
private
FCircleRefCount: Integer;
protected
(* InOrder to activate, and use an interited class must override
DoReferenceAdded; and DoReferenceReleased;
And Point then to
DoPlainReferenceAdded; and DoPlainReferenceReleased;
*)
procedure DoPlainReferenceAdded; inline;
procedure DoPlainReferenceReleased; inline;
procedure AddCirclularReference{$IFDEF WITH_REFCOUNT_DEBUG}(DebugIdAdr: Pointer = nil; DebugIdTxt: String = ''){$ENDIF};
procedure ReleaseCirclularReference{$IFDEF WITH_REFCOUNT_DEBUG}(DebugIdAdr: Pointer = nil; DebugIdTxt: String = ''){$ENDIF};
procedure MakePlainRefToCirclular;
procedure MakeCirclularRefToPlain;
function CircleBackRefsActive: Boolean; inline;
procedure CircleBackRefActiveChanged(NewActive: Boolean); virtual;
end;
{ TFpDbgCircularRefCntObjList }
TFpDbgCircularRefCntObjList = class(TRefCntObjList)
protected
procedure Notify(Ptr: Pointer; Action: TListNotification); override;
end;
TFpDbgMemReaderBase = class
public
function ReadMemory(AnAddress: TDbgPtr; ASize: Cardinal; ADest: Pointer): Boolean; virtual; abstract;
@ -147,7 +179,7 @@ type
{ TDbgSymbol }
TDbgSymbol = class(TRefCountedObject)
TDbgSymbol = class(TFpDbgCircularRefCountedObject)
private
FEvaluatedFields: TDbgSymbolFields;
@ -321,6 +353,83 @@ begin
WriteStr(Result, ADbgSymbolKind);
end;
{ TFpDbgCircularRefCountedObject }
procedure TFpDbgCircularRefCountedObject.DoPlainReferenceAdded;
begin
if (RefCount = FCircleRefCount + 1) then
CircleBackRefActiveChanged(True);
end;
procedure TFpDbgCircularRefCountedObject.DoPlainReferenceReleased;
begin
if (RefCount = FCircleRefCount) then
CircleBackRefActiveChanged(False);
end;
procedure TFpDbgCircularRefCountedObject.AddCirclularReference{$IFDEF WITH_REFCOUNT_DEBUG}(DebugIdAdr: Pointer = nil; DebugIdTxt: String = ''){$ENDIF};
begin
if CircleBackRefsActive then begin
AddReference{$IFDEF WITH_REFCOUNT_DEBUG}(DebugIdAdr, DebugIdTxt){$ENDIF};
inc(FCircleRefCount);
end
else begin
inc(FCircleRefCount);
AddReference{$IFDEF WITH_REFCOUNT_DEBUG}(DebugIdAdr, DebugIdTxt){$ENDIF};
end;
end;
procedure TFpDbgCircularRefCountedObject.ReleaseCirclularReference{$IFDEF WITH_REFCOUNT_DEBUG}(DebugIdAdr: Pointer = nil; DebugIdTxt: String = ''){$ENDIF};
begin
Assert(FCircleRefCount > 0, 'ReleaseCirclularReference > 0');
if CircleBackRefsActive then begin
dec(FCircleRefCount);
ReleaseReference{$IFDEF WITH_REFCOUNT_DEBUG}(DebugIdAdr, DebugIdTxt){$ENDIF};
end
else begin
ReleaseReference{$IFDEF WITH_REFCOUNT_DEBUG}(DebugIdAdr, DebugIdTxt){$ENDIF};
dec(FCircleRefCount);
end;
end;
procedure TFpDbgCircularRefCountedObject.MakePlainRefToCirclular;
begin
Assert(FCircleRefCount < RefCount, 'MakePlainRefToCirclular < max');
inc(FCircleRefCount);
if (RefCount = FCircleRefCount) then
CircleBackRefActiveChanged(False);
end;
procedure TFpDbgCircularRefCountedObject.MakeCirclularRefToPlain;
begin
Assert(FCircleRefCount > 0, 'MakeCirclularRefToPlain > 0');
dec(FCircleRefCount);
if (RefCount = FCircleRefCount + 1) then
CircleBackRefActiveChanged(True);
end;
function TFpDbgCircularRefCountedObject.CircleBackRefsActive: Boolean;
begin
Result := (RefCount > FCircleRefCount);
end;
procedure TFpDbgCircularRefCountedObject.CircleBackRefActiveChanged(NewActive: Boolean);
begin
//
end;
{ TFpDbgCircularRefCntObjList }
procedure TFpDbgCircularRefCntObjList.Notify(Ptr: Pointer; Action: TListNotification);
begin
// Do NOT call inherited
case Action of
lnAdded: TFpDbgCircularRefCountedObject(Ptr).AddCirclularReference;
lnExtracted,
lnDeleted: TFpDbgCircularRefCountedObject(Ptr).ReleaseCirclularReference;
end;
end;
{ TDbgSymbolValue }
function TDbgSymbolValue.GetAsString: AnsiString;