* fixed genmultistringadd() optimization for jvm and enabled it

* created separate version of fpc_AnsiStr_Concat_multi() after all
    because it contains a punicodechar(unicodestring) typecast, which
    can't be supported on the JVM target (and splitting it out in the
    generic code seems like a bit overkill), and restored original
    generic version of fpc_AnsiStr_Concat_multi() (slightly faster
    than version partially adapted for jvm)

git-svn-id: branches/jvmbackend@20903 -
This commit is contained in:
Jonas Maebe 2012-04-16 20:51:51 +00:00
parent 1efee1d2eb
commit 8e3d7fe8d3
4 changed files with 132 additions and 16 deletions

View File

@ -2733,16 +2733,14 @@ implementation
{$endif cpuneedsmulhelper}
begin
result:=nil;
{$ifndef jvm}
{ Can we optimize multiple string additions into a single call?
This need to be done on a complete tree to detect the multiple
add nodes and is therefor done before the subtrees are processed }
if canbemultistringadd(self) then
begin
result := genmultistringadd(self);
result:=genmultistringadd(self);
exit;
end;
{$endif jvm}
{ first do the two subtrees }
firstpass(left);
firstpass(right);

View File

@ -86,7 +86,9 @@ var
implementation
uses cutils, htypechk, defutil, defcmp, globtype, globals, cpubase, ncnv, ncon,ncal,nld,nmem,
uses cutils, systems,
htypechk, defutil, defcmp, globtype, globals, cpubase,
ncnv, ncon, ncal, ninl, nld, nmem,
verbose, symconst,symdef, cgbase, procinfo;
@ -320,12 +322,9 @@ begin
inserttypeconv(sn,p.resultdef);
if is_shortstr then
begin
{$ifndef jvm}
sn:=caddrnode.create(sn);
include(sn.flags,nf_typedaddr);
include(sn.flags,nf_internal);
{$else not jvm}
inserttypeconv_internal(sn,java_shortstring);
{$endif jvm}
end;
arrp:=carrayconstructornode.create(sn,arrp);
hp:=taddnode(hp).left;
@ -367,6 +366,16 @@ begin
result:=internalstatements(newstatement);
tempnode:=ctempcreatenode.create(p.resultdef,p.resultdef.size,tt_persistent ,true);
addstatement(newstatement,tempnode);
{ initialize the temp, since it will be passed to a
var-parameter (and finalization, which is performed by the
ttempcreate node and which takes care of the initialization
on native targets, is a noop on managed VM targets) }
if (target_info.system in systems_managed_vm) and
is_managed_type(p.resultdef) then
addstatement(newstatement,cinlinenode.create(in_setlength_x,
false,
ccallparanode.create(genintconstnode(0),
ccallparanode.create(ctemprefnode.create(tempnode),nil))));
para:=ccallparanode.create(
arrp,
ccallparanode.create(ctemprefnode.create(tempnode),nil)

View File

@ -275,7 +275,7 @@ Var
p,pc : pointer;
Size,NewLen,
OldDestLen : SizeInt;
destcopy : RawByteString;
destcopy : pointer;
DestCP : TSystemCodePage;
U : UnicodeString;
sameCP : Boolean;
@ -327,9 +327,10 @@ begin
DestS:='';
widestringmanager.Unicode2AnsiMoveProc(PUnicodeChar(Pointer(U)),DestS,DestCP,Length(U));
exit;
exit;
end;
destcopy:=nil;
lowstart:=low(sarr);
if Pointer(DestS)=Pointer(sarr[lowstart]) then
inc(lowstart);
@ -342,7 +343,8 @@ begin
{ if DestS is used somewhere in the middle of the expression,
we need to make sure the original string still exists after
we empty/modify DestS }
destcopy:=dests;
destcopy:=pointer(dests);
fpc_AnsiStr_Incr_Ref(destcopy);
lowstart:=low(sarr);
break;
end;
@ -362,18 +364,18 @@ begin
SetCodePage(DestS,DestCP,False);
{ Concat all strings, except the string we already
copied in DestS }
NewLen:=OldDestLen;
pc:=Pointer(DestS);
pc:=Pointer(DestS)+OldDestLen;
for i:=lowstart to high(sarr) do
begin
p:=pointer(sarr[i]);
if assigned(p) then
begin
Size:=length(ansistring(p));
fpc_pchar_pchar_intern_charmove(pchar(p),0,pchar(pc),NewLen,Size+1);
inc(NewLen,size);
Move(p^,pc^,Size+1);
inc(pc,size);
end;
end;
fpc_AnsiStr_Decr_Ref(destcopy);
end;
{$endif FPC_HAS_ANSISTR_CONCAT_MULTI}

View File

@ -298,13 +298,120 @@ begin
temp:=S;
Size:=Length(temp);
widestringmanager.Unicode2AnsiMoveProc(PUnicodeChar(JLString(temp).toCharArray),result,cp,Size);
AnsistringClass(result).fCodePage:=cp;
end;
end;
end;
Function fpc_AnsiStr_To_AnsiStr (const S : RawByteString;cp : TSystemCodePage): RawByteString; [external name 'fpc_ansistr_to_ansistr'];
{$define FPC_HAS_ANSISTR_CONCAT_MULTI}
procedure fpc_AnsiStr_Concat_multi (var DestS:RawByteString;const sarr:array of RawByteString{$ifdef FPC_HAS_CPSTRING};cp : TSystemCodePage{$endif FPC_HAS_CPSTRING}); compilerproc;
Var
lowstart,i : Longint;
p : pointer;
Size,NewLen,
OldDestLen : SizeInt;
destcopy : RawByteString;
DestCP : TSystemCodePage;
U : UnicodeString;
sameCP : Boolean;
tmpStr : RawByteString;
tmpCP : TSystemCodePage;
begin
if high(sarr)=0 then
begin
DestS:='';
exit;
end;
{$ifdef FPC_HAS_CPSTRING}
if (Pointer(DestS)=nil) then
DestCP:=cp
else
DestCP:=StringCodePage(DestS);
{$else FPC_HAS_CPSTRING}
DestCP:=StringCodePage(DestS);
{$endif FPC_HAS_CPSTRING}
if (DestCP=CP_ACP) then
DestCP:=DefaultSystemCodePage;
sameCP:=true;
lowstart:=low(sarr);
for i:=lowstart to high(sarr) do
begin
tmpCP:=StringCodePage(sarr[i]);
if tmpCP=CP_ACP then
tmpCP:=DefaultSystemCodePage;
if (DestCP<>tmpCp) then
begin
sameCP:=false;
break;
end;
end;
if not sameCP then
begin
U:='';
for i:=lowstart to high(sarr) do begin
tmpCP:=StringCodePage(sarr[i]);
if (tmpCP=CP_ACP) then
begin
tmpStr:=sarr[i];
SetCodePage(tmpStr,DefaultSystemCodePage,False);
U:=U+UnicodeString(tmpStr);
end
else
U:=U+UnicodeString(sarr[i]);
end;
DestS:='';
widestringmanager.Unicode2AnsiMoveProc(PUnicodeChar(JLString(U).toCharArray),DestS,DestCP,Length(U));
exit;
end;
lowstart:=low(sarr);
if Pointer(DestS)=Pointer(sarr[lowstart]) then
inc(lowstart);
{ Check for another reuse, then we can't use
the append optimization }
for i:=lowstart to high(sarr) do
begin
if Pointer(DestS)=Pointer(sarr[i]) then
begin
{ if DestS is used somewhere in the middle of the expression,
we need to make sure the original string still exists after
we empty/modify DestS -- not necessary on JVM platform, ansistrings
are not explicitly refrence counted there }
lowstart:=low(sarr);
break;
end;
end;
{ Start with empty DestS if we start with concatting
the first array element }
if lowstart=low(sarr) then
DestS:='';
OldDestLen:=length(DestS);
{ Calculate size of the result so we can do
a single call to SetLength() }
NewLen:=0;
for i:=low(sarr) to high(sarr) do
inc(NewLen,length(sarr[i]));
SetLength(DestS,NewLen);
if (StringCodePage(DestS) <> DestCP) then
SetCodePage(DestS,DestCP,False);
{ Concat all strings, except the string we already
copied in DestS }
NewLen:=OldDestLen;
for i:=lowstart to high(sarr) do
begin
p:=pointer(sarr[i]);
if assigned(p) then
begin
Size:=length(ansistring(p));
fpc_pchar_pchar_intern_charmove(pchar(ansistring(p)),0,pchar(DestS),NewLen,Size+1);
inc(NewLen,size);
end;
end;
end;
{$define FPC_HAS_ANSISTR_TO_SHORTSTR}
procedure fpc_AnsiStr_To_ShortStr (out res: shortstring; const S2 : RawByteString);[Public, alias: 'FPC_ANSISTR_TO_SHORTSTR']; compilerproc;
{