Bladeren bron

+ Initialize/finalize variants using dedicated helpers, produces both smaller (no RTTI loading necessary) and faster (direct path taken) code.

git-svn-id: trunk@19442 -
sergei 14 jaren geleden
bovenliggende
commit
6e23565edf
4 gewijzigde bestanden met toevoegingen van 43 en 6 verwijderingen
  1. 22 4
      compiler/cgobj.pas
  2. 14 0
      compiler/nutils.pas
  3. 2 0
      rtl/inc/compproc.inc
  4. 5 2
      rtl/inc/variant.inc

+ 22 - 4
compiler/cgobj.pas

@@ -3627,18 +3627,27 @@ implementation
       begin
         cgpara1.init;
         cgpara2.init;
-        paramanager.getintparaloc(pocall_default,1,cgpara1);
-        paramanager.getintparaloc(pocall_default,2,cgpara2);
          if is_ansistring(t) or
             is_widestring(t) or
             is_unicodestring(t) or
             is_interfacecom_or_dispinterface(t) or
             is_dynamic_array(t) then
            a_load_const_ref(list,OS_ADDR,0,ref)
+         else if t.typ=variantdef then
+           begin
+             paramanager.getintparaloc(pocall_default,1,cgpara1);
+             a_loadaddr_ref_cgpara(list,ref,cgpara1);
+             paramanager.freecgpara(list,cgpara1);
+             allocallcpuregisters(list);
+             a_call_name(list,'FPC_VARIANT_INIT',false);
+             deallocallcpuregisters(list);
+           end
          else
            begin
               if is_open_array(t) then
                 InternalError(201103052);
+              paramanager.getintparaloc(pocall_default,1,cgpara1);
+              paramanager.getintparaloc(pocall_default,2,cgpara2);
               reference_reset_symbol(href,RTTIWriter.get_rtti_label(t,initrtti),0,sizeof(pint));
               a_loadaddr_ref_cgpara(list,href,cgpara2);
               a_loadaddr_ref_cgpara(list,ref,cgpara1);
@@ -3660,8 +3669,6 @@ implementation
       begin
         cgpara1.init;
         cgpara2.init;
-        paramanager.getintparaloc(pocall_default,1,cgpara1);
-        paramanager.getintparaloc(pocall_default,2,cgpara2);
          if is_ansistring(t) or
             is_widestring(t) or
             is_unicodestring(t) or
@@ -3670,10 +3677,21 @@ implementation
               g_decrrefcount(list,t,ref);
               a_load_const_ref(list,OS_ADDR,0,ref);
             end
+         else if t.typ=variantdef then
+           begin
+             paramanager.getintparaloc(pocall_default,1,cgpara1);
+             a_loadaddr_ref_cgpara(list,ref,cgpara1);
+             paramanager.freecgpara(list,cgpara1);
+             allocallcpuregisters(list);
+             a_call_name(list,'FPC_VARIANT_CLEAR',false);
+             deallocallcpuregisters(list);
+           end
          else
            begin
               if is_open_array(t) then
                 InternalError(201103051);
+              paramanager.getintparaloc(pocall_default,1,cgpara1);
+              paramanager.getintparaloc(pocall_default,2,cgpara2);
               reference_reset_symbol(href,RTTIWriter.get_rtti_label(t,initrtti),0,sizeof(pint));
               a_loadaddr_ref_cgpara(list,href,cgpara2);
               a_loadaddr_ref_cgpara(list,ref,cgpara1);

+ 14 - 0
compiler/nutils.pas

@@ -602,6 +602,13 @@ implementation
                cnilnode.create
                );
           end
+        else if (p.resultdef.typ=variantdef) then
+          begin
+            result:=ccallnode.createintern('fpc_variant_init',
+              ccallparanode.create(
+                ctypeconvnode.create_internal(p,search_system_type('TVARDATA').typedef),
+              nil));
+          end
         else
           begin
             result:=ccallnode.createintern('fpc_initialize',
@@ -670,6 +677,13 @@ implementation
                cnilnode.create
                ));
           end
+        else if p.resultdef.typ=variantdef then
+          begin
+            result:=ccallnode.createintern('fpc_variant_clear',
+              ccallparanode.create(
+                ctypeconvnode.create_internal(p,search_system_type('TVARDATA').typedef),
+              nil));
+          end
         else
           result:=ccallnode.createintern('fpc_finalize',
                 ccallparanode.create(

+ 2 - 0
rtl/inc/compproc.inc

@@ -546,6 +546,8 @@ function fpc_SetupReadStr_Widestr(const s: widestring): PText; compilerproc;
 {$endif FPC_HAS_FEATURE_TEXTIO}
 
 {$ifdef FPC_HAS_FEATURE_VARIANTS}
+procedure fpc_variant_init(var v: tvardata);compilerproc;
+procedure fpc_variant_clear(var v: tvardata);compilerproc;
 procedure fpc_variant_copy(d,s : pointer);compilerproc;
 procedure fpc_variant_copy_overwrite(source, dest : pointer);compilerproc;
 procedure fpc_write_text_variant(Len : Longint;var f : Text;const v : variant); compilerproc;

+ 5 - 2
rtl/inc/variant.inc

@@ -21,7 +21,7 @@ var
     Compiler helper routines.
   ---------------------------------------------------------------------}
 
-procedure variant_init(var v : tvardata);[Public,Alias:'FPC_VARIANT_INIT'];
+procedure fpc_variant_init(var v : tvardata);[Public,Alias:'FPC_VARIANT_INIT'];compilerproc;
   begin
      { calling the variant manager here is a problem because the static/global variants
        are initialized while the variant manager isn't assigned }
@@ -29,12 +29,15 @@ procedure variant_init(var v : tvardata);[Public,Alias:'FPC_VARIANT_INIT'];
   end;
 
 
-procedure variant_clear(var v : tvardata);[Public,Alias:'FPC_VARIANT_CLEAR'];
+procedure fpc_variant_clear(var v : tvardata);[Public,Alias:'FPC_VARIANT_CLEAR'];compilerproc;
   begin
     if assigned(VarClearProc) then
       VarClearProc(v);
   end;
 
+{ declare aliases for local use }
+procedure variant_init(var v: tvardata); external name 'FPC_VARIANT_INIT';
+procedure variant_clear(var v: tvardata); external name 'FPC_VARIANT_CLEAR';
 
 procedure variant_addref(var v : tvardata);[Public,Alias:'FPC_VARIANT_ADDREF'];
   begin