Browse Source

* 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 -

Jonas Maebe 13 years ago
parent
commit
8e3d7fe8d3
4 changed files with 132 additions and 16 deletions
  1. 1 3
      compiler/nadd.pas
  2. 14 5
      compiler/nopt.pas
  3. 9 7
      rtl/inc/astrings.inc
  4. 108 1
      rtl/java/jastrings.inc

+ 1 - 3
compiler/nadd.pas

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

+ 14 - 5
compiler/nopt.pas

@@ -86,7 +86,9 @@ var
 
 
 implementation
 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;
      verbose, symconst,symdef, cgbase, procinfo;
 
 
 
 
@@ -320,12 +322,9 @@ begin
       inserttypeconv(sn,p.resultdef);
       inserttypeconv(sn,p.resultdef);
       if is_shortstr then
       if is_shortstr then
         begin
         begin
-{$ifndef jvm}
           sn:=caddrnode.create(sn);
           sn:=caddrnode.create(sn);
+          include(sn.flags,nf_typedaddr);
           include(sn.flags,nf_internal);
           include(sn.flags,nf_internal);
-{$else not jvm}
-          inserttypeconv_internal(sn,java_shortstring);
-{$endif jvm}
         end;
         end;
       arrp:=carrayconstructornode.create(sn,arrp);
       arrp:=carrayconstructornode.create(sn,arrp);
       hp:=taddnode(hp).left;
       hp:=taddnode(hp).left;
@@ -367,6 +366,16 @@ begin
       result:=internalstatements(newstatement);
       result:=internalstatements(newstatement);
       tempnode:=ctempcreatenode.create(p.resultdef,p.resultdef.size,tt_persistent ,true);
       tempnode:=ctempcreatenode.create(p.resultdef,p.resultdef.size,tt_persistent ,true);
       addstatement(newstatement,tempnode);
       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(
       para:=ccallparanode.create(
               arrp,
               arrp,
               ccallparanode.create(ctemprefnode.create(tempnode),nil)
               ccallparanode.create(ctemprefnode.create(tempnode),nil)

+ 9 - 7
rtl/inc/astrings.inc

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

+ 108 - 1
rtl/java/jastrings.inc

@@ -298,13 +298,120 @@ begin
           temp:=S;
           temp:=S;
           Size:=Length(temp);
           Size:=Length(temp);
           widestringmanager.Unicode2AnsiMoveProc(PUnicodeChar(JLString(temp).toCharArray),result,cp,Size);
           widestringmanager.Unicode2AnsiMoveProc(PUnicodeChar(JLString(temp).toCharArray),result,cp,Size);
-          AnsistringClass(result).fCodePage:=cp;
         end;
         end;
     end;
     end;
 end;
 end;
 
 
 Function fpc_AnsiStr_To_AnsiStr (const S : RawByteString;cp : TSystemCodePage): RawByteString; [external name 'fpc_ansistr_to_ansistr'];
 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}
 {$define FPC_HAS_ANSISTR_TO_SHORTSTR}
 procedure fpc_AnsiStr_To_ShortStr (out res: shortstring; const S2 : RawByteString);[Public, alias: 'FPC_ANSISTR_TO_SHORTSTR'];  compilerproc;
 procedure fpc_AnsiStr_To_ShortStr (out res: shortstring; const S2 : RawByteString);[Public, alias: 'FPC_ANSISTR_TO_SHORTSTR'];  compilerproc;
 {
 {