Browse Source

Rework the interface table of VMTs to get rid of FPC_EMPTYINTF.

Previously we had the following approach:
- classes that implemented interfaces had an interface table
- classes that didn't implement an interface, but inherited from a class that did had a Nil entry
- classes that didn't implement any interface (including their parents) had a reference to FPC_EMPTYINTF (this was to optimize lookups)

Now the approach is as follows:
- classes that implement an interface or have a parent that implements an interface have an interface table; if the class itself doesn't implement an interface then the count will be 0
- classes that don't implement an interface at all (neither them nor their parents) have a Nil interface table

This way FPC_EMPTYINTF can be removed without sacrificing at least the optimization for classes without any interface. For classes that have parents with interfaces there will be a small speed penalty due to an additional lookup for the counter.

git-svn-id: trunk@34087 -
svenbarth 9 years ago
parent
commit
7a5bac9cd3
2 changed files with 25 additions and 19 deletions
  1. 13 15
      compiler/ncgvmt.pas
  2. 12 4
      rtl/inc/objpas.inc

+ 13 - 15
compiler/ncgvmt.pas

@@ -818,15 +818,18 @@ implementation
         datatcb.emit_tai(Tai_const.Create_pint(_class.ImplementedInterfaces.count),search_system_type('SIZEUINT').typedef);
         interfaceentrydef:=search_system_type('TINTERFACEENTRY').typedef;
         interfaceentrytypedef:=search_system_type('TINTERFACEENTRYTYPE').typedef;
-        interfacearray:=carraydef.getreusable(interfaceentrydef,_class.ImplementedInterfaces.count);
-        datatcb.maybe_begin_aggregate(interfacearray);
-        { Write vtbl references }
-        for i:=0 to _class.ImplementedInterfaces.count-1 do
+        if _class.ImplementedInterfaces.count>0 then
           begin
-            ImplIntf:=TImplementedInterface(_class.ImplementedInterfaces[i]);
-            intf_gen_intf_ref(datatcb,ImplIntf,i,interfaceentrydef,interfaceentrytypedef);
+            interfacearray:=carraydef.getreusable(interfaceentrydef,_class.ImplementedInterfaces.count);
+            datatcb.maybe_begin_aggregate(interfacearray);
+            { Write vtbl references }
+            for i:=0 to _class.ImplementedInterfaces.count-1 do
+              begin
+                ImplIntf:=TImplementedInterface(_class.ImplementedInterfaces[i]);
+                intf_gen_intf_ref(datatcb,ImplIntf,i,interfaceentrydef,interfaceentrytypedef);
+              end;
+            datatcb.maybe_end_aggregate(interfacearray);
           end;
-        datatcb.maybe_end_aggregate(interfacearray);
         intftabledef:=datatcb.end_anonymous_record;
         tcb.finish_internal_data_builder(datatcb,lab,intftabledef,intftabledef.alignment);
 
@@ -1084,7 +1087,7 @@ implementation
             tcb.finish_internal_data_builder(datatcb,classnamelabel,classnamedef,sizeof(pint));
 
             { interface table }
-            if _class.ImplementedInterfaces.count>0 then
+            if _class.implements_any_interfaces then
               intf_write_table(tcb,interfacetable,interfacetabledef);
 
             genpublishedmethodstable(tcb,methodnametable,methodnametabledef);
@@ -1180,18 +1183,13 @@ implementation
             tcb.emit_tai(Tai_const.Create_nil_dataptr,voidpointertype);
             { interface table }
             pinterfacetabledef:=search_system_type('PINTERFACETABLE').typedef;
-            if _class.ImplementedInterfaces.count>0 then
+            if _class.implements_any_interfaces then
               begin
                 tcb.queue_init(pinterfacetabledef);
                 tcb.queue_emit_asmsym(interfacetable,interfacetabledef)
               end
-            else if _class.implements_any_interfaces then
-              tcb.emit_tai(Tai_const.Create_nil_dataptr,pinterfacetabledef)
             else
-              begin
-                tcb.queue_init(pinterfacetabledef);
-                tcb.queue_emit_asmsym(current_asmdata.RefAsmSymbol('FPC_EMPTYINTF',AT_DATA),ptruinttype);
-              end;
+              tcb.emit_tai(Tai_const.Create_nil_dataptr,pinterfacetabledef);
             { table for string messages }
             pstringmessagetabledef:=search_system_type('PSTRINGMESSAGETABLE').typedef;
             if (oo_has_msgstr in _class.objectoptions) then

+ 12 - 4
rtl/inc/objpas.inc

@@ -294,8 +294,10 @@
            InstanceSize := PVmt(Self)^.vInstanceSize;
         end;
 
+      {$ifdef VER3_0}
       var
         emptyintf: ptruint; public name 'FPC_EMPTYINTF';
+      {$endif VER3_0}
 
       procedure InitInterfacePointers(objclass: tclass;instance : pointer);
 
@@ -306,10 +308,12 @@
           Res: pinterfaceentry;
         begin
           ovmt := PVmt(objclass);
-          while assigned(ovmt) and (ovmt^.vIntfTable <> @emptyintf) do
+          while assigned(ovmt) and {$ifdef VER3_0}(ovmt^.vIntfTable <> @emptyintf){$else}assigned(ovmt^.vIntfTable){$endif} do
             begin
               intftable:=ovmt^.vIntfTable;
+              {$ifdef VER3_0}
               if assigned(intftable) then
+              {$endif VER3_0}
               begin
                 i:=intftable^.EntryCount;
                 Res:=@intftable^.Entries[0];
@@ -333,7 +337,7 @@
            { insert VMT pointer into the new created memory area }
            { (in class methods self contains the VMT!)           }
            ppointer(instance)^:=pointer(self);
-           if PVmt(self)^.vIntfTable <> @emptyintf then
+           if {$ifdef VER3_0}PVmt(self)^.vIntfTable <> @emptyintf{$else}assigned(PVmt(self)^.vIntfTable){$endif} then
              InitInterfacePointers(self,instance);
            InitInstance:=TObject(Instance);
         end;
@@ -844,10 +848,12 @@
           ovmt: PVmt;
         begin
           ovmt := PVmt(Self);
-          while Assigned(ovmt) and (ovmt^.vIntfTable <> @emptyintf) do
+          while Assigned(ovmt) and {$ifdef VER3_0}(ovmt^.vIntfTable <> @emptyintf){$else}Assigned(ovmt^.vIntftable){$endif} do
           begin
             intftable:=ovmt^.vIntfTable;
+            {$ifdef VER3_0}
             if assigned(intftable) then
+            {$endif VER3_0}
             begin
               for i:=0 to intftable^.EntryCount-1 do
               begin
@@ -868,10 +874,12 @@
           ovmt: PVmt;
         begin
           ovmt := PVmt(Self);
-          while Assigned(ovmt) and (ovmt^.vIntfTable <> @emptyintf) do
+          while Assigned(ovmt) and {$ifdef VER3_0}(ovmt^.vIntfTable <> @emptyintf){$else}Assigned(ovmt^.vIntfTable){$endif} do
           begin
             intftable:=ovmt^.vIntfTable;
+            {$ifdef VER3_0}
             if assigned(intftable) then
+            {$endif VER3_0}
             begin
               for i:=0 to intftable^.EntryCount-1 do
               begin