IdeDebugger: reduce amount of update calls for changing a breakpoint

This commit is contained in:
Martin 2024-08-12 22:51:08 +02:00
parent 49b9015f4b
commit 3a0ab2b96c
5 changed files with 117 additions and 34 deletions

View File

@ -399,11 +399,17 @@ type
TBaseBreakPoints = class(TCollection)
private
FIgnoreUpdate: boolean;
FAutoBeginUpdate: boolean;
protected
procedure Update(Item: TCollectionItem); override;
property IgnoreUpdate: boolean read FIgnoreUpdate;
property AutoBeginUpdate: boolean read FAutoBeginUpdate;
public
constructor Create(const ABreakPointClass: TBaseBreakPointClass);
destructor Destroy; override;
procedure Clear; reintroduce;
function Add(AnUpdating: Boolean = False): TBaseBreakPoint; reintroduce; overload;
function Add(const ASource: String; const ALine: Integer; AnUpdating: Boolean = False): TBaseBreakPoint; overload;
function Add(const AAddress: TDBGPtr; AnUpdating: Boolean = False): TBaseBreakPoint; overload;
function Add(const AData: String; const AScope: TDBGWatchPointScope;
@ -3174,6 +3180,8 @@ end;
constructor TBaseBreakPoint.Create(ACollection: TCollection);
begin
if (ACollection <> nil) and TBaseBreakPoints(ACollection).AutoBeginUpdate then
BeginUpdate;
FPropertiesChanged := [ciCreated];
FAddress := 0;
FSource := '';
@ -3298,8 +3306,10 @@ begin
if FBreakHitCount <> AValue
then begin
FBreakHitCount := AValue;
BeginUpdate;
Changed;
MarkPropertyChanged(ciHitCount);
EndUpdate;
end;
end;
@ -3341,8 +3351,10 @@ begin
if (FSource = ASource) and (FLine = ALine) then exit;
FSource := ASource;
FLine := ALine;
BeginUpdate;
Changed;
MarkPropertyChanged(ciLocation);
EndUpdate;
end;
procedure TBaseBreakPoint.SetWatch(const AData: String; const AScope: TDBGWatchPointScope;
@ -3352,8 +3364,10 @@ begin
FWatchData := AData;
FWatchScope := AScope;
FWatchKind := AKind;
BeginUpdate;
Changed;
MarkPropertyChanged(ciLocation);
EndUpdate;
end;
procedure TBaseBreakPoint.SetValid(const AValue: TValidState );
@ -3547,13 +3561,24 @@ end;
{ TBaseBreakPoints }
{ =========================================================================== }
function TBaseBreakPoints.Add(AnUpdating: Boolean): TBaseBreakPoint;
begin
FAutoBeginUpdate := AnUpdating;
Result := TBaseBreakPoint(inherited Add);
FAutoBeginUpdate := False;
end;
function TBaseBreakPoints.Add(const ASource: String; const ALine: Integer;
AnUpdating: Boolean): TBaseBreakPoint;
begin
FIgnoreUpdate := True;
FAutoBeginUpdate := True;
Result := TBaseBreakPoint(inherited Add);
Result.BeginUpdate;
FAutoBeginUpdate := False;
Result.SetKind(bpkSource);
Result.SetLocation(ASource, ALine);
FIgnoreUpdate := False;
if not AnUpdating then
Result.EndUpdate;
end;
@ -3561,10 +3586,14 @@ end;
function TBaseBreakPoints.Add(const AAddress: TDBGPtr; AnUpdating: Boolean
): TBaseBreakPoint;
begin
FIgnoreUpdate := True;
FAutoBeginUpdate := True;
Result := TBaseBreakPoint(inherited Add);
Result.BeginUpdate;
FAutoBeginUpdate := False;
Result.SetKind(bpkAddress);
Result.SetAddress(AAddress);
FIgnoreUpdate := False;
if not AnUpdating then
Result.EndUpdate;
end;
@ -3573,14 +3602,24 @@ function TBaseBreakPoints.Add(const AData: String;
const AScope: TDBGWatchPointScope; const AKind: TDBGWatchPointKind;
AnUpdating: Boolean): TBaseBreakPoint;
begin
FIgnoreUpdate := True;
FAutoBeginUpdate := True;
Result := TBaseBreakPoint(inherited Add);
Result.BeginUpdate;
FAutoBeginUpdate := False;
Result.SetKind(bpkData);
Result.SetWatch(AData, AScope, AKind);
FIgnoreUpdate := False;
if not AnUpdating then
Result.EndUpdate;
end;
procedure TBaseBreakPoints.Update(Item: TCollectionItem);
begin
if not FIgnoreUpdate then
inherited Update(Item);
end;
constructor TBaseBreakPoints.Create(const ABreakPointClass: TBaseBreakPointClass);
begin
inherited Create(ABreakPointClass);
@ -3594,7 +3633,10 @@ end;
procedure TBaseBreakPoints.Clear;
begin
FIgnoreUpdate := True;
// TODO, if anything else has a reference...
while Count > 0 do TBaseBreakPoint(GetItem(0)).ReleaseReference;
FIgnoreUpdate := False;
end;
function TBaseBreakPoints.Find(const ASource: String; const ALine: Integer): TBaseBreakPoint;

View File

@ -114,6 +114,7 @@ type
TDelayedUdateItem = class(TCollectionItem)
private
FUpdateCount: Integer;
FInEndUpdate: Integer;
FDoChanged: Boolean;
protected
procedure Changed;
@ -122,9 +123,10 @@ type
public
procedure Assign(ASource: TPersistent); override;
procedure BeginUpdate; virtual;
constructor Create(ACollection: TCollection); override;
procedure EndUpdate;
procedure ClearChanged;
function IsUpdating: Boolean;
function IsUpdateEnding: Boolean;
end;
{ TRefCountedColectionItem }
@ -498,12 +500,6 @@ begin
else DoChanged;
end;
constructor TDelayedUdateItem.Create(ACollection: TCollection);
begin
inherited Create(ACollection);
FUpdateCount := 0;
end;
procedure TDelayedUdateItem.DoChanged;
begin
inherited Changed(False);
@ -516,20 +512,34 @@ end;
procedure TDelayedUdateItem.EndUpdate;
begin
if FUpdateCount <= 0 then raise EInvalidOperation.Create('TDelayedUdateItem.EndUpdate');
if (FUpdateCount = 1) then begin
inc(FInEndUpdate);
DoEndUpdate;
dec(FInEndUpdate);
end;
Dec(FUpdateCount);
if FUpdateCount < 0 then raise EInvalidOperation.Create('TDelayedUdateItem.EndUpdate');
if (FUpdateCount = 0)
then DoEndUpdate;
if (FUpdateCount = 0) and FDoChanged
then begin
if (FUpdateCount = 0) and FDoChanged then begin
DoChanged;
FDoChanged := False;
end;
end;
procedure TDelayedUdateItem.ClearChanged;
begin
FDoChanged := False;
end;
function TDelayedUdateItem.IsUpdating: Boolean;
begin
Result := FUpdateCount > 0;
Result := (FUpdateCount > 0) and (FInEndUpdate = 0);
end;
function TDelayedUdateItem.IsUpdateEnding: Boolean;
begin
Result := FInEndUpdate > 0;
end;

View File

@ -594,6 +594,7 @@ type
FBrkLogStackLimit: Integer;
FBrkLogStackResult: array of String;
FBrkLogExpr, FBrkLogResult: String;
FNeedCheckChangeFlags: boolean;
procedure MaybeAbortWorker(AWait: Boolean = false);
procedure SetBreak;
procedure ResetBreak;
@ -605,6 +606,8 @@ type
procedure DoStateChange(const AOldState: TDBGState); override;
procedure DoPropertiesChanged(AChanged: TDbgBpChangeIndicators); override;
procedure DoChanged; override;
procedure DoEndUpdate; override;
procedure CheckChangeFlags;
property Validity: TValidState write SetValid;
public
destructor Destroy; override;
@ -2076,12 +2079,12 @@ begin
if (Enabled and not FIsSet) or FLocationChanged then
begin
FSetBreakFlag:=true;
Changed;
CheckChangeFlags;
end
else if (not enabled) and FIsSet then
begin
FResetBreakFlag:=true;
Changed;
CheckChangeFlags;
end;
end
else if Debugger.State = dsStop then
@ -2138,6 +2141,23 @@ end;
procedure TFPBreakpoint.DoChanged;
begin
CheckChangeFlags;
inherited DoChanged;
end;
procedure TFPBreakpoint.DoEndUpdate;
begin
inherited DoEndUpdate;
CheckChangeFlags; // in case DoChange is not called
end;
procedure TFPBreakpoint.CheckChangeFlags;
begin
FNeedCheckChangeFlags := IsUpdating and not IsUpdateEnding;
if FNeedCheckChangeFlags then
exit;
if FResetBreakFlag and not FSetBreakFlag then
ResetBreak
else
@ -2146,8 +2166,6 @@ begin
FSetBreakFlag := false;
FResetBreakFlag := false;
inherited DoChanged;
end;
{ TFPDBGDisassembler }

View File

@ -610,6 +610,8 @@ end;
procedure TManagedBreakPoints.Update(Item: TCollectionItem);
begin
if IgnoreUpdate then
exit;
inherited Update(Item);
if (Project1 <> nil) and (Item is TIDEBreakPoint) and (TIDEBreakPoint(Item).UserModified)
then begin

View File

@ -5698,7 +5698,6 @@ procedure TIDEBreakPoint.SetAutoContinueTime(const AValue: Cardinal);
begin
if FAutoContinueTime = AValue then Exit;
FAutoContinueTime := AValue;
//Changed;
DoUserChanged;
end;
@ -5707,7 +5706,6 @@ begin
if FLogEvalExpression <> AValue then
begin
FLogEvalExpression := AValue;
//Changed;
DoUserChanged;
end;
end;
@ -5717,7 +5715,6 @@ begin
if FLogMessage <> AValue then
begin
FLogMessage := AValue;
//Changed;
DoUserChanged;
end;
end;
@ -5737,7 +5734,6 @@ begin
if FLogCallStackLimit <> AValue then
begin
FLogCallStackLimit := AValue;
//Changed;
DoUserChanged;
end;
end;
@ -5789,7 +5785,7 @@ end;
procedure TIDEBreakPoint.DoUserChanged;
begin
FUserModified := True;
DoChanged;
Changed;
end;
function TIDEBreakPoint.GetHitCount: Integer;
@ -5910,7 +5906,6 @@ end;
procedure TIDEBreakPoint.DoActionChange;
begin
//Changed;
DoUserChanged;
end;
@ -6138,7 +6133,6 @@ begin
then begin
FGroup.Add(Self);
end;
//Changed;
DoUserChanged;
end;
end;
@ -6174,23 +6168,29 @@ end;
function TIDEBreakPoints.Add(const ASource: String; const ALine: Integer;
AnUpdating: Boolean): TIDEBreakPoint;
begin
Result := TIDEBreakPoint(inherited Add(ASource, ALine, AnUpdating));
Result := TIDEBreakPoint(inherited Add(ASource, ALine, True));
NotifyAdd(Result);
if not AnUpdating then
Result.EndUpdate;
end;
function TIDEBreakPoints.Add(const AAddress: TDBGPtr; AnUpdating: Boolean
): TIDEBreakPoint;
begin
Result := TIDEBreakPoint(inherited Add(AAddress, AnUpdating));
Result := TIDEBreakPoint(inherited Add(AAddress, True));
NotifyAdd(Result);
if not AnUpdating then
Result.EndUpdate;
end;
function TIDEBreakPoints.Add(const AData: String;
const AScope: TDBGWatchPointScope; const AKind: TDBGWatchPointKind;
AnUpdating: Boolean): TIDEBreakPoint;
begin
Result := TIDEBreakPoint(inherited Add(AData, AScope, AKind, AnUpdating));
Result := TIDEBreakPoint(inherited Add(AData, AScope, AKind, True));
NotifyAdd(Result);
if not AnUpdating then
Result.EndUpdate;
end;
procedure TIDEBreakPoints.AddNotification(
@ -6290,12 +6290,14 @@ begin
if Assigned(Notification.FOnAdd)
then Notification.FOnAdd(Self, ABreakPoint);
end;
ABreakPoint.ClearChanged; // we did send "Add" instead
if FMaster <> nil
then begin
// create without data. it will be set in assign (but during Begin/EndUpdate)
BP := TBaseBreakPoint(FMaster.Add);
BP := TBaseBreakPoint(FMaster.Add(True));
BP.Assign(ABreakPoint); // will set ABreakPoint.FMaster := BP;
BP.EndUpdate;
end;
end;
@ -6345,23 +6347,30 @@ begin
begin
BreakPoint := Find(LoadBreakPoint.Source, LoadBreakPoint.Line, LoadBreakPoint);
if BreakPoint = nil then
BreakPoint := Add(LoadBreakPoint.Source, LoadBreakPoint.Line);
BreakPoint := Add(LoadBreakPoint.Source, LoadBreakPoint.Line, True)
else
BreakPoint.BeginUpdate;
end;
bpkAddress:
begin
BreakPoint := Find(LoadBreakPoint.Address, LoadBreakPoint);
if BreakPoint = nil then
BreakPoint := Add(LoadBreakPoint.Address);
BreakPoint := Add(LoadBreakPoint.Address, True)
else
BreakPoint.BeginUpdate;
end;
bpkData:
begin
BreakPoint := Find(LoadBreakPoint.WatchData, LoadBreakPoint.WatchScope, LoadBreakPoint.WatchKind, LoadBreakPoint);
if BreakPoint = nil then
BreakPoint := Add(LoadBreakPoint.WatchData, LoadBreakPoint.WatchScope, LoadBreakPoint.WatchKind);
BreakPoint := Add(LoadBreakPoint.WatchData, LoadBreakPoint.WatchScope, LoadBreakPoint.WatchKind, True)
else
BreakPoint.BeginUpdate;
end;
end;
BreakPoint.Assign(LoadBreakPoint);
BreakPoint.EndUpdate;
ReleaseRefAndNil(LoadBreakPoint)
end;
end;
@ -6395,6 +6404,8 @@ var
n: Integer;
Notification: TIDEBreakPointsNotification;
begin
if IgnoreUpdate then
exit;
// Note: Item will be nil in case all items need to be updated
for n := 0 to FNotificationList.Count - 1 do
begin