From f1050aeb73100c28576e1a91915846e04fd8e053 Mon Sep 17 00:00:00 2001 From: Rika Ichinose Date: Thu, 28 Nov 2024 06:44:46 +0300 Subject: [PATCH] Simplify dynarr.inc. --- rtl/inc/dynarr.inc | 169 ++++++++++++++++++--------------------------- 1 file changed, 66 insertions(+), 103 deletions(-) diff --git a/rtl/inc/dynarr.inc b/rtl/inc/dynarr.inc index a119ed29cd..acf0c1885f 100644 --- a/rtl/inc/dynarr.inc +++ b/rtl/inc/dynarr.inc @@ -80,22 +80,19 @@ function fpc_dynarray_high(p : pointer) : tdynarrayindex;[Public,Alias:'FPC_DYNA procedure fpc_dynarray_clear(var p : pointer;ti : pointer); [Public,Alias:'FPC_DYNARRAY_CLEAR']; compilerproc; var - realp : pdynarray; + pv : pdynarray; begin - if (P=Nil) then + pv:=p; + if not assigned(pv) then exit; - realp:=pdynarray(p-sizeof(tdynarray)); - if realp^.refcount=0 then - HandleErrorAddrFrameInd(204,get_pc_addr,get_frame); - - if (realp^.refcount>0) and declocked(realp^.refcount) then - begin - ti:=aligntoqword(ti+2+PByte(ti)[1]); - if assigned(pdynarraytypedata(ti)^.elType) then - int_finalizearray(p,pdynarraytypedata(ti)^.elType^,realp^.high+1); - freemem(realp); - end; p:=nil; + if (pv[-1].refcount>0) and declocked(pv[-1].refcount) then + begin + ti:=pdynarraytypedata(aligntoqword(ti+2+PByte(ti)[1]))^.elType; + if assigned(ti) then + int_finalizearray(pv,PPointer(ti)^,pv[-1].high+1); + freemem(pv-1); + end; end; { alias for internal use } @@ -103,17 +100,9 @@ Procedure fpc_dynarray_clear (var p : pointer;ti : pointer);[external name 'FPC_ procedure fpc_dynarray_incr_ref(p : pointer);[Public,Alias:'FPC_DYNARRAY_INCR_REF']; compilerproc; - var - realp : pdynarray; begin - if p=nil then - exit; - - realp:=pdynarray(p-sizeof(tdynarray)); - if realp^.refcount=0 then - HandleErrorAddrFrameInd(204,get_pc_addr,get_frame) - else if realp^.refcount>0 then - inclocked(realp^.refcount); + if assigned(p) and (pdynarray(p)[-1].refcount>0) then + inclocked(pdynarray(p)[-1].refcount); end; { provide local access to dynarr_decr_ref for dynarr_setlength } @@ -138,82 +127,56 @@ procedure fpc_dynarray_setlength(var p : pointer;pti : pointer; var i : tdynarrayindex; - movelen, - size : sizeint; + movelen,size,_size,elesize,oldlen,newlen : sizeint; { contains the "fixed" pointers where the refcount } { and high are at positive offsets } realp,newp : pdynarray; - ti : pointer; - elesize : sizeint; - eletype,eletypemngd : pointer; - movsize,_size : sizeint; + ti,eletypemngd : pointer; begin + newlen:=dims[0]; { negative or zero length? } - if dims[0]<=0 then - { negative length is not allowed } - if dims[0]<0 then - HandleErrorAddrFrameInd(201,get_pc_addr,get_frame) - else - begin - { if the new dimension is 0, we've to release all data } - fpc_dynarray_clear(p,pti); - exit; - end; + if newlen<=0 then + begin + { negative length is not allowed } + if newlen<0 then + HandleErrorAddrFrameInd(201,get_pc_addr,get_frame); + { if the new dimension is 0, we've to release all data } + fpc_dynarray_clear(p,pti); + exit; + end; { skip kind and name } ti:=aligntoqword(Pointer(pti)+2+PByte(pti)[1]); elesize:=pdynarraytypedata(ti)^.elSize; - eletype:=pdynarraytypedata(ti)^.elType2^; { only set if type needs finalization } - if assigned(pdynarraytypedata(ti)^.elType) then - eletypemngd:=pdynarraytypedata(ti)^.elType^ - else - eletypemngd:=nil; + eletypemngd:=pdynarraytypedata(ti)^.elType; + if assigned(eletypemngd) then + eletypemngd:=PPointer(eletypemngd)^; { determine new memory size, throw a runtime error on overflow } {$push} {$q+,r+} - size:=elesize*dims[0]+sizeof(tdynarray); + size:=elesize*newlen+sizeof(tdynarray); {$pop} - { not assigned yet? } - if not(assigned(p)) then + if assigned(p) then begin - newp:=AllocMem(size); - { call int_InitializeArray for management operators; not required if no operators as memory is already zeroed } - if assigned(eletypemngd) and (PTypeKind(eletype)^ in [tkRecord, tkObject, tkArray]) and (RTTIManagementAndSize(eletype, rotInitialize, _size, true)) then - int_InitializeArray(pointer(newp)+sizeof(tdynarray), eletype, dims[0]); - end - else - begin - realp:=pdynarray(p-sizeof(tdynarray)); - newp := realp; - - if realp^.refcount<>1 then + oldlen:=pdynarray(p-sizeof(tdynarray))^.high+1; + if pdynarray(p-sizeof(tdynarray))^.refcount<>1 then begin - { make an unique copy } newp:=getmem(size); - fillchar(newp^,sizeof(tdynarray),0); - if realp^.high < dims[0] then - movelen := realp^.high+1 - else - movelen := dims[0]; - movsize := elesize*movelen; - move(p^,(pointer(newp)+sizeof(tdynarray))^, movsize); - if size-sizeof(tdynarray)>movsize then - begin - fillchar((pointer(newp)+sizeof(tdynarray)+movsize)^,size-sizeof(tdynarray)-movsize,0); - if assigned(eletypemngd) and (PTypeKind(eletype)^ in [tkRecord, tkObject, tkArray]) and (RTTIManagementAndSize(eletype, rotInitialize, _size, true)) then - int_InitializeArray(pointer(newp)+sizeof(tdynarray)+movsize, eletype, dims[0]-movelen); - end; - + { make an unique copy } + movelen:=oldlen; + if newlennewp^.high+1 then - begin - { grow the array } - reallocmem(realp,size); - newp := realp; - fillchar((pointer(newp)+sizeof(tdynarray)+elesize*(newp^.high+1))^, - (dims[0]-newp^.high-1)*elesize,0); - if assigned(eletypemngd) and (PTypeKind(eletype)^ in [tkRecord, tkObject, tkArray]) and (RTTIManagementAndSize(eletype, rotInitialize, _size, true)) then - int_InitializeArray(pointer(newp)+sizeof(tdynarray)+elesize*(newp^.high+1), - eletype, dims[0]-newp^.high-1); + { Finalize if shrinking. } + if assigned(eletypemngd) and (newlenoldlen then + begin + { Initialize new items. } + if oldlen<>0 then { Skip if AllocMem was used. CAREFUL: Assigned(p) won’t work because of fpc_dynarray_clear above. } + fillchar((pointer(newp)+sizeof(tdynarray)+elesize*oldlen)^,(newlen-oldlen)*elesize,0); + if assigned(eletypemngd) and (PTypeKind(eletypemngd)^ in [tkRecord, tkObject, tkArray]) and RTTIManagementAndSize(eletypemngd, rotInitialize, _size, true) then + int_InitializeArray(pointer(newp)+sizeof(tdynarray)+elesize*oldlen,eletypemngd,newlen-oldlen); + end; + p:=pointer(newp)+sizeof(tdynarray); + newp^.refcount:=1; + newp^.high:=newlen-1; + { handle nested arrays } + if dimcount>1 then + begin + for i:=0 to newlen-1 do + int_dynarray_setlength(pointer((pointer(newp)+sizeof(tdynarray)+i*elesize)^), + pdynarraytypedata(ti)^.elType2^,dimcount-1,@dims[1]); end; - p:=pointer(newp)+sizeof(tdynarray); - newp^.refcount:=1; - newp^.high:=dims[0]-1; - { handle nested arrays } - if dimcount>1 then - begin - for i:=0 to dims[0]-1 do - int_dynarray_setlength(pointer((pointer(newp)+sizeof(tdynarray)+i*elesize)^), - eletype,dimcount-1,@dims[1]); - end; end;