Browse Source

Rewrite fpc_shortstr_concat_multi for AVR to not use a temporary shortstring to reduce RAM usage.

ccrause 2 years ago
parent
commit
991460c4ee
2 changed files with 65 additions and 1 deletions
  1. 62 0
      rtl/avr/avr.inc
  2. 3 1
      rtl/inc/generic.inc

+ 62 - 0
rtl/avr/avr.inc

@@ -279,5 +279,67 @@ function InterLockedExchangeAdd (var Target: smallint;Source : smallint) : small
     avr_restore(temp_sreg);
   end;
 
+{$define FPC_HAS_SHORTSTR_SHORTSTR_INTERN_CHARMOVE}
+procedure fpc_shortstr_shortstr_intern_charmove(const src: shortstring; const srcindex: byte; var dst: shortstring; const dstindex, len: byte); {$ifdef SYSTEMINLINE}inline;{$endif}
+  begin
+    move(src[srcindex],dst[dstindex],len);
+  end;
+
+{$define FPC_SYSTEM_HAS_FPC_SHORTSTR_CONCAT_MULTI}
+procedure fpc_shortstr_concat_multi(var dests:shortstring;const sarr:array of pshortstring);compilerproc;
+  var
+    s2l, tmpindex : byte;
+    i,
+    Len : ObjpasInt;
+    relocatedstringindex: byte;
+    p : pshortstring;
+  begin
+    if high(sarr)=0 then
+      begin
+        DestS:='';
+        exit;
+      end;
+    { for s := s1 + s + ..., relocate s to the correct first position in dests
+      and remember this position for possible subsequent occurences of s }
+    Len:=1;
+    i:=low(sarr);
+    while (i<=high(sarr)) and (@dests<>sarr[i]) and (Len<=high(dests)) do
+      begin
+        Len:=Len+length(sarr[i]^);
+        inc(i);
+      end;
+
+    if Len<=high(dests) then
+      begin
+        relocatedstringindex:=Len;
+        s2l:=length(dests);
+        if uint16(s2l)+uint16(relocatedstringindex) > high(dests) then
+          s2l:=high(dests)-relocatedstringindex+1;
+        fpc_shortstr_shortstr_intern_charmove(dests,1,dests,relocatedstringindex,s2l);
+      end;
+
+    Len:=0;
+    for i:=low(sarr) to high(sarr) do
+      begin
+        p:=sarr[i];
+        if assigned(p) then
+          begin
+            s2l:=length(p^);
+            if Len+s2l>high(dests) then
+              s2l:=high(dests)-Len;
+
+            { Use relocated string position if src = dests }
+            if (p=@dests) then
+              tmpindex:=relocatedstringindex
+            else
+              tmpindex:=1;
+
+            fpc_shortstr_shortstr_intern_charmove(p^,tmpindex,dests,Len+1,s2l);
+            inc(Len,s2l);
+          end;
+      end;
+    dests[0]:=Chr(Len);
+  end;
+
 {include hand-optimized assembler code}
 {$i math.inc}

+ 3 - 1
rtl/inc/generic.inc

@@ -958,7 +958,9 @@ begin
     end;
   dests[0]:=chr(s1l+s2l);
 end;
+{$endif ndef FPC_SYSTEM_HAS_FPC_SHORTSTR_CONCAT}
 
+{$ifndef FPC_SYSTEM_HAS_FPC_SHORTSTR_CONCAT_MULTI}
 procedure fpc_shortstr_concat_multi(var dests:shortstring;const sarr:array of pshortstring);compilerproc;
 var
   s2l : byte;
@@ -1020,7 +1022,7 @@ begin
   if needtemp then
     DestS:=TmpStr;
 end;
-{$endif ndef FPC_SYSTEM_HAS_FPC_SHORTSTR_CONCAT}
+{$endif ndef FPC_SYSTEM_HAS_FPC_SHORTSTR_CONCAT_MULTI}
 
 {$pop}