From a8fe9601de43b159d45f6584d7320a042f81d391 Mon Sep 17 00:00:00 2001 From: sergei Date: Wed, 18 Jan 2012 19:28:08 +0000 Subject: [PATCH] * Get rid of using pdynarraytypeinfo, instead treat rtti as distinct 'header' and 'data' parts. In variants unit, use rtti declarations from typinfo directly. In system unit, declare private tdynarraytypedata record which (like typinfo.TTypeData) is not packed on alignment-sensitive targets. This simplifies code and removes scary pointer manipulations, should also yield better code on aligned targets. git-svn-id: trunk@20106 - --- rtl/inc/dynarr.inc | 50 ++++++++++++++++++++++----------------------- rtl/inc/variants.pp | 40 +++++++++++------------------------- 2 files changed, 36 insertions(+), 54 deletions(-) diff --git a/rtl/inc/dynarr.inc b/rtl/inc/dynarr.inc index 351bfb0797..1a1654be36 100644 --- a/rtl/inc/dynarr.inc +++ b/rtl/inc/dynarr.inc @@ -24,6 +24,16 @@ type high : tdynarrayindex; end; + pdynarraytypedata = ^tdynarraytypedata; + tdynarraytypedata = +{$ifndef FPC_REQUIRES_PROPER_ALIGNMENT} + packed +{$endif FPC_REQUIRES_PROPER_ALIGNMENT} + record + elSize : PtrUInt; + elType2 : Pointer; + varType : Longint; + end; procedure fpc_dynarray_rangecheck(p : pointer;i : tdynarrayindex);[Public,Alias:'FPC_DYNARRAY_RANGECHECK']; compilerproc; begin @@ -52,21 +62,15 @@ function fpc_dynarray_high(p : pointer) : tdynarrayindex;[Public,Alias:'FPC_DYNA { releases and finalizes the data of a dyn. array and sets p to nil } procedure fpc_dynarray_clear_internal(p : pointer;ti : pointer); - var - eletype : pdynarraytypeinfo; begin if p=nil then exit; { skip kind and name } - inc(pointer(ti),ord(pdynarraytypeinfo(ti)^.namelen)+2); - - ti:=aligntoptr(ti); - - eletype:=pdynarraytypeinfo(pointer(pdynarraytypeinfo(pointer(ti)+sizeof(sizeint)))^); + ti:=aligntoptr(ti+2+PByte(ti)[1]); { finalize all data } - int_finalizearray(p+sizeof(tdynarray),eletype,pdynarray(p)^.high+1); + int_finalizearray(p+sizeof(tdynarray),pdynarraytypedata(ti)^.elType2,pdynarray(p)^.high+1); { release the data } freemem(p); @@ -104,7 +108,7 @@ procedure fpc_dynarray_decr_ref(var p : pointer;ti : pointer); [Public,Alias:'FP { should we remove the array? } if declocked(realp^.refcount) then begin - fpc_dynarray_clear_internal(realp,pdynarraytypeinfo(ti)); + fpc_dynarray_clear_internal(realp,ti); p := nil; end; end; @@ -144,21 +148,17 @@ procedure fpc_dynarray_setlength(var p : pointer;pti : pointer; { contains the "fixed" pointers where the refcount } { and high are at positive offsets } realp,newp : pdynarray; - ti : pdynarraytypeinfo; + ti : pointer; updatep: boolean; elesize : sizeint; - eletype : pdynarraytypeinfo; + eletype : pointer; begin - ti:=pdynarraytypeinfo(pti); - { skip kind and name } - inc(pointer(ti),ord(pdynarraytypeinfo(ti)^.namelen)+2); + ti:=aligntoptr(Pointer(pti)+2+PByte(pti)[1]); - ti:=aligntoptr(ti); - - elesize:=psizeint(ti)^; - eletype:=pdynarraytypeinfo(pointer(pdynarraytypeinfo(pointer(ti)+sizeof(sizeint)))^); + elesize:=pdynarraytypedata(ti)^.elSize; + eletype:=pdynarraytypedata(ti)^.elType2; { determine new memory size } size:=elesize*dims[0]+sizeof(tdynarray); @@ -187,7 +187,7 @@ procedure fpc_dynarray_setlength(var p : pointer;pti : pointer; if dims[0]<0 then HandleErrorFrame(201,get_frame); if declocked(realp^.refcount) then - fpc_dynarray_clear_internal(realp,pdynarraytypeinfo(pti)); + fpc_dynarray_clear_internal(realp,pti); p:=nil; exit; end; @@ -217,7 +217,7 @@ procedure fpc_dynarray_setlength(var p : pointer;pti : pointer; { if the array is now removed } { fpc_dynarray_decr_ref(p,ti); } if declocked(realp^.refcount) then - fpc_dynarray_clear_internal(realp,pdynarraytypeinfo(ti)); + fpc_dynarray_clear_internal(realp,pti); end else if dims[0]<>realp^.high+1 then begin @@ -282,7 +282,7 @@ function fpc_dynarray_copy(psrc : pointer;ti : pointer; i,size : longint; highidx : tdynarrayindex; elesize : sizeint; - eletype : pdynarraytypeinfo; + eletype : pointer; pdest : pointer; begin highidx:=lowidx+count-1; @@ -292,12 +292,10 @@ function fpc_dynarray_copy(psrc : pointer;ti : pointer; exit; realpsrc:=pdynarray(psrc-sizeof(tdynarray)); { skip kind and name } - inc(pointer(ti),ord(pdynarraytypeinfo(ti)^.namelen)+2); + ti:=aligntoptr(ti+2+PByte(ti)[1]); - ti:=aligntoptr(ti); - - elesize:=psizeint(ti)^; - eletype:=pdynarraytypeinfo(pointer(pdynarraytypeinfo(pointer(ti)+sizeof(sizeint)))^); + elesize:=pdynarraytypedata(ti)^.elSize; + eletype:=pdynarraytypedata(ti)^.elType2; { -1, -1 (highidx=lowidx-1-1=-3) is used to copy the whole array like a:=copy(b);, so update the lowidx and highidx with the values from psrc } diff --git a/rtl/inc/variants.pp b/rtl/inc/variants.pp index 2d10c0ffee..37de800f42 100644 --- a/rtl/inc/variants.pp +++ b/rtl/inc/variants.pp @@ -511,13 +511,13 @@ type positions : tdynarraypositions; Dims : SizeInt; data : Pointer; - constructor init(d : Pointer;p : pdynarraytypeinfo;_dims: SizeInt;b : tdynarraybounds); + constructor init(d : Pointer;typeInfo : Pointer;_dims: SizeInt;b : tdynarraybounds); function next : Boolean; destructor done; end; -constructor tdynarrayiter.init(d : Pointer;p : pdynarraytypeinfo;_dims: SizeInt;b : tdynarraybounds); +constructor tdynarrayiter.init(d : Pointer;typeInfo : Pointer;_dims: SizeInt;b : tdynarraybounds); var i : sizeint; begin @@ -534,16 +534,10 @@ constructor tdynarrayiter.init(d : Pointer;p : pdynarraytypeinfo;_dims: SizeInt; if i>0 then positions[i]:=Pointer(positions[i-1]^); { skip kind and name } - inc(Pointer(p),ord(pdynarraytypeinfo(p)^.namelen)+2); + typeInfo:=aligntoptr(typeInfo+2+Length(PTypeInfo(typeInfo)^.Name)); - p:=AlignToPtr(p); - - elesize[i]:=psizeint(p)^; - - { skip elesize } - inc(Pointer(p),SizeOf(sizeint)); - - p:=pdynarraytypeinfo(ppointer(p)^); + elesize[i]:=PTypeData(typeInfo)^.elSize; + typeInfo:=PTypeData(typeInfo)^.elType2; end; data:=positions[Dims-1]; end; @@ -819,12 +813,11 @@ begin { get TypeInfo of second level } { skip kind and name } - inc(Pointer(TypeInfo),ord(pdynarraytypeinfo(TypeInfo)^.namelen)+2); - TypeInfo:=AlignToPtr(TypeInfo); - TypeInfo:=ppointer(TypeInfo+SizeOf(sizeint))^; + TypeInfo:=aligntoptr(TypeInfo+2+Length(PTypeInfo(TypeInfo)^.Name)); + TypeInfo:=PTypeData(TypeInfo)^.elType2; { check recursively? } - if assigned(pdynarraytypeinfo(TypeInfo)) and (pdynarraytypeinfo(TypeInfo)^.kind=byte(tkDynArray)) then + if assigned(TypeInfo) and (PTypeInfo(TypeInfo)^.kind=tkDynArray) then begin { set to dimension of first element } arraysize:=psizeint(ppointer(p)^-SizeOf(sizeint))^; @@ -3371,22 +3364,13 @@ function DynArrayGetVariantInfo(p : Pointer; var Dims : sizeint) : sizeint; begin Result:=varNull; { skip kind and name } - inc(Pointer(p),ord(pdynarraytypeinfo(p)^.namelen)+2); - - p:=AlignToPtr(p); - - { skip elesize } - inc(p,SizeOf(sizeint)); + p:=aligntoptr(p+2+Length(PTypeInfo(p)^.Name)); { search recursive? } - if pdynarraytypeinfo(ppointer(p)^)^.kind=21{tkDynArr} then - Result:=DynArrayGetVariantInfo(ppointer(p)^,Dims) + if PTypeInfo(PTypeData(p)^.elType2)^.kind=tkDynArray then + Result:=DynArrayGetVariantInfo(PTypeData(p)^.elType2,Dims) else - begin - { skip dynarraytypeinfo } - inc(p,SizeOf(pdynarraytypeinfo)); - Result:=plongint(p)^; - end; + Result:=PTypeData(p)^.varType; inc(Dims); end;