mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-09-12 17:39:18 +02:00
FpDebug: Change line-num/address mapping. Improve performance. Issue #41230
This commit is contained in:
parent
d82e6b2dca
commit
d461637604
@ -489,14 +489,23 @@ type
|
|||||||
{ TDWarfLineMap }
|
{ TDWarfLineMap }
|
||||||
|
|
||||||
TDWarfLineMap = object
|
TDWarfLineMap = object
|
||||||
private
|
private const
|
||||||
// FLineIndexList[ line div 256 ]
|
PAGE_SIZE = 128;
|
||||||
FLineIndexList: Array of record
|
PAGE_SHIFT = 7;
|
||||||
LineOffsets: Array of Byte;
|
PAGE_MASK = 127;
|
||||||
Addresses: Array of TDBGPtr;
|
LIST_FLAG = $80;
|
||||||
|
private type
|
||||||
|
TLineMapPage = record
|
||||||
|
AddrCnt: Int16;
|
||||||
|
Map: array [0..PAGE_SIZE-1] of byte;
|
||||||
|
Addresses: array [0..PAGE_SIZE-1] of TDBGPtr;
|
||||||
end;
|
end;
|
||||||
|
PLineMapPage = ^TLineMapPage;
|
||||||
|
private
|
||||||
|
FLinePageList: Array of PLineMapPage;
|
||||||
public
|
public
|
||||||
procedure Init;
|
procedure Init;
|
||||||
|
procedure Free;
|
||||||
procedure SetAddressForLine(ALine: Cardinal; AnAddress: TDBGPtr); inline;
|
procedure SetAddressForLine(ALine: Cardinal; AnAddress: TDBGPtr); inline;
|
||||||
function GetAddressesForLine(ALine: Cardinal; var AResultList: TDBGPtrArray;
|
function GetAddressesForLine(ALine: Cardinal; var AResultList: TDBGPtrArray;
|
||||||
NoData: Boolean = False;
|
NoData: Boolean = False;
|
||||||
@ -506,7 +515,6 @@ type
|
|||||||
ADbgInfo: TFpDwarfInfo = nil
|
ADbgInfo: TFpDwarfInfo = nil
|
||||||
): Boolean; inline;
|
): Boolean; inline;
|
||||||
// NoData: only return True/False, but nothing in AResultList
|
// NoData: only return True/False, but nothing in AResultList
|
||||||
procedure Compress;
|
|
||||||
end;
|
end;
|
||||||
PDWarfLineMap = ^TDWarfLineMap;
|
PDWarfLineMap = ^TDWarfLineMap;
|
||||||
{%endregion Line Info / Section "debug_line"}
|
{%endregion Line Info / Section "debug_line"}
|
||||||
@ -3560,101 +3568,135 @@ end;
|
|||||||
|
|
||||||
procedure TDWarfLineMap.Init;
|
procedure TDWarfLineMap.Init;
|
||||||
begin
|
begin
|
||||||
|
SetLength(FLinePageList, 32);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TDWarfLineMap.Free;
|
||||||
|
var
|
||||||
|
idx, j: Integer;
|
||||||
|
CurPage: PLineMapPage;
|
||||||
|
MappedOffset: Word;
|
||||||
|
begin
|
||||||
|
for idx := 0 to Length(FLinePageList) - 1 do begin
|
||||||
|
CurPage := FLinePageList[idx];
|
||||||
|
if CurPage <> nil then begin
|
||||||
|
for j := 0 to PAGE_SIZE - 1 do begin
|
||||||
|
MappedOffset := CurPage^.Map[j];
|
||||||
|
if (MappedOffset and LIST_FLAG) <> 0 then
|
||||||
|
Freemem(PDBGPtr(CurPage^.Addresses[MappedOffset and PAGE_MASK]));
|
||||||
|
end;
|
||||||
|
Dispose(CurPage);
|
||||||
|
end
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TDWarfLineMap.SetAddressForLine(ALine: Cardinal; AnAddress: TDBGPtr);
|
procedure TDWarfLineMap.SetAddressForLine(ALine: Cardinal; AnAddress: TDBGPtr);
|
||||||
var
|
var
|
||||||
SectLen, SectCnt, i, j, o, o2: Integer;
|
idx, offset: integer;
|
||||||
idx, offset: TDBGPtr;
|
i: integer;
|
||||||
LineOffsets: Array of Byte;
|
CurPage: PLineMapPage;
|
||||||
Addresses: Array of TDBGPtr;
|
AddrList: PDBGPtr;
|
||||||
|
MappedOffset: Byte;
|
||||||
begin
|
begin
|
||||||
idx := ALine div 256;
|
idx := ALine SHR PAGE_SHIFT;
|
||||||
offset := ALine mod 256;
|
offset := ALine AND PAGE_MASK;
|
||||||
i := Length(FLineIndexList);
|
i := Length(FLinePageList);
|
||||||
if idx >= i then
|
if idx >= i then
|
||||||
SetLength(FLineIndexList, idx+4);
|
SetLength(FLinePageList, idx+20);
|
||||||
|
|
||||||
LineOffsets := FLineIndexList[idx].LineOffsets;
|
CurPage := FLinePageList[idx];
|
||||||
Addresses := FLineIndexList[idx].Addresses;
|
if CurPage = nil then begin
|
||||||
|
CurPage := GetMem(PtrInt(@PLineMapPage(nil)^.Addresses) + 32*SizeOf(TDBGPtr));
|
||||||
|
FillChar(CurPage^.Map[0], SizeOf(CurPage^.Map), $7f);
|
||||||
|
CurPage^.AddrCnt := 0;
|
||||||
|
FLinePageList[idx] := CurPage;
|
||||||
|
end;
|
||||||
|
|
||||||
if Addresses = nil then begin
|
MappedOffset := CurPage^.Map[offset];
|
||||||
SectLen := 192;
|
if (MappedOffset and LIST_FLAG) <> 0 then begin
|
||||||
SectCnt := 0;
|
MappedOffset := MappedOffset and PAGE_MASK;
|
||||||
SetLength(FLineIndexList[idx].Addresses, 193);
|
AddrList := PDBGPtr(CurPage^.Addresses[MappedOffset]);
|
||||||
SetLength(FLineIndexList[idx].LineOffsets, 192);
|
i := AddrList[0];
|
||||||
LineOffsets := FLineIndexList[idx].LineOffsets;
|
while (i > 0) and (AddrList[i] <> AnAddress) do
|
||||||
Addresses := FLineIndexList[idx].Addresses;
|
dec(i);
|
||||||
end
|
if i > 0 then // address already exists
|
||||||
else begin
|
exit;
|
||||||
SectLen := Length(LineOffsets);
|
|
||||||
SectCnt := Integer(Addresses[SectLen]);
|
i := AddrList[0]+1;
|
||||||
if SectCnt >= SectLen then begin
|
if (i and 1) = 0 then begin
|
||||||
SectLen := SectCnt + 64;
|
AddrList := ReAllocMem(AddrList, SizeOf(TDBGPtr)*(i+2));
|
||||||
SetLength(FLineIndexList[idx].Addresses, SectLen+1);
|
CurPage^.Addresses[MappedOffset] := TDBGPtr(AddrList);
|
||||||
SetLength(FLineIndexList[idx].LineOffsets, SectLen);
|
|
||||||
LineOffsets := FLineIndexList[idx].LineOffsets;
|
|
||||||
Addresses := FLineIndexList[idx].Addresses;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
AddrList[0] := i;
|
||||||
|
AddrList[i] := AnAddress;
|
||||||
|
end
|
||||||
|
|
||||||
|
else
|
||||||
|
if MappedOffset < CurPage^.AddrCnt then begin
|
||||||
|
if CurPage^.Addresses[MappedOffset] = AnAddress then
|
||||||
|
exit;
|
||||||
|
|
||||||
|
CurPage^.Map[offset] := MappedOffset or LIST_FLAG;
|
||||||
|
AddrList := GetMem(SizeOf(TDBGPtr)*4);
|
||||||
|
AddrList[0] := 2;
|
||||||
|
AddrList[1] := CurPage^.Addresses[MappedOffset];
|
||||||
|
AddrList[2] := AnAddress;
|
||||||
|
CurPage^.Addresses[MappedOffset] := TDBGPtr(AddrList);
|
||||||
|
end
|
||||||
|
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
MappedOffset := CurPage^.AddrCnt;
|
||||||
|
case MappedOffset of
|
||||||
|
32: begin
|
||||||
|
CurPage := ReAllocMem(CurPage, PtrInt(@PLineMapPage(nil)^.Addresses) + 64*SizeOf(TDBGPtr));
|
||||||
|
FLinePageList[idx] := CurPage;
|
||||||
|
end;
|
||||||
|
64: begin
|
||||||
|
CurPage := ReAllocMem(CurPage, PtrInt(@PLineMapPage(nil)^.Addresses) + 96*SizeOf(TDBGPtr));
|
||||||
|
FLinePageList[idx] := CurPage;
|
||||||
|
end;
|
||||||
|
96: begin
|
||||||
|
CurPage := ReAllocMem(CurPage, SizeOf(TLineMapPage));
|
||||||
|
FLinePageList[idx] := CurPage;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
inc(CurPage^.AddrCnt);
|
||||||
|
CurPage^.Map[offset] := MappedOffset;
|
||||||
|
CurPage^.Addresses[MappedOffset] := AnAddress;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
i := 0;
|
|
||||||
o := 0;
|
|
||||||
while (i < SectCnt) do begin
|
|
||||||
o2 := o + LineOffsets[i];
|
|
||||||
if o2 > offset then break;
|
|
||||||
o := o2;
|
|
||||||
inc(i);
|
|
||||||
end;
|
|
||||||
|
|
||||||
j := SectCnt;
|
|
||||||
while j > i do begin
|
|
||||||
LineOffsets[j] := LineOffsets[j-1];
|
|
||||||
Addresses[j] := Addresses[j-1];
|
|
||||||
dec(j);
|
|
||||||
end;
|
|
||||||
|
|
||||||
offset := offset - o;
|
|
||||||
LineOffsets[i] := offset;
|
|
||||||
Addresses[i] := AnAddress;
|
|
||||||
|
|
||||||
if i < SectCnt then begin
|
|
||||||
assert(LineOffsets[i+1] >= offset, 'TDWarfLineMap.SetAddressForLine LineOffsets[i+1] > offset');
|
|
||||||
LineOffsets[i+1] := LineOffsets[i+1] - offset;
|
|
||||||
end;
|
|
||||||
|
|
||||||
Addresses[SectLen] := SectCnt + 1;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TDWarfLineMap.GetAddressesForLine(ALine: Cardinal; var AResultList: TDBGPtrArray;
|
function TDWarfLineMap.GetAddressesForLine(ALine: Cardinal; var AResultList: TDBGPtrArray;
|
||||||
NoData: Boolean; AFindSibling: TGetLineAddrFindSibling; AFoundLine: PInteger;
|
NoData: Boolean; AFindSibling: TGetLineAddrFindSibling; AFoundLine: PInteger;
|
||||||
AMaxSiblingDistance: integer; ADbgInfo: TFpDwarfInfo): Boolean;
|
AMaxSiblingDistance: integer; ADbgInfo: TFpDwarfInfo): Boolean;
|
||||||
var
|
var
|
||||||
idx: integer;
|
idx, offset: integer;
|
||||||
offset, Addr1, Addr2: TDBGPtr;
|
Addr1, Addr2, FndAddr, FirstAddr: TDBGPtr;
|
||||||
LineOffsets: Array of Byte;
|
o, MappedOffset: Byte;
|
||||||
Addresses: Array of TDBGPtr;
|
i, j, k, l, ln: Integer;
|
||||||
o: Byte;
|
|
||||||
i, j, k, l, ln, CurOffs: Integer;
|
|
||||||
TmpResList: TDBGPtrArray;
|
TmpResList: TDBGPtrArray;
|
||||||
|
CurPage: PLineMapPage;
|
||||||
|
IsList, OffsetExist: Boolean;
|
||||||
begin
|
begin
|
||||||
Result := False;
|
Result := False;
|
||||||
idx := ALine div 256;
|
idx := ALine SHR PAGE_SHIFT;
|
||||||
offset := ALine mod 256;
|
offset := ALine AND PAGE_MASK;
|
||||||
if idx >= Length(FLineIndexList) then begin
|
|
||||||
|
if idx >= Length(FLinePageList) then begin
|
||||||
if AFindSibling = fsBefore then begin
|
if AFindSibling = fsBefore then begin
|
||||||
idx := Length(FLineIndexList)-1;
|
idx := Length(FLinePageList)-1;
|
||||||
offset := 255;
|
offset := PAGE_SIZE-1;
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
repeat
|
repeat
|
||||||
LineOffsets := FLineIndexList[idx].LineOffsets;
|
// TODO: check AMaxSiblingDistance against page size distance
|
||||||
Addresses := FLineIndexList[idx].Addresses;
|
CurPage := FLinePageList[idx];
|
||||||
if Addresses = nil then
|
if CurPage = nil then
|
||||||
case AFindSibling of
|
case AFindSibling of
|
||||||
fsNone:
|
fsNone:
|
||||||
exit;
|
exit;
|
||||||
@ -3662,75 +3704,67 @@ begin
|
|||||||
if idx = 0 then
|
if idx = 0 then
|
||||||
exit;
|
exit;
|
||||||
dec(idx);
|
dec(idx);
|
||||||
offset := 255;
|
offset := PAGE_SIZE-1;
|
||||||
Continue;
|
Continue;
|
||||||
end;
|
end;
|
||||||
fsNext, fsNextFunc, fsNextFuncLazy: begin
|
fsNext, fsNextFunc, fsNextFuncLazy: begin
|
||||||
inc(idx);
|
inc(idx);
|
||||||
if idx >= Length(FLineIndexList) then
|
if idx >= Length(FLinePageList) then
|
||||||
exit;
|
exit;
|
||||||
offset := 0;
|
offset := 0;
|
||||||
Continue;
|
Continue;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
l := Length(LineOffsets);
|
MappedOffset := CurPage^.Map[offset];
|
||||||
i := 0;
|
OffsetExist := (MappedOffset and PAGE_MASK) < CurPage^.AddrCnt;
|
||||||
CurOffs := 0;
|
|
||||||
while (i < l) do begin
|
|
||||||
o := LineOffsets[i];
|
|
||||||
CurOffs := CurOffs + o;
|
|
||||||
if o > offset then begin
|
|
||||||
case AFindSibling of
|
|
||||||
fsNone:
|
|
||||||
exit;
|
|
||||||
fsBefore: begin
|
|
||||||
if i > 0 then begin
|
|
||||||
dec(i);
|
|
||||||
CurOffs := CurOffs - o;
|
|
||||||
offset := 0; // found line before
|
|
||||||
end
|
|
||||||
else begin
|
|
||||||
// i=0 => will trigger continue for outer loop
|
|
||||||
dec(idx);
|
|
||||||
if idx < 0 then
|
|
||||||
exit;
|
|
||||||
offset := 255; // Must be last entry from block before (if there is a block before)
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
fsNext, fsNextFunc, fsNextFuncLazy: begin
|
|
||||||
offset := 0; // found line after/next
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
break;
|
|
||||||
end;
|
|
||||||
offset := offset - o;
|
|
||||||
if offset = 0 then
|
|
||||||
break;
|
|
||||||
inc(i);
|
|
||||||
end;
|
|
||||||
|
|
||||||
if offset = 0 then
|
|
||||||
break;
|
|
||||||
case AFindSibling of
|
case AFindSibling of
|
||||||
fsNone: exit;
|
|
||||||
fsBefore: begin
|
fsBefore: begin
|
||||||
if i = 0 then
|
while not OffsetExist do begin
|
||||||
continue;
|
dec(offset);
|
||||||
assert(i=l, 'TDWarfLineMap.GetAddressesForLine: i=l');
|
if offset < 0 then
|
||||||
dec(i);
|
break;
|
||||||
break;
|
|
||||||
end;
|
MappedOffset := CurPage^.Map[offset];
|
||||||
else begin
|
OffsetExist := (MappedOffset and PAGE_MASK) < CurPage^.AddrCnt;
|
||||||
inc(idx);
|
end;
|
||||||
if idx >= Length(FLineIndexList) then
|
if offset < 0 then begin
|
||||||
exit;
|
dec(idx);
|
||||||
continue;
|
if idx < 0 then
|
||||||
end;
|
exit;
|
||||||
|
offset := 0;
|
||||||
|
Continue;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
fsNext, fsNextFunc, fsNextFuncLazy: begin
|
||||||
|
while not OffsetExist do begin
|
||||||
|
inc(offset);
|
||||||
|
if offset >= PAGE_SIZE then
|
||||||
|
break;
|
||||||
|
MappedOffset := CurPage^.Map[offset];
|
||||||
|
OffsetExist := (MappedOffset and PAGE_MASK) < CurPage^.AddrCnt;
|
||||||
|
end;
|
||||||
|
if offset >= PAGE_SIZE then begin
|
||||||
|
inc(idx);
|
||||||
|
if idx >= Length(FLinePageList) then
|
||||||
|
exit;
|
||||||
|
offset := PAGE_SIZE-1;
|
||||||
|
Continue;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
break;
|
||||||
until False;
|
until False;
|
||||||
|
|
||||||
ln := 256 * idx + CurOffs;
|
if not OffsetExist then
|
||||||
|
exit;
|
||||||
|
|
||||||
|
IsList := (MappedOffset and LIST_FLAG) <> 0;
|
||||||
|
MappedOffset := MappedOffset and PAGE_MASK;
|
||||||
|
FndAddr := CurPage^.Addresses[MappedOffset];
|
||||||
|
|
||||||
|
ln := PAGE_SIZE * idx + offset;
|
||||||
if ln <> ALine then
|
if ln <> ALine then
|
||||||
case AFindSibling of
|
case AFindSibling of
|
||||||
fsBefore:
|
fsBefore:
|
||||||
@ -3742,7 +3776,10 @@ begin
|
|||||||
then begin
|
then begin
|
||||||
// check same function
|
// check same function
|
||||||
if ADbgInfo = nil then exit;
|
if ADbgInfo = nil then exit;
|
||||||
if not ADbgInfo.FindProcStartEndPC(Addresses[i], Addr1, Addr2) then exit;
|
FirstAddr := FndAddr;
|
||||||
|
if IsList then
|
||||||
|
FirstAddr := PDBGPtr(FndAddr)[1];
|
||||||
|
if not ADbgInfo.FindProcStartEndPC(FirstAddr, Addr1, Addr2) then exit;
|
||||||
if GetAddressesForLine(ALine, TmpResList, False, fsBefore) then begin
|
if GetAddressesForLine(ALine, TmpResList, False, fsBefore) then begin
|
||||||
if (Length(TmpResList) = 0) or (TmpResList[0] < Addr1) or (TmpResList[0] > Addr2) then
|
if (Length(TmpResList) = 0) or (TmpResList[0] < Addr1) or (TmpResList[0] > Addr2) then
|
||||||
exit;
|
exit;
|
||||||
@ -3757,39 +3794,21 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
if AFoundLine <> nil then
|
if AFoundLine <> nil then
|
||||||
AFoundLine^ := 256 * idx + CurOffs;
|
AFoundLine^ := ln;
|
||||||
|
|
||||||
if NoData then begin
|
|
||||||
Result := True;
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
|
|
||||||
j := i + 1;
|
|
||||||
while (j < l) and (LineOffsets[j] = 0) do inc(j);
|
|
||||||
|
|
||||||
k := Length(AResultList);
|
|
||||||
SetLength(AResultList, k + (j-i));
|
|
||||||
while i < j do begin
|
|
||||||
AResultList[k] := Addresses[i];
|
|
||||||
inc(i);
|
|
||||||
inc(k);
|
|
||||||
end;
|
|
||||||
|
|
||||||
Result := True;
|
Result := True;
|
||||||
end;
|
if NoData then
|
||||||
|
exit;
|
||||||
|
|
||||||
procedure TDWarfLineMap.Compress;
|
k := Length(AResultList);
|
||||||
var
|
if (not IsList) then begin
|
||||||
i, j: Integer;
|
SetLength(AResultList, k + 1);
|
||||||
begin
|
AResultList[k] := FndAddr;
|
||||||
for i := 0 to high(FLineIndexList) do begin
|
end
|
||||||
j := Length(FLineIndexList[i].LineOffsets);
|
else begin
|
||||||
if j <> 0 then begin
|
j := PDBGPtr(FndAddr)[0];
|
||||||
j := FLineIndexList[i].Addresses[j];
|
SetLength(AResultList, k + j);
|
||||||
SetLength(FLineIndexList[i].Addresses, j+1);
|
move(PDBGPtr(FndAddr)[1], AResultList[k], j*SizeOf(TDBGPtr));
|
||||||
FLineIndexList[i].Addresses[j] := j;
|
|
||||||
SetLength(FLineIndexList[i].LineOffsets, j);
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -3834,11 +3853,15 @@ destructor TFpDwarfInfo.Destroy;
|
|||||||
procedure FreeLineNumberMap;
|
procedure FreeLineNumberMap;
|
||||||
var
|
var
|
||||||
n: Integer;
|
n: Integer;
|
||||||
|
m: PDWarfLineMap;
|
||||||
begin
|
begin
|
||||||
if FLineNumberMap = nil then
|
if FLineNumberMap = nil then
|
||||||
exit;
|
exit;
|
||||||
for n := 0 to FLineNumberMap.Count - 1 do
|
for n := 0 to FLineNumberMap.Count - 1 do begin
|
||||||
Dispose(FLineNumberMap.Data[n]);
|
m := FLineNumberMap.Data[n];
|
||||||
|
m^.Free;
|
||||||
|
Dispose(m);
|
||||||
|
end;
|
||||||
FreeAndNil(FLineNumberMap);
|
FreeAndNil(FLineNumberMap);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -4160,8 +4183,6 @@ begin
|
|||||||
if CU.Valid then
|
if CU.Valid then
|
||||||
CU.BuildLineInfo(nil, True);
|
CU.BuildLineInfo(nil, True);
|
||||||
end;
|
end;
|
||||||
for n := 0 to FLineNumberMap.Count - 1 do
|
|
||||||
FLineNumberMap.Data[n]^.Compress;
|
|
||||||
FLineNumberMapDone := True;
|
FLineNumberMapDone := True;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -5069,10 +5090,6 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
Iter.Free;
|
Iter.Free;
|
||||||
|
|
||||||
if not ADoAll then
|
|
||||||
for Idx := 0 to FOwner.FLineNumberMap.Count - 1 do
|
|
||||||
FOwner.FLineNumberMap.Data[idx]^.Compress;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TDwarfCompilationUnit.GetAddressMap: TMap;
|
function TDwarfCompilationUnit.GetAddressMap: TMap;
|
||||||
|
@ -35,7 +35,6 @@ begin
|
|||||||
LMap.Init;
|
LMap.Init;
|
||||||
for i := 0 to Length(l) - 1 do
|
for i := 0 to Length(l) - 1 do
|
||||||
LMap.SetAddressForLine(l[i], l[i]);
|
LMap.SetAddressForLine(l[i], l[i]);
|
||||||
LMap.Compress;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TTestLineMap.CheckNotFound(ASearch: Integer; AFindSibling: TGetLineAddrFindSibling;
|
procedure TTestLineMap.CheckNotFound(ASearch: Integer; AFindSibling: TGetLineAddrFindSibling;
|
||||||
|
Loading…
Reference in New Issue
Block a user