Parcourir la 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 il y a 13 ans
Parent
commit
8e3d7fe8d3
4 fichiers modifiés avec 132 ajouts et 16 suppressions
  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}
       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);

+ 14 - 5
compiler/nopt.pas

@@ -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)

+ 9 - 7
rtl/inc/astrings.inc

@@ -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}
 

+ 108 - 1
rtl/java/jastrings.inc

@@ -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;
 {