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

View File

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

View File

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

View File

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

View File

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