mirror of
				https://gitlab.com/freepascal.org/fpc/source.git
				synced 2025-11-04 09:19:39 +01:00 
			
		
		
		
	* optimization in tcg386.g_intf_wrapper: use the much more efficient case 1
for virtual methods, that use the register calling convention, but have at least one free register (i.e. not used as a parameter and not required to be preserved by the function) git-svn-id: trunk@25830 -
This commit is contained in:
		
							parent
							
								
									bfd31e7516
								
							
						
					
					
						commit
						378afb69b2
					
				@ -30,7 +30,7 @@ unit cgcpu;
 | 
			
		||||
       cgbase,cgobj,cg64f32,cgx86,
 | 
			
		||||
       aasmbase,aasmtai,aasmdata,aasmcpu,
 | 
			
		||||
       cpubase,parabase,cgutils,
 | 
			
		||||
       symconst,symdef
 | 
			
		||||
       symconst,symdef,symsym
 | 
			
		||||
       ;
 | 
			
		||||
 | 
			
		||||
    type
 | 
			
		||||
@ -616,17 +616,17 @@ unit cgcpu;
 | 
			
		||||
      possible calling conventions:
 | 
			
		||||
                    default stdcall cdecl pascal register
 | 
			
		||||
      default(0):      OK     OK    OK     OK       OK
 | 
			
		||||
      virtual(1):      OK     OK    OK     OK       OK(2)
 | 
			
		||||
      virtual(1):      OK     OK    OK     OK       OK(2 or 1)
 | 
			
		||||
 | 
			
		||||
      (0):
 | 
			
		||||
          set self parameter to correct value
 | 
			
		||||
          jmp mangledname
 | 
			
		||||
 | 
			
		||||
      (1): The wrapper code use %eax to reach the virtual method address
 | 
			
		||||
      (1): The wrapper code use %ecx to reach the virtual method address
 | 
			
		||||
           set self to correct value
 | 
			
		||||
           move self,%eax
 | 
			
		||||
           mov  0(%eax),%eax ; load vmt
 | 
			
		||||
           jmp  vmtoffs(%eax) ; method offs
 | 
			
		||||
           mov  0(%eax),%ecx ; load vmt
 | 
			
		||||
           jmp  vmtoffs(%ecx) ; method offs
 | 
			
		||||
 | 
			
		||||
      (2): Virtual use values pushed on stack to reach the method address
 | 
			
		||||
           so the following code be generated:
 | 
			
		||||
@ -642,6 +642,27 @@ unit cgcpu;
 | 
			
		||||
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      { returns whether ECX is used as a parameter }
 | 
			
		||||
      function is_ecx_used: boolean;
 | 
			
		||||
        var
 | 
			
		||||
          i: Integer;
 | 
			
		||||
          hp: tparavarsym;
 | 
			
		||||
          paraloc: PCGParaLocation;
 | 
			
		||||
        begin
 | 
			
		||||
          for i:=0 to procdef.paras.count-1 do
 | 
			
		||||
           begin
 | 
			
		||||
             hp:=tparavarsym(procdef.paras[i]);
 | 
			
		||||
             paraloc:=hp.paraloc[calleeside].Location;
 | 
			
		||||
             while paraloc<>nil do
 | 
			
		||||
               begin
 | 
			
		||||
                 if (paraloc^.Loc=LOC_REGISTER) and (getsupreg(paraloc^.register)=RS_ECX) then
 | 
			
		||||
                   exit(true);
 | 
			
		||||
                 paraloc:=paraloc^.Next;
 | 
			
		||||
               end;
 | 
			
		||||
           end;
 | 
			
		||||
          Result:=false;
 | 
			
		||||
        end;
 | 
			
		||||
 | 
			
		||||
      procedure getselftoeax(offs: longint);
 | 
			
		||||
        var
 | 
			
		||||
          href : treference;
 | 
			
		||||
@ -660,23 +681,23 @@ unit cgcpu;
 | 
			
		||||
            end;
 | 
			
		||||
        end;
 | 
			
		||||
 | 
			
		||||
      procedure loadvmttoeax;
 | 
			
		||||
      procedure loadvmtto(reg: tregister);
 | 
			
		||||
        var
 | 
			
		||||
          href : treference;
 | 
			
		||||
        begin
 | 
			
		||||
          { mov  0(%eax),%eax ; load vmt}
 | 
			
		||||
          { mov  0(%eax),%reg ; load vmt}
 | 
			
		||||
          reference_reset_base(href,NR_EAX,0,4);
 | 
			
		||||
          cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_EAX);
 | 
			
		||||
          cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,reg);
 | 
			
		||||
        end;
 | 
			
		||||
 | 
			
		||||
      procedure op_oneaxmethodaddr(op: TAsmOp);
 | 
			
		||||
      procedure op_onregmethodaddr(op: TAsmOp; reg: tregister);
 | 
			
		||||
        var
 | 
			
		||||
          href : treference;
 | 
			
		||||
        begin
 | 
			
		||||
          if (procdef.extnumber=$ffff) then
 | 
			
		||||
            Internalerror(200006139);
 | 
			
		||||
          { call/jmp  vmtoffs(%eax) ; method offs }
 | 
			
		||||
          reference_reset_base(href,NR_EAX,tobjectdef(procdef.struct).vmtmethodoffset(procdef.extnumber),4);
 | 
			
		||||
          { call/jmp  vmtoffs(%reg) ; method offs }
 | 
			
		||||
          reference_reset_base(href,reg,tobjectdef(procdef.struct).vmtmethodoffset(procdef.extnumber),4);
 | 
			
		||||
          list.concat(taicpu.op_ref(op,S_L,href));
 | 
			
		||||
        end;
 | 
			
		||||
 | 
			
		||||
@ -724,13 +745,13 @@ unit cgcpu;
 | 
			
		||||
        if (po_virtualmethod in procdef.procoptions) and
 | 
			
		||||
            not is_objectpascal_helper(procdef.struct) then
 | 
			
		||||
          begin
 | 
			
		||||
            if (procdef.proccalloption=pocall_register) then
 | 
			
		||||
            if (procdef.proccalloption=pocall_register) and is_ecx_used then
 | 
			
		||||
              begin
 | 
			
		||||
                { case 2 }
 | 
			
		||||
                list.concat(taicpu.op_reg(A_PUSH,S_L,NR_EBX)); { allocate space for address}
 | 
			
		||||
                list.concat(taicpu.op_reg(A_PUSH,S_L,NR_EAX));
 | 
			
		||||
                getselftoeax(8);
 | 
			
		||||
                loadvmttoeax;
 | 
			
		||||
                loadvmtto(NR_EAX);
 | 
			
		||||
                loadmethodoffstoeax;
 | 
			
		||||
                { mov %eax,4(%esp) }
 | 
			
		||||
                reference_reset_base(href,NR_ESP,4,4);
 | 
			
		||||
@ -744,8 +765,8 @@ unit cgcpu;
 | 
			
		||||
              begin
 | 
			
		||||
                { case 1 }
 | 
			
		||||
                getselftoeax(0);
 | 
			
		||||
                loadvmttoeax;
 | 
			
		||||
                op_oneaxmethodaddr(A_JMP);
 | 
			
		||||
                loadvmtto(NR_ECX);
 | 
			
		||||
                op_onregmethodaddr(A_JMP,NR_ECX);
 | 
			
		||||
              end;
 | 
			
		||||
          end
 | 
			
		||||
        { case 0 }
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user