From 9ae8e9fa218badeafea9ec2b39b1cc06c36ecaa8 Mon Sep 17 00:00:00 2001
From: peter <peter@freepascal.org>
Date: Mon, 13 Nov 2006 22:03:17 +0000
Subject: [PATCH]   * refactor tclassheader in tvmtbuilder and tvmtwriter   *
 fix rtti generation   * rtti is now written at the end of a module when all
 info is available,     this prevents some duplicate rtti entries cause by
 inheritance

git-svn-id: trunk@5363 -
---
 compiler/dbgdwarf.pas     |    6 +-
 compiler/ncgrtti.pas      |   31 +-
 compiler/nobj.pas         | 1907 ++++++++++++++++++-------------------
 compiler/pdecl.pas        |   31 +-
 compiler/pdecobj.pas      |    4 +-
 compiler/pmodules.pas     |   31 +-
 compiler/psystem.pas      |    3 -
 compiler/ptype.pas        |   93 +-
 compiler/symconst.pas     |   20 +-
 compiler/symdef.pas       |   26 +-
 compiler/symtype.pas      |    7 +-
 compiler/utils/ppudump.pp |   41 +-
 12 files changed, 1127 insertions(+), 1073 deletions(-)

diff --git a/compiler/dbgdwarf.pas b/compiler/dbgdwarf.pas
index cb77d35f62..826d2a18b0 100644
--- a/compiler/dbgdwarf.pas
+++ b/compiler/dbgdwarf.pas
@@ -612,7 +612,7 @@ implementation
         { Need a new label? }
         if not assigned(def.dwarf_lab) then
           begin
-            if (df_has_dwarf_dbg_info in def.defoptions) then
+            if (ds_dwarf_dbg_info_written in def.defstates) then
               begin
                 if not assigned(def.typesym) then
                   internalerror(200610011);
@@ -628,7 +628,7 @@ implementation
                    (def.owner.iscurrentunit) then
                   begin
                     def.dwarf_lab:=current_asmdata.DefineAsmSymbol(make_mangledname('DBG',def.owner,symname(def.typesym)),AB_GLOBAL,AT_DATA);
-                    include(def.defoptions,df_has_dwarf_dbg_info);
+                    include(def.defstates,ds_dwarf_dbg_info_written);
                   end
                 else
                   { The pointer typecast is needed to prevent a problem with range checking
@@ -1388,7 +1388,7 @@ implementation
 
         current_asmdata.asmlists[al_dwarf_info].concat(tai_comment.Create(strpnew('Definition '+def.typename)));
         labsym:=def_dwarf_lab(def);
-        if df_has_dwarf_dbg_info in def.defoptions then
+        if ds_dwarf_dbg_info_written in def.defstates then
           current_asmdata.asmlists[al_dwarf_info].concat(tai_symbol.create_global(labsym,0))
         else
           current_asmdata.asmlists[al_dwarf_info].concat(tai_symbol.create(labsym,0));
diff --git a/compiler/ncgrtti.pas b/compiler/ncgrtti.pas
index 6d967439b0..d08f24f3d3 100644
--- a/compiler/ncgrtti.pas
+++ b/compiler/ncgrtti.pas
@@ -68,7 +68,7 @@ implementation
 
 
     const
-       rttidefopt : array[trttitype] of tdefoption = (df_has_rttitable,df_has_inittable);
+       rttidefstate : array[trttitype] of tdefstate = (ds_rtti_table_written,ds_init_table_written);
 
     type
        TPropNameListItem = class(TFPHashObject)
@@ -831,18 +831,20 @@ implementation
           recorddef :
             fields_write_rtti(trecorddef(def).symtable,rt);
           objectdef :
-            if rt=initrtti then
-              fields_write_rtti(tobjectdef(def).symtable,rt)
-            else
-              published_write_rtti(tobjectdef(def).symtable,rt);
+            begin
+              if assigned(tobjectdef(def).childof) then
+                write_rtti(tobjectdef(def).childof,rt);
+              if rt=initrtti then
+                fields_write_rtti(tobjectdef(def).symtable,rt)
+              else
+                published_write_rtti(tobjectdef(def).symtable,rt);
+            end;
         end;
       end;
 
 
     function TRTTIWriter.ref_rtti(def:tdef;rt:trttitype):tasmsymbol;
       begin
-        if not(rttidefopt[rt] in def.defoptions) then
-          internalerror(200611037);
         result:=current_asmdata.RefAsmSymbol(def.rtti_mangledname(rt));
       end;
 
@@ -851,14 +853,13 @@ implementation
       var
         rttilab : tasmsymbol;
       begin
-        if rttidefopt[rt] in def.defoptions then
-          exit;
-        { only write the rttis of defs defined in the current unit,
-          otherwise we will generate duplicate asmsymbols }
+        { only write rtti of definitions from the current module }
         if not findunitsymtable(def.owner).iscurrentunit then
-          internalerror(200611035);
+          exit;
         { prevent recursion }
-        include(def.defoptions,rttidefopt[rt]);
+        if rttidefstate[rt] in def.defstates then
+          exit;
+        include(def.defstates,rttidefstate[rt]);
         { write first all dependencies }
         write_child_rtti_data(def,rt);
         { write rtti data }
@@ -873,9 +874,7 @@ implementation
 
     function TRTTIWriter.get_rtti_label(def:tdef;rt:trttitype):tasmsymbol;
       begin
-        if not(rttidefopt[rt] in def.defoptions) then
-          write_rtti(def,rt);
-        result:=ref_rtti(def,rt);
+        result:=current_asmdata.RefAsmSymbol(def.rtti_mangledname(rt));
       end;
 
 end.
diff --git a/compiler/nobj.pas b/compiler/nobj.pas
index 4f658ad917..7129d12d2c 100644
--- a/compiler/nobj.pas
+++ b/compiler/nobj.pas
@@ -33,6 +33,42 @@ interface
        aasmbase,aasmtai,aasmdata
        ;
 
+    type
+      pprocdefentry = ^tprocdefentry;
+      tprocdefentry = record
+         data    : tprocdef;
+         hidden  : boolean;
+         visible : boolean;
+      end;
+
+      { tvmtsymentry }
+
+      tvmtsymentry = class(TFPHashObject)
+        procdeflist : TFPList;
+        constructor Create(AList:TFPHashObjectList;const AName:shortstring);
+        destructor Destroy;override;
+      end;
+
+      TVMTBuilder=class
+      private
+        _Class : tobjectdef;
+        VMTSymEntryList : TFPHashObjectList;
+        has_constructor,
+        has_virtual_method : boolean;
+        function is_new_vmt_entry(VMTSymEntry:TVMTSymEntry;pd:tprocdef):boolean;
+        procedure add_new_vmt_entry(VMTSymEntry:TVMTSymEntry;pd:tprocdef);
+        procedure add_vmt_entries(objdef:tobjectdef);
+        function  intf_search_procdef_by_name(proc: tprocdef;const name: string): tprocdef;
+        procedure intf_get_procdefs(ImplIntf:TImplementedInterface;IntfDef:TObjectDef);
+        procedure intf_get_procdefs_recursive(ImplIntf:TImplementedInterface;IntfDef:TObjectDef);
+        procedure intf_optimize_vtbls;
+        procedure intf_allocate_vtbls;
+      public
+        constructor create(c:tobjectdef);
+        destructor  destroy;override;
+        procedure generate_vmt;
+      end;
+
     type
       pprocdeftree = ^tprocdeftree;
       tprocdeftree = record
@@ -41,26 +77,9 @@ interface
          l,r  : pprocdeftree;
       end;
 
-      pprocdefcoll = ^tprocdefcoll;
-      tprocdefcoll = record
-         data    : tprocdef;
-         hidden  : boolean;
-         visible : boolean;
-         next    : pprocdefcoll;
-      end;
-
-      pvmtentry = ^tvmtentry;
-      tvmtentry = record
-         hash         : longword;
-         name         : pshortstring;
-         firstprocdef : pprocdefcoll;
-         next         : pvmtentry;
-      end;
-
-      tclassheader=class
+      TVMTWriter=class
       private
         _Class : tobjectdef;
-      private
         { message tables }
         root : pprocdeftree;
         procedure disposeprocdeftree(p : pprocdeftree);
@@ -72,59 +91,38 @@ interface
         procedure writeintentry(p : pprocdeftree);
         procedure writestrentry(p : pprocdeftree);
 {$ifdef WITHDMT}
-      private
         { dmt }
         procedure insertdmtentry(p:TObject;arg:pointer);
         procedure writedmtindexentry(p : pprocdeftree);
         procedure writedmtaddressentry(p : pprocdeftree);
 {$endif}
-      private
         { published methods }
         procedure do_count_published_methods(p:TObject;arg:pointer);
         procedure do_gen_published_methods(p:TObject;arg:pointer);
-      private
-        { vmt }
-        firstvmtentry      : pvmtentry;
-        nextvirtnumber     : integer;
-        has_constructor,
-        has_virtual_method : boolean;
-        procedure newdefentry(vmtentry:pvmtentry;pd:tprocdef;is_visible:boolean);
-        function  newvmtentry(sym:tprocsym):pvmtentry;
-        procedure eachsym(sym : TObject;arg:pointer);
-        procedure disposevmttree;
+        { virtual methods }
         procedure writevirtualmethods(List:TAsmList);
-      private
         { interface tables }
         function  intf_get_vtbl_name(AImplIntf:TImplementedInterface): string;
         procedure intf_create_vtbl(rawdata: TAsmList;AImplIntf:TImplementedInterface);
         procedure intf_gen_intf_ref(rawdata: TAsmList;AImplIntf:TImplementedInterface);
-        procedure intf_optimize_vtbls;
-        procedure intf_write_data;
-        function  intf_search_procdef_by_name(proc: tprocdef;const name: string): tprocdef;
-        procedure intf_get_procdefs(ImplIntf:TImplementedInterface;IntfDef:TObjectDef);
-        procedure intf_get_procdefs_recursive(ImplIntf:TImplementedInterface;IntfDef:TObjectDef);
-      public
-        constructor create(c:tobjectdef);
-        destructor destroy;override;
+        function  intf_write_table:TAsmLabel;
         { generates the message tables for a class }
         function  genstrmsgtab : tasmlabel;
         function  genintmsgtab : tasmlabel;
         function  genpublishedmethodstable : tasmlabel;
         function  generate_field_table : tasmlabel;
-        { generates a VMT entries }
-        procedure genvmt;
 {$ifdef WITHDMT}
         { generates a DMT for _class }
         function  gendmt : tasmlabel;
 {$endif WITHDMT}
-        { interfaces }
-        function  genintftable: tasmlabel;
+      public
+        constructor create(c:tobjectdef);
+        destructor destroy;override;
         { write the VMT to al_globals }
         procedure writevmt;
         procedure writeinterfaceids;
       end;
 
-
 implementation
 
     uses
@@ -137,465 +135,50 @@ implementation
 
 
 {*****************************************************************************
-                                TClassHeader
+                              TVMTSymEntry
 *****************************************************************************}
 
-    constructor tclassheader.create(c:tobjectdef);
+    constructor tvmtsymentry.Create(AList:TFPHashObjectList;const AName:shortstring);
+      begin
+        inherited Create(AList,AName);
+        procdeflist:=TFPList.Create;
+      end;
+
+
+    destructor TVMTSymEntry.Destroy;
+      var
+        i : longint;
+      begin
+        for i:=0 to procdeflist.Count-1 do
+          Dispose(pprocdefentry(procdeflist[i]));
+        procdeflist.free;
+        inherited Destroy;
+      end;
+
+
+{*****************************************************************************
+                              TVMTBuilder
+*****************************************************************************}
+
+    constructor TVMTBuilder.create(c:tobjectdef);
       begin
         inherited Create;
         _Class:=c;
+        VMTSymEntryList:=TFPHashObjectList.Create;
       end;
 
 
-    destructor tclassheader.destroy;
+    destructor TVMTBuilder.destroy;
       begin
-        disposevmttree;
+        VMTSymEntryList.free;
       end;
 
 
-{**************************************
-           Message Tables
-**************************************}
-
-    procedure tclassheader.disposeprocdeftree(p : pprocdeftree);
-      begin
-         if assigned(p^.l) then
-           disposeprocdeftree(p^.l);
-         if assigned(p^.r) then
-           disposeprocdeftree(p^.r);
-         dispose(p);
-      end;
-
-
-    procedure tclassheader.insertint(p : pprocdeftree;var at : pprocdeftree;var count:longint);
-
-      begin
-         if at=nil then
-           begin
-              at:=p;
-              inc(count);
-           end
-         else
-           begin
-              if p^.data.messageinf.i<at^.data.messageinf.i then
-                insertint(p,at^.l,count)
-              else if p^.data.messageinf.i>at^.data.messageinf.i then
-                insertint(p,at^.r,count)
-              else
-                Message1(parser_e_duplicate_message_label,tostr(p^.data.messageinf.i));
-           end;
-      end;
-
-    procedure tclassheader.insertstr(p : pprocdeftree;var at : pprocdeftree;var count:longint);
-
+    procedure TVMTBuilder.add_new_vmt_entry(VMTSymEntry:TVMTSymEntry;pd:tprocdef);
       var
-         i : integer;
-
-      begin
-         if at=nil then
-           begin
-              at:=p;
-              inc(count);
-           end
-         else
-           begin
-              i:=CompareStr(p^.data.messageinf.str^,at^.data.messageinf.str^);
-              if i<0 then
-                insertstr(p,at^.l,count)
-              else if i>0 then
-                insertstr(p,at^.r,count)
-              else
-                Message1(parser_e_duplicate_message_label,p^.data.messageinf.str^);
-           end;
-      end;
-
-
-    procedure tclassheader.insertmsgint(p:TObject;arg:pointer);
-      var
-        i  : longint;
-        pd : Tprocdef;
-        pt : pprocdeftree;
-      begin
-        if tsym(p).typ<>procsym then
-          exit;
-        for i:=0 to Tprocsym(p).ProcdefList.Count-1 do
-          begin
-            pd:=tprocdef(Tprocsym(p).ProcdefList[i]);
-            if po_msgint in pd.procoptions then
-              begin
-                new(pt);
-                pt^.data:=pd;
-                pt^.l:=nil;
-                pt^.r:=nil;
-                insertint(pt,root,plongint(arg)^);
-              end;
-          end;
-      end;
-
-
-    procedure tclassheader.insertmsgstr(p:TObject;arg:pointer);
-      var
-        i  : longint;
-        pd : Tprocdef;
-        pt : pprocdeftree;
-      begin
-        if tsym(p).typ<>procsym then
-          exit;
-        for i:=0 to Tprocsym(p).ProcdefList.Count-1 do
-          begin
-            pd:=tprocdef(Tprocsym(p).ProcdefList[i]);
-            if po_msgstr in pd.procoptions then
-              begin
-                new(pt);
-                pt^.data:=pd;
-                pt^.l:=nil;
-                pt^.r:=nil;
-                insertstr(pt,root,plongint(arg)^);
-              end;
-          end;
-      end;
-
-
-    procedure tclassheader.writenames(p : pprocdeftree);
-      var
-        ca : pchar;
-        len : byte;
-      begin
-         current_asmdata.getdatalabel(p^.nl);
-         if assigned(p^.l) then
-           writenames(p^.l);
-         current_asmdata.asmlists[al_globals].concat(cai_align.create(const_align(sizeof(aint))));
-         current_asmdata.asmlists[al_globals].concat(Tai_label.Create(p^.nl));
-         len:=length(p^.data.messageinf.str^);
-         current_asmdata.asmlists[al_globals].concat(tai_const.create_8bit(len));
-         getmem(ca,len+1);
-         move(p^.data.messageinf.str[1],ca^,len);
-         ca[len]:=#0;
-         current_asmdata.asmlists[al_globals].concat(Tai_string.Create_pchar(ca,len));
-         if assigned(p^.r) then
-           writenames(p^.r);
-      end;
-
-    procedure tclassheader.writestrentry(p : pprocdeftree);
-
-      begin
-         if assigned(p^.l) then
-           writestrentry(p^.l);
-
-         { write name label }
-         current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(p^.nl));
-         current_asmdata.asmlists[al_globals].concat(Tai_const.Createname(p^.data.mangledname,0));
-
-         if assigned(p^.r) then
-           writestrentry(p^.r);
-     end;
-
-
-    function tclassheader.genstrmsgtab : tasmlabel;
-      var
-         count : aint;
-      begin
-         root:=nil;
-         count:=0;
-         { insert all message handlers into a tree, sorted by name }
-         _class.symtable.SymList.ForEachCall(@insertmsgstr,@count);
-
-         { write all names }
-         if assigned(root) then
-           writenames(root);
-
-         { now start writing of the message string table }
-         current_asmdata.getdatalabel(result);
-         current_asmdata.asmlists[al_globals].concat(cai_align.create(const_align(sizeof(aint))));
-         current_asmdata.asmlists[al_globals].concat(Tai_label.Create(result));
-         current_asmdata.asmlists[al_globals].concat(Tai_const.Create_aint(count));
-         if assigned(root) then
-           begin
-              writestrentry(root);
-              disposeprocdeftree(root);
-           end;
-      end;
-
-
-    procedure tclassheader.writeintentry(p : pprocdeftree);
-      begin
-         if assigned(p^.l) then
-           writeintentry(p^.l);
-
-         { write name label }
-         current_asmdata.asmlists[al_globals].concat(Tai_const.Create_32bit(p^.data.messageinf.i));
-         current_asmdata.asmlists[al_globals].concat(Tai_const.Createname(p^.data.mangledname,0));
-
-         if assigned(p^.r) then
-           writeintentry(p^.r);
-      end;
-
-
-    function tclassheader.genintmsgtab : tasmlabel;
-      var
-         r : tasmlabel;
-         count : longint;
-      begin
-         root:=nil;
-         count:=0;
-         { insert all message handlers into a tree, sorted by name }
-         _class.symtable.SymList.ForEachCall(@insertmsgint,@count);
-
-         { now start writing of the message string table }
-         current_asmdata.getdatalabel(r);
-         current_asmdata.asmlists[al_globals].concat(cai_align.create(const_align(sizeof(aint))));
-         current_asmdata.asmlists[al_globals].concat(Tai_label.Create(r));
-         genintmsgtab:=r;
-         current_asmdata.asmlists[al_globals].concat(Tai_const.Create_32bit(count));
-         if assigned(root) then
-           begin
-              writeintentry(root);
-              disposeprocdeftree(root);
-           end;
-      end;
-
-{$ifdef WITHDMT}
-
-{**************************************
-              DMT
-**************************************}
-
-    procedure tclassheader.insertdmtentry(p:TObject;arg:pointer);
-
-      var
-         hp : tprocdef;
-         pt : pprocdeftree;
-
-      begin
-         if tsym(p).typ=procsym then
-           begin
-              hp:=tprocsym(p).definition;
-              while assigned(hp) do
-                begin
-                   if (po_msgint in hp.procoptions) then
-                     begin
-                        new(pt);
-                        pt^.p:=hp;
-                        pt^.l:=nil;
-                        pt^.r:=nil;
-                        insertint(pt,root);
-                     end;
-                   hp:=hp.nextoverloaded;
-                end;
-           end;
-      end;
-
-    procedure tclassheader.writedmtindexentry(p : pprocdeftree);
-
-      begin
-         if assigned(p^.l) then
-           writedmtindexentry(p^.l);
-         al_globals.concat(Tai_const.Create_32bit(p^.data.messageinf.i));
-         if assigned(p^.r) then
-           writedmtindexentry(p^.r);
-      end;
-
-    procedure tclassheader.writedmtaddressentry(p : pprocdeftree);
-
-      begin
-         if assigned(p^.l) then
-           writedmtaddressentry(p^.l);
-         al_globals.concat(Tai_const_symbol.Createname(p^.data.mangledname,0));
-         if assigned(p^.r) then
-           writedmtaddressentry(p^.r);
-      end;
-
-    function tclassheader.gendmt : tasmlabel;
-
-      var
-         r : tasmlabel;
-
-      begin
-         root:=nil;
-         count:=0;
-         gendmt:=nil;
-         { insert all message handlers into a tree, sorted by number }
-         _class.symtable.SymList.ForEachCall(insertdmtentry);
-
-         if count>0 then
-           begin
-              current_asmdata.getdatalabel(r);
-              gendmt:=r;
-              al_globals.concat(cai_align.create(const_align(sizeof(aint))));
-              al_globals.concat(Tai_label.Create(r));
-              { entries for caching }
-              al_globals.concat(Tai_const.Create_ptr(0));
-              al_globals.concat(Tai_const.Create_ptr(0));
-
-              al_globals.concat(Tai_const.Create_32bit(count));
-              if assigned(root) then
-                begin
-                   writedmtindexentry(root);
-                   writedmtaddressentry(root);
-                   disposeprocdeftree(root);
-                end;
-           end;
-      end;
-
-{$endif WITHDMT}
-
-{**************************************
-        Published Methods
-**************************************}
-
-    procedure tclassheader.do_count_published_methods(p:TObject;arg:pointer);
-      var
-        i  : longint;
-        pd : tprocdef;
-      begin
-        if (tsym(p).typ<>procsym) then
-          exit;
-        for i:=0 to Tprocsym(p).ProcdefList.Count-1 do
-          begin
-            pd:=tprocdef(Tprocsym(p).ProcdefList[i]);
-            if (pd.procsym=tsym(p)) and
-               (sp_published in pd.symoptions) then
-              inc(plongint(arg)^);
-          end;
-      end;
-
-
-    procedure tclassheader.do_gen_published_methods(p:TObject;arg:pointer);
-      var
-        i  : longint;
-        l  : tasmlabel;
-        pd : tprocdef;
-      begin
-        if (tsym(p).typ<>procsym) then
-          exit;
-        for i:=0 to Tprocsym(p).ProcdefList.Count-1 do
-          begin
-            pd:=tprocdef(Tprocsym(p).ProcdefList[i]);
-            if (pd.procsym=tsym(p)) and
-               (sp_published in pd.symoptions) then
-              begin
-                current_asmdata.getdatalabel(l);
-
-                current_asmdata.asmlists[al_typedconsts].concat(cai_align.create(const_align(sizeof(aint))));
-                current_asmdata.asmlists[al_typedconsts].concat(Tai_label.Create(l));
-                current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_8bit(length(tsym(p).realname)));
-                current_asmdata.asmlists[al_typedconsts].concat(Tai_string.Create(tsym(p).realname));
-
-                current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(l));
-                if po_abstractmethod in pd.procoptions then
-                  current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(nil))
-                else
-                  current_asmdata.asmlists[al_globals].concat(Tai_const.Createname(pd.mangledname,0));
-              end;
-           end;
-      end;
-
-
-    function tclassheader.genpublishedmethodstable : tasmlabel;
-
-      var
-         l : tasmlabel;
-         count : longint;
-
-      begin
-         count:=0;
-         _class.symtable.SymList.ForEachCall(@do_count_published_methods,@count);
-         if count>0 then
-           begin
-              current_asmdata.getdatalabel(l);
-              current_asmdata.asmlists[al_globals].concat(cai_align.create(const_align(sizeof(aint))));
-              current_asmdata.asmlists[al_globals].concat(Tai_label.Create(l));
-              current_asmdata.asmlists[al_globals].concat(Tai_const.Create_32bit(count));
-              _class.symtable.SymList.ForEachCall(@do_gen_published_methods,nil);
-              genpublishedmethodstable:=l;
-           end
-         else
-           genpublishedmethodstable:=nil;
-      end;
-
-
-    function tclassheader.generate_field_table : tasmlabel;
-      var
-        i   : longint;
-        sym : tsym;
-        fieldtable,
-        classtable : tasmlabel;
-        classindex,
-        fieldcount : longint;
-        classtablelist : TFPList;
-      begin
-        classtablelist:=TFPList.Create;
-        current_asmdata.getdatalabel(fieldtable);
-        current_asmdata.getdatalabel(classtable);
-        maybe_new_object_file(current_asmdata.asmlists[al_rtti]);
-        new_section(current_asmdata.asmlists[al_rtti],sec_rodata,classtable.name,const_align(sizeof(aint)));
-
-        { retrieve field info fields }
-        fieldcount:=0;
-        for i:=0 to _class.symtable.SymList.Count-1 do
-          begin
-            sym:=tsym(_class.symtable.SymList[i]);
-            if (tsym(sym).typ=fieldvarsym) and
-               (sp_published in tsym(sym).symoptions) then
-             begin
-                if tfieldvarsym(sym).vardef.typ<>objectdef then
-                  internalerror(200611032);
-                classindex:=classtablelist.IndexOf(tfieldvarsym(sym).vardef);
-                if classindex=-1 then
-                  classtablelist.Add(tfieldvarsym(sym).vardef);
-                inc(fieldcount);
-             end;
-          end;
-
-        { write fields }
-        current_asmdata.asmlists[al_rtti].concat(Tai_label.Create(fieldtable));
-        current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_16bit(fieldcount));
-{$ifdef cpurequiresproperalignment}
-        current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
-{$endif cpurequiresproperalignment}
-        current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_sym(classtable));
-        for i:=0 to _class.symtable.SymList.Count-1 do
-          begin
-            sym:=tsym(_class.symtable.SymList[i]);
-            if (tsym(sym).typ=fieldvarsym) and
-               (sp_published in tsym(sym).symoptions) then
-              begin
-{$ifdef cpurequiresproperalignment}
-                current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(AInt)));
-{$endif cpurequiresproperalignment}
-                current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_aint(tfieldvarsym(sym).fieldoffset));
-                classindex:=classtablelist.IndexOf(tfieldvarsym(sym).vardef);
-                if classindex=-1 then
-                  internalerror(200611033);
-                current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_16bit(classindex+1));
-                current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(length(tfieldvarsym(sym).realname)));
-                current_asmdata.asmlists[al_rtti].concat(Tai_string.Create(tfieldvarsym(sym).realname));
-              end;
-          end;
-
-        { generate the class table }
-        current_asmdata.asmlists[al_rtti].concat(cai_align.create(const_align(sizeof(aint))));
-        current_asmdata.asmlists[al_rtti].concat(Tai_label.Create(classtable));
-        current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_16bit(classtablelist.count));
-{$ifdef cpurequiresproperalignment}
-        current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
-{$endif cpurequiresproperalignment}
-        for i:=0 to classtablelist.Count-1 do
-          current_asmdata.asmlists[al_rtti].concat(Tai_const.Createname(tobjectdef(classtablelist[i]).vmt_mangledname,0));
-
-        classtablelist.free;
-        result:=fieldtable;
-      end;
-
-
-{**************************************
-               VMT
-**************************************}
-
-
-    procedure tclassheader.newdefentry(vmtentry:pvmtentry;pd:tprocdef;is_visible:boolean);
-      var
-        procdefcoll : pprocdefcoll;
+        procdefcoll : pprocdefentry;
+        i : longint;
+        oldpd : tprocdef;
       begin
         if (_class=pd._class) then
           begin
@@ -606,18 +189,17 @@ implementation
             { check that all methods have overload directive }
             if not(m_fpc in current_settings.modeswitches) then
               begin
-                procdefcoll:=vmtentry^.firstprocdef;
-                while assigned(procdefcoll) do
+                for i:=0 to VMTSymentry.ProcdefList.Count-1 do
                   begin
-                    if (procdefcoll^.data._class=pd._class) and
-                       ((po_overload in pd.procoptions)<>(po_overload in procdefcoll^.data.procoptions)) then
+                    oldpd:=pprocdefentry(VMTSymentry.ProcdefList[i])^.data;
+                    if (oldpd._class=pd._class) and
+                       ((po_overload in pd.procoptions)<>(po_overload in oldpd.procoptions)) then
                       begin
                         MessagePos1(pd.fileinfo,parser_e_no_overload_for_all_procs,pd.procsym.realname);
                         { recover }
-                        include(procdefcoll^.data.procoptions,po_overload);
+                        include(oldpd.procoptions,po_overload);
                         include(pd.procoptions,po_overload);
                       end;
-                    procdefcoll:=procdefcoll^.next;
                   end;
               end;
           end;
@@ -626,15 +208,22 @@ implementation
         new(procdefcoll);
         procdefcoll^.data:=pd;
         procdefcoll^.hidden:=false;
-        procdefcoll^.visible:=is_visible;
-        procdefcoll^.next:=vmtentry^.firstprocdef;
-        vmtentry^.firstprocdef:=procdefcoll;
+        procdefcoll^.visible:=pd.is_visible_for_object(_class,nil);
+        VMTSymEntry.ProcdefList.Add(procdefcoll);
 
-        { give virtual method a number }
+        { Register virtual method and give it a number }
         if (po_virtualmethod in pd.procoptions) then
           begin
-             pd.extnumber:=nextvirtnumber;
-             inc(nextvirtnumber);
+             if not assigned(_class.VMTEntries) then
+               _class.VMTEntries:=TFPObjectList.Create(false);
+             if pd.extnumber=$ffff then
+               pd.extnumber:=_class.VMTEntries.Count
+             else
+               begin
+                 if pd.extnumber<>_class.VMTEntries.Count then
+                   internalerror(200611081);
+               end;
+             _class.VMTEntries.Add(pd);
              has_virtual_method:=true;
           end;
 
@@ -643,375 +232,306 @@ implementation
       end;
 
 
-    function tclassheader.newvmtentry(sym:tprocsym):pvmtentry;
-      begin
-        { generate new vmtentry }
-        new(result);
-        result^.Hash:=sym.Hash;
-        result^.name:=stringdup(sym.name);
-        result^.next:=firstvmtentry;
-        result^.firstprocdef:=nil;
-        firstvmtentry:=result;
-      end;
-
-
-    procedure tclassheader.eachsym(sym : TObject;arg:pointer);
+    function TVMTBuilder.is_new_vmt_entry(VMTSymEntry:TVMTSymEntry;pd:tprocdef):boolean;
       const
         po_comp = [po_classmethod,po_virtualmethod,po_staticmethod,po_interrupt,po_iocheck,po_msgstr,po_msgint,
                    po_exports,po_varargs,po_explicitparaloc,po_nostackframe];
-      label
-         handlenextdef;
       var
-         pd : tprocdef;
-         i : cardinal;
-         is_visible,
-         hasoverloads,
-         pdoverload : boolean;
-         procdefcoll : pprocdefcoll;
-         vmtentry : pvmtentry;
-         _name : string;
-         _speed : cardinal;
+        i : longint;
+        is_visible,
+        hasoverloads,
+        pdoverload : boolean;
+        procdefcoll : pprocdefentry;
       begin
-        if (tsym(sym).typ<>procsym) then
-          exit;
+        result:=false;
+        { is this procdef visible from the class that we are
+          generating. This will be used to hide the other procdefs.
+          When the symbol is not visible we don't hide the other
+          procdefs, because they can be reused in the next class.
+          The check to skip the invisible methods that are in the
+          list is futher down in the code }
+        is_visible:=pd.is_visible_for_object(_class,nil);
+        { Load other values for easier readability }
+        hasoverloads:=(tprocsym(pd.procsym).ProcdefList.Count>1);
+        pdoverload:=(po_overload in pd.procoptions);
 
-        { check the current list of symbols }
-        _name:=TSym(sym).name;
-        _speed:=TSym(sym).Hash;
-        vmtentry:=firstvmtentry;
-        while assigned(vmtentry) do
-         begin
-           { does the symbol already exist in the list? First
-             compare speedvalue before doing the string compare to
-             speed it up a little }
-           if (_speed=vmtentry^.Hash) and
-              (_name=vmtentry^.name^) then
-            begin
-              hasoverloads:=(Tprocsym(sym).ProcdefList.Count>1);
-              { walk through all defs of the symbol }
-              for i:=0 to Tprocsym(sym).ProcdefList.Count-1 do
-               begin
-                 pd:=tprocdef(Tprocsym(sym).ProcdefList[i]);
+        { compare with all stored definitions }
+        for i:=0 to VMTSymEntry.ProcdefList.Count-1 do
+          begin
+            procdefcoll:=pprocdefentry(VMTSymEntry.ProcdefList[i]);
+            { skip definitions that are already hidden }
+            if procdefcoll^.hidden then
+              continue;
 
-                 { is this procdef visible from the class that we are
-                   generating. This will be used to hide the other procdefs.
-                   When the symbol is not visible we don't hide the other
-                   procdefs, because they can be reused in the next class.
-                   The check to skip the invisible methods that are in the
-                   list is futher down in the code }
-                 is_visible:=pd.is_visible_for_object(_class,nil);
-
-                 if pd.procsym=sym then
+            { check if one of the two methods has virtual }
+            if (po_virtualmethod in procdefcoll^.data.procoptions) or
+               (po_virtualmethod in pd.procoptions) then
+              begin
+                { if the current definition has no virtual then hide the
+                  old virtual if the new definition has the same arguments or
+                  when it has no overload directive and no overloads }
+                if not(po_virtualmethod in pd.procoptions) then
                   begin
-                    pdoverload:=(po_overload in pd.procoptions);
-
-                    { compare with all stored definitions }
-                    procdefcoll:=vmtentry^.firstprocdef;
-                    while assigned(procdefcoll) do
+                    if procdefcoll^.visible and
+                       (
+                        not(pdoverload or hasoverloads) or
+                        (compare_paras(procdefcoll^.data.paras,pd.paras,cp_all,[])>=te_equal)
+                       ) then
                       begin
-                         { compare only if the definition is not hidden }
-                         if not procdefcoll^.hidden then
-                          begin
-                            { check if one of the two methods has virtual }
-                            if (po_virtualmethod in procdefcoll^.data.procoptions) or
-                               (po_virtualmethod in pd.procoptions) then
-                             begin
-                               { if the current definition has no virtual then hide the
-                                 old virtual if the new definition has the same arguments or
-                                 when it has no overload directive and no overloads }
-                               if not(po_virtualmethod in pd.procoptions) then
-                                begin
-                                  if procdefcoll^.visible and
-                                     (not(pdoverload or hasoverloads) or
-                                      (compare_paras(procdefcoll^.data.paras,pd.paras,cp_all,[])>=te_equal)) then
-                                   begin
-                                     if is_visible then
-                                       procdefcoll^.hidden:=true;
-                                     if (_class=pd._class) and not(po_reintroduce in pd.procoptions) then
-                                       MessagePos1(pd.fileinfo,parser_w_should_use_override,pd.fullprocname(false));
-                                   end;
-                                end
-                               { if both are virtual we check the header }
-                               else if (po_virtualmethod in pd.procoptions) and
-                                       (po_virtualmethod in procdefcoll^.data.procoptions) then
-                                begin
-                                  { new one has not override }
-                                  if is_class(_class) and
-                                     not(po_overridingmethod in pd.procoptions) then
-                                   begin
-                                     { we start a new virtual tree, hide the old }
-                                     if (not(pdoverload or hasoverloads) or
-                                         (compare_paras(procdefcoll^.data.paras,pd.paras,cp_all,[])>=te_equal)) and
-                                        (procdefcoll^.visible) then
-                                      begin
-                                        if is_visible then
-                                          procdefcoll^.hidden:=true;
-                                        if (_class=pd._class) and not(po_reintroduce in pd.procoptions) then
-                                          MessagePos1(pd.fileinfo,parser_w_should_use_override,pd.fullprocname(false));
-                                      end;
-                                   end
-                                  { same parameters }
-                                  else if (compare_paras(procdefcoll^.data.paras,pd.paras,cp_all,[])>=te_equal) then
-                                   begin
-                                     { overload is inherited }
-                                     if (po_overload in procdefcoll^.data.procoptions) then
-                                      include(pd.procoptions,po_overload);
-
-                                     { inherite calling convention when it was force and the
-                                       current definition has none force }
-                                     if (po_hascallingconvention in procdefcoll^.data.procoptions) and
-                                        not(po_hascallingconvention in pd.procoptions) then
-                                       begin
-                                         pd.proccalloption:=procdefcoll^.data.proccalloption;
-                                         include(pd.procoptions,po_hascallingconvention);
-                                       end;
-
-                                     { the flags have to match except abstract and override }
-                                     { only if both are virtual !!  }
-                                     if (procdefcoll^.data.proccalloption<>pd.proccalloption) or
-                                        (procdefcoll^.data.proctypeoption<>pd.proctypeoption) or
-                                        ((procdefcoll^.data.procoptions*po_comp)<>(pd.procoptions*po_comp)) then
-                                        begin
-                                          MessagePos1(pd.fileinfo,parser_e_header_dont_match_forward,pd.fullprocname(false));
-                                          tprocsym(procdefcoll^.data.procsym).write_parameter_lists(pd);
-                                        end;
-
-                                     { error, if the return types aren't equal }
-                                     if not(equal_defs(procdefcoll^.data.returndef,pd.returndef)) and
-                                        not((procdefcoll^.data.returndef.typ=objectdef) and
-                                         (pd.returndef.typ=objectdef) and
-                                         is_class_or_interface(procdefcoll^.data.returndef) and
-                                         is_class_or_interface(pd.returndef) and
-                                         (tobjectdef(pd.returndef).is_related(
-                                             tobjectdef(procdefcoll^.data.returndef)))) then
-                                       begin
-                                         if not((m_delphi in current_settings.modeswitches) and
-                                                is_interface(_class)) then
-                                           Message2(parser_e_overridden_methods_not_same_ret,pd.fullprocname(false),
-                                                    procdefcoll^.data.fullprocname(false))
-                                         else
-                                          { Delphi allows changing the result type }
-                                          { of interface methods from anything to  }
-                                          { anything (JM)                          }
-                                           Message2(parser_w_overridden_methods_not_same_ret,pd.fullprocname(false),
-                                                    procdefcoll^.data.fullprocname(false));
-                                       end;
-                                     { check if the method to override is visible, check is only needed
-                                       for the current parsed class. Parent classes are already validated and
-                                       need to include all virtual methods including the ones not visible in the
-                                       current class }
-                                     if (_class=pd._class) and
-                                        (po_overridingmethod in pd.procoptions) and
-                                        (not procdefcoll^.visible) then
-                                       MessagePos1(pd.fileinfo,parser_e_nothing_to_be_overridden,pd.fullprocname(false));
-
-                                     { override old virtual method in VMT }
-                                     pd.extnumber:=procdefcoll^.data.extnumber;
-                                     procdefcoll^.data:=pd;
-                                     if is_visible then
-                                       procdefcoll^.visible:=true;
-
-                                     goto handlenextdef;
-                                   end
-                                  { different parameters }
-                                  else
-                                   begin
-                                     { when we got an override directive then can search futher for
-                                       the procedure to override.
-                                       If we are starting a new virtual tree then hide the old tree }
-                                     if not(po_overridingmethod in pd.procoptions) and
-                                        not pdoverload then
-                                      begin
-                                        if is_visible then
-                                          procdefcoll^.hidden:=true;
-                                        if (_class=pd._class) and not(po_reintroduce in pd.procoptions) then
-                                          MessagePos1(pd.fileinfo,parser_w_should_use_override,pd.fullprocname(false));
-                                      end;
-                                   end;
-                                end
-                               else
-                                begin
-                                  { the new definition is virtual and the old static, we hide the old one
-                                    if the new defintion has not the overload directive }
-                                  if is_visible and
-                                     ((not(pdoverload or hasoverloads)) or
-                                      (compare_paras(procdefcoll^.data.paras,pd.paras,cp_all,[])>=te_equal)) then
-                                    procdefcoll^.hidden:=true;
-                                end;
-                             end
-                            else
-                             begin
-                               { both are static, we hide the old one if the new defintion
-                                 has not the overload directive }
-                               if is_visible and
-                                  ((not pdoverload) or
-                                   (compare_paras(procdefcoll^.data.paras,pd.paras,cp_all,[])>=te_equal)) then
-                                 procdefcoll^.hidden:=true;
-                             end;
-                          end; { not hidden }
-                         procdefcoll:=procdefcoll^.next;
+                        if is_visible then
+                          procdefcoll^.hidden:=true;
+                        if (_class=pd._class) and not(po_reintroduce in pd.procoptions) then
+                          MessagePos1(pd.fileinfo,parser_w_should_use_override,pd.fullprocname(false));
                       end;
+                  end
+                { if both are virtual we check the header }
+                else if (po_virtualmethod in pd.procoptions) and
+                        (po_virtualmethod in procdefcoll^.data.procoptions) then
+                  begin
+                    { new one has not override }
+                    if is_class(_class) and
+                       not(po_overridingmethod in pd.procoptions) then
+                      begin
+                        { we start a new virtual tree, hide the old }
+                        if (not(pdoverload or hasoverloads) or
+                            (compare_paras(procdefcoll^.data.paras,pd.paras,cp_all,[])>=te_equal)) and
+                           (procdefcoll^.visible) then
+                          begin
+                            if is_visible then
+                              procdefcoll^.hidden:=true;
+                            if (_class=pd._class) and not(po_reintroduce in pd.procoptions) then
+                              MessagePos1(pd.fileinfo,parser_w_should_use_override,pd.fullprocname(false));
+                          end;
+                      end
+                    { same parameters }
+                    else if (compare_paras(procdefcoll^.data.paras,pd.paras,cp_all,[])>=te_equal) then
+                      begin
+                        { overload is inherited }
+                        if (po_overload in procdefcoll^.data.procoptions) then
+                         include(pd.procoptions,po_overload);
 
-                    { if it isn't saved in the list we create a new entry }
-                    newdefentry(vmtentry,pd,is_visible);
+                        { inherite calling convention when it was force and the
+                          current definition has none force }
+                        if (po_hascallingconvention in procdefcoll^.data.procoptions) and
+                           not(po_hascallingconvention in pd.procoptions) then
+                          begin
+                            pd.proccalloption:=procdefcoll^.data.proccalloption;
+                            include(pd.procoptions,po_hascallingconvention);
+                          end;
+
+                        { the flags have to match except abstract and override }
+                        { only if both are virtual !!  }
+                        if (procdefcoll^.data.proccalloption<>pd.proccalloption) or
+                           (procdefcoll^.data.proctypeoption<>pd.proctypeoption) or
+                           ((procdefcoll^.data.procoptions*po_comp)<>(pd.procoptions*po_comp)) then
+                           begin
+                             MessagePos1(pd.fileinfo,parser_e_header_dont_match_forward,pd.fullprocname(false));
+                             tprocsym(procdefcoll^.data.procsym).write_parameter_lists(pd);
+                           end;
+
+                        { error, if the return types aren't equal }
+                        if not(equal_defs(procdefcoll^.data.returndef,pd.returndef)) and
+                           not((procdefcoll^.data.returndef.typ=objectdef) and
+                            (pd.returndef.typ=objectdef) and
+                            is_class_or_interface(procdefcoll^.data.returndef) and
+                            is_class_or_interface(pd.returndef) and
+                            (tobjectdef(pd.returndef).is_related(tobjectdef(procdefcoll^.data.returndef)))) then
+                          begin
+                            if not((m_delphi in current_settings.modeswitches) and
+                                   is_interface(_class)) then
+                              Message2(parser_e_overridden_methods_not_same_ret,pd.fullprocname(false),
+                                       procdefcoll^.data.fullprocname(false))
+                            else
+                              { Delphi allows changing the result type of interface methods from anything to
+                                anything (JM) }
+                              Message2(parser_w_overridden_methods_not_same_ret,pd.fullprocname(false),
+                                       procdefcoll^.data.fullprocname(false));
+                          end;
+                        { check if the method to override is visible, check is only needed
+                          for the current parsed class. Parent classes are already validated and
+                          need to include all virtual methods including the ones not visible in the
+                          current class }
+                        if (_class=pd._class) and
+                           (po_overridingmethod in pd.procoptions) and
+                           (not procdefcoll^.visible) then
+                          MessagePos1(pd.fileinfo,parser_e_nothing_to_be_overridden,pd.fullprocname(false));
+
+                        { override old virtual method in VMT }
+                        if (procdefcoll^.data.extnumber>=_class.VMTEntries.Count) or
+                           (_class.VMTEntries[procdefcoll^.data.extnumber]<>procdefcoll^.data) then
+                          internalerror(200611084);
+                        _class.VMTEntries[procdefcoll^.data.extnumber]:=pd;
+                        pd.extnumber:=procdefcoll^.data.extnumber;
+                        procdefcoll^.data:=pd;
+                        if is_visible then
+                          procdefcoll^.visible:=true;
+
+                        exit;
+                      end
+                    { different parameters }
+                    else
+                     begin
+                       { when we got an override directive then can search futher for
+                         the procedure to override.
+                         If we are starting a new virtual tree then hide the old tree }
+                       if not(po_overridingmethod in pd.procoptions) and
+                          not pdoverload then
+                        begin
+                          if is_visible then
+                            procdefcoll^.hidden:=true;
+                          if (_class=pd._class) and not(po_reintroduce in pd.procoptions) then
+                            MessagePos1(pd.fileinfo,parser_w_should_use_override,pd.fullprocname(false));
+                        end;
+                     end;
+                  end
+                else
+                  begin
+                    { the new definition is virtual and the old static, we hide the old one
+                      if the new defintion has not the overload directive }
+                    if is_visible and
+                       (
+                        (not(pdoverload or hasoverloads)) or
+                        (compare_paras(procdefcoll^.data.paras,pd.paras,cp_all,[])>=te_equal)
+                       ) then
+                      procdefcoll^.hidden:=true;
                   end;
-                  handlenextdef:
+              end
+            else
+              begin
+                { both are static, we hide the old one if the new defintion
+                  has not the overload directive }
+                if is_visible and
+                   (
+                    (not pdoverload) or
+                    (compare_paras(procdefcoll^.data.paras,pd.paras,cp_all,[])>=te_equal)
+                   ) then
+                  procdefcoll^.hidden:=true;
                end;
-              exit;
-            end;
-           vmtentry:=vmtentry^.next;
-         end;
+          end;
+        { No entry found, we need to create a new entry }
+        result:=true;
+      end;
 
-        { Generate new procsym entry in vmt }
-        vmtentry:=newvmtentry(tprocsym(sym));
 
-        { Add procdefs }
-        for i:=0 to Tprocsym(sym).ProcdefList.Count-1 do
+    procedure TVMTBuilder.add_vmt_entries(objdef:tobjectdef);
+      var
+         pd  : tprocdef;
+         i,j : longint;
+         sym : tsym;
+         VMTSymEntry : TVMTSymEntry;
+      begin
+        { start with the base class }
+        if assigned(objdef.childof) then
+          add_vmt_entries(objdef.childof);
+        { process all procsyms }
+        for i:=0 to objdef.symtable.SymList.Count-1 do
           begin
-            pd:=tprocdef(Tprocsym(sym).ProcdefList[i]);
-            newdefentry(vmtentry,pd,pd.is_visible_for_object(_class,nil));
+            sym:=tsym(objdef.symtable.SymList[i]);
+            if sym.typ=procsym then
+              begin
+                { Find VMT procsym }
+                VMTSymEntry:=TVMTSymEntry(VMTSymEntryList.Find(sym.name));
+                if not assigned(VMTSymEntry) then
+                  VMTSymEntry:=TVMTSymEntry.Create(VMTSymEntryList,sym.name);
+                { Add all procdefs }
+                for j:=0 to Tprocsym(sym).ProcdefList.Count-1 do
+                  begin
+                    pd:=tprocdef(Tprocsym(sym).ProcdefList[j]);
+                    if pd.procsym=tprocsym(sym) then
+                      begin
+                        if is_new_vmt_entry(VMTSymEntry,pd) then
+                          add_new_vmt_entry(VMTSymEntry,pd);
+                      end;
+                  end;
+              end;
           end;
       end;
 
 
-    procedure tclassheader.disposevmttree;
+    function TVMTBuilder.intf_search_procdef_by_name(proc: tprocdef;const name: string): tprocdef;
+      const
+        po_comp = [po_classmethod,po_staticmethod,po_interrupt,po_iocheck,po_msgstr,po_msgint,
+                   po_exports,po_varargs,po_explicitparaloc,po_nostackframe];
       var
-        vmtentry : pvmtentry;
-        procdefcoll : pprocdefcoll;
+        sym: tsym;
+        implprocdef : Tprocdef;
+        i: cardinal;
       begin
-        { disposes the above generated tree }
-        vmtentry:=firstvmtentry;
-        while assigned(vmtentry) do
+        result:=nil;
+
+        sym:=tsym(search_class_member(_class,name));
+        if assigned(sym) and
+           (sym.typ=procsym) then
           begin
-            firstvmtentry:=vmtentry^.next;
-            stringdispose(vmtentry^.name);
-            procdefcoll:=vmtentry^.firstprocdef;
-            while assigned(procdefcoll) do
+            { when the definition has overload directive set, we search for
+              overloaded definitions in the class, this only needs to be done once
+              for class entries as the tree keeps always the same }
+            if (not tprocsym(sym).overloadchecked) and
+               (po_overload in tprocdef(tprocsym(sym).ProcdefList[0]).procoptions) and
+               (tprocsym(sym).owner.symtabletype=ObjectSymtable) then
+             search_class_overloads(tprocsym(sym));
+
+            for i:=0 to Tprocsym(sym).ProcdefList.Count-1 do
               begin
-                vmtentry^.firstprocdef:=procdefcoll^.next;
-                dispose(procdefcoll);
-                procdefcoll:=vmtentry^.firstprocdef;
+                implprocdef:=tprocdef(Tprocsym(sym).ProcdefList[i]);
+                if (compare_paras(proc.paras,implprocdef.paras,cp_none,[])>=te_equal) and
+                   (proc.proccalloption=implprocdef.proccalloption) and
+                   (proc.proctypeoption=implprocdef.proctypeoption) and
+                   ((proc.procoptions*po_comp)=((implprocdef.procoptions+[po_virtualmethod])*po_comp)) then
+                  begin
+                    result:=implprocdef;
+                    exit;
+                  end;
               end;
-            dispose(vmtentry);
-            vmtentry:=firstvmtentry;
           end;
       end;
 
 
-    procedure tclassheader.genvmt;
-
-      procedure do_genvmt(p : tobjectdef);
-
-        begin
-           { start with the base class }
-           if assigned(p.childof) then
-             do_genvmt(p.childof);
-
-           { walk through all public syms }
-           p.symtable.SymList.ForEachCall(@eachsym,nil);
-        end;
-
-      begin
-         firstvmtentry:=nil;
-         nextvirtnumber:=0;
-
-         has_constructor:=false;
-         has_virtual_method:=false;
-
-         { generates a tree of all used methods }
-         do_genvmt(_class);
-
-         if not(is_interface(_class)) and
-            has_virtual_method and
-            not(has_constructor) then
-           Message1(parser_w_virtual_without_constructor,_class.objrealname^);
-      end;
-
-
-{**************************************
-           Interface tables
-**************************************}
-
-    function  tclassheader.intf_get_vtbl_name(AImplIntf:TImplementedInterface): string;
-      begin
-        result:=make_mangledname('VTBL',_class.owner,_class.objname^+'_$_'+AImplIntf.IntfDef.objname^);
-      end;
-
-
-    procedure tclassheader.intf_create_vtbl(rawdata: TAsmList;AImplIntf:TImplementedInterface);
+    procedure TVMTBuilder.intf_get_procdefs(ImplIntf:TImplementedInterface;IntfDef:TObjectDef);
       var
-        pd : tprocdef;
-        vtblstr,
-        hs : string;
-        i  : longint;
+        i   : longint;
+        def : tdef;
+        hs,
+        prefix,
+        mappedname: string;
+        implprocdef: tprocdef;
       begin
-        vtblstr:=intf_get_vtbl_name(AImplIntf);
-        section_symbol_start(rawdata,vtblstr,AT_DATA,true,sec_data,const_align(sizeof(aint)));
-        if assigned(AImplIntf.procdefs) then
+        prefix:=ImplIntf.IntfDef.symtable.name^+'.';
+        for i:=0 to IntfDef.symtable.DefList.Count-1 do
           begin
-            for i:=0 to AImplIntf.procdefs.count-1 do
+            def:=tdef(IntfDef.symtable.DefList[i]);
+            if def.typ=procdef then
               begin
-                pd:=tprocdef(AImplIntf.procdefs[i]);
-                hs:=make_mangledname('WRPR',_class.owner,_class.objname^+'_$_'+AImplIntf.IntfDef.objname^+'_$_'+
-                                     tostr(i)+'_$_'+pd.mangledname);
-                { create reference }
-                rawdata.concat(Tai_const.Createname(hs,0));
+                { Find implementing procdef
+                   1. Check for mapped name
+                   2. Use symbol name }
+                implprocdef:=nil;
+                hs:=prefix+tprocdef(def).procsym.name;
+                mappedname:=ImplIntf.GetMapping(hs);
+                if mappedname<>'' then
+                  implprocdef:=intf_search_procdef_by_name(tprocdef(def),mappedname);
+                if not assigned(implprocdef) then
+                  implprocdef:=intf_search_procdef_by_name(tprocdef(def),tprocdef(def).procsym.name);
+                { Add procdef to the implemented interface }
+                if assigned(implprocdef) then
+                  ImplIntf.AddImplProc(implprocdef)
+                else
+                  if ImplIntf.IntfDef.iitype = etStandard then
+                    Message1(sym_e_no_matching_implementation_found,tprocdef(def).fullprocname(false));
               end;
-           end;
-        section_symbol_end(rawdata,vtblstr);
-      end;
-
-
-    procedure tclassheader.intf_gen_intf_ref(rawdata: TAsmList;AImplIntf:TImplementedInterface);
-      var
-        iidlabel,
-        guidlabel : tasmlabel;
-        i: longint;
-      begin
-        { GUID }
-        if AImplIntf.IntfDef.objecttype in [odt_interfacecom] then
-          begin
-            { label for GUID }
-            current_asmdata.getdatalabel(guidlabel);
-            rawdata.concat(cai_align.create(const_align(sizeof(aint))));
-            rawdata.concat(Tai_label.Create(guidlabel));
-            with AImplIntf.IntfDef.iidguid^ do
-              begin
-                rawdata.concat(Tai_const.Create_32bit(longint(D1)));
-                rawdata.concat(Tai_const.Create_16bit(D2));
-                rawdata.concat(Tai_const.Create_16bit(D3));
-                for i:=Low(D4) to High(D4) do
-                  rawdata.concat(Tai_const.Create_8bit(D4[i]));
-              end;
-            current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(guidlabel));
-          end
-        else
-          begin
-            { nil for Corba interfaces }
-            current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(nil));
           end;
-        { VTable }
-        current_asmdata.asmlists[al_globals].concat(Tai_const.Createname(intf_get_vtbl_name(AImplIntf.VtblImplIntf),0));
-        { IOffset field }
-        current_asmdata.asmlists[al_globals].concat(Tai_const.Create_aint(AImplIntf.VtblImplIntf.ioffset));
-        { IIDStr }
-        current_asmdata.getdatalabel(iidlabel);
-        rawdata.concat(cai_align.create(const_align(sizeof(aint))));
-        rawdata.concat(Tai_label.Create(iidlabel));
-        rawdata.concat(Tai_const.Create_8bit(length(AImplIntf.IntfDef.iidstr^)));
-        if AImplIntf.IntfDef.objecttype=odt_interfacecom then
-          rawdata.concat(Tai_string.Create(upper(AImplIntf.IntfDef.iidstr^)))
-        else
-          rawdata.concat(Tai_string.Create(AImplIntf.IntfDef.iidstr^));
-        current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(iidlabel));
-        { EntryType }
-        current_asmdata.asmlists[al_globals].concat(Tai_const.Create_aint(aint(AImplIntf.IntfDef.iitype)));
-        { EntryOffset }
-        current_asmdata.asmlists[al_globals].concat(Tai_const.Create_aint(aint(AImplIntf.IntfDef.iioffset)));
       end;
 
 
-    procedure tclassheader.intf_optimize_vtbls;
+    procedure TVMTBuilder.intf_get_procdefs_recursive(ImplIntf:TImplementedInterface;IntfDef:TObjectDef);
+      begin
+        if assigned(IntfDef.childof) then
+          intf_get_procdefs_recursive(ImplIntf,IntfDef.childof);
+        intf_get_procdefs(ImplIntf,IntfDef);
+      end;
+
+
+    procedure TVMTBuilder.intf_optimize_vtbls;
       type
         tcompintfentry = record
           weight: longint;
@@ -1117,14 +637,12 @@ implementation
       end;
 
 
-    procedure tclassheader.intf_write_data;
+    procedure TVMTBuilder.intf_allocate_vtbls;
       var
-        rawdata  : TAsmList;
-        i        : longint;
+        i : longint;
         ImplIntf : TImplementedInterface;
       begin
-        rawdata:=TAsmList.Create;
-        { Two pass, one for allocation and vtbl creation }
+        { Allocation vtbl space }
         for i:=0 to _class.ImplementedInterfaces.count-1 do
           begin
             ImplIntf:=TImplementedInterface(_class.ImplementedInterfaces[i]);
@@ -1138,134 +656,618 @@ implementation
                     ImplIntf.Ioffset:=datasize;
                     inc(datasize,sizeof(aint));
                   end;
-                { write vtbl }
-                intf_create_vtbl(rawdata,ImplIntf);
               end;
           end;
-        { second pass: for fill interfacetable and remained ioffsets }
-        current_asmdata.asmlists[al_globals].concat(Tai_const.Create_aint(_class.ImplementedInterfaces.count));
+        { Update ioffset of current interface with the ioffset from
+          the interface that is reused to implements this interface }
         for i:=0 to _class.ImplementedInterfaces.count-1 do
           begin
             ImplIntf:=TImplementedInterface(_class.ImplementedInterfaces[i]);
-            { Update ioffset of current interface with the ioffset from
-              the interface that is reused to implements this interface }
             if ImplIntf.VtblImplIntf<>ImplIntf then
               ImplIntf.Ioffset:=ImplIntf.VtblImplIntf.Ioffset;
-            intf_gen_intf_ref(rawdata,ImplIntf);
           end;
-        current_asmdata.asmlists[al_globals].concatlist(rawdata);
-        rawdata.free;
       end;
 
 
-    function tclassheader.intf_search_procdef_by_name(proc: tprocdef;const name: string): tprocdef;
-      const
-        po_comp = [po_classmethod,po_staticmethod,po_interrupt,po_iocheck,po_msgstr,po_msgint,
-                   po_exports,po_varargs,po_explicitparaloc,po_nostackframe];
+    procedure TVMTBuilder.generate_vmt;
       var
-        sym: tsym;
-        implprocdef : Tprocdef;
-        i: cardinal;
+        i : longint;
+        ImplIntf : TImplementedInterface;
       begin
-        result:=nil;
+        { Find VMT entries }
+        has_constructor:=false;
+        has_virtual_method:=false;
+        add_vmt_entries(_class);
+        if not(is_interface(_class)) and
+           has_virtual_method and
+           not(has_constructor) then
+          Message1(parser_w_virtual_without_constructor,_class.objrealname^);
 
-        sym:=tsym(search_class_member(_class,name));
-        if assigned(sym) and
-           (sym.typ=procsym) then
+        { Find Procdefs implementing the interfaces }
+        if assigned(_class.ImplementedInterfaces) then
           begin
-            { when the definition has overload directive set, we search for
-              overloaded definitions in the class, this only needs to be done once
-              for class entries as the tree keeps always the same }
-            if (not tprocsym(sym).overloadchecked) and
-               (po_overload in tprocdef(tprocsym(sym).ProcdefList[0]).procoptions) and
-               (tprocsym(sym).owner.symtabletype=ObjectSymtable) then
-             search_class_overloads(tprocsym(sym));
-
-            for i:=0 to Tprocsym(sym).ProcdefList.Count-1 do
+            { Collect implementor functions into the tImplementedInterface.procdefs }
+            for i:=0 to _class.ImplementedInterfaces.count-1 do
               begin
-                implprocdef:=tprocdef(Tprocsym(sym).ProcdefList[i]);
-                if (compare_paras(proc.paras,implprocdef.paras,cp_none,[])>=te_equal) and
-                   (proc.proccalloption=implprocdef.proccalloption) and
-                   (proc.proctypeoption=implprocdef.proctypeoption) and
-                   ((proc.procoptions*po_comp)=((implprocdef.procoptions+[po_virtualmethod])*po_comp)) then
-                  begin
-                    result:=implprocdef;
-                    exit;
-                  end;
+                ImplIntf:=TImplementedInterface(_class.ImplementedInterfaces[i]);
+                intf_get_procdefs_recursive(ImplIntf,ImplIntf.IntfDef);
+              end;
+            { Optimize interface tables to reuse wrappers }
+            intf_optimize_vtbls;
+            { Allocate interface tables }
+            intf_allocate_vtbls;
+          end;
+      end;
+
+
+{*****************************************************************************
+                                TVMTWriter
+*****************************************************************************}
+
+    constructor TVMTWriter.create(c:tobjectdef);
+      begin
+        inherited Create;
+        _Class:=c;
+      end;
+
+
+    destructor TVMTWriter.destroy;
+      begin
+      end;
+
+
+{**************************************
+           Message Tables
+**************************************}
+
+    procedure TVMTWriter.disposeprocdeftree(p : pprocdeftree);
+      begin
+         if assigned(p^.l) then
+           disposeprocdeftree(p^.l);
+         if assigned(p^.r) then
+           disposeprocdeftree(p^.r);
+         dispose(p);
+      end;
+
+
+    procedure TVMTWriter.insertint(p : pprocdeftree;var at : pprocdeftree;var count:longint);
+
+      begin
+         if at=nil then
+           begin
+              at:=p;
+              inc(count);
+           end
+         else
+           begin
+              if p^.data.messageinf.i<at^.data.messageinf.i then
+                insertint(p,at^.l,count)
+              else if p^.data.messageinf.i>at^.data.messageinf.i then
+                insertint(p,at^.r,count)
+              else
+                Message1(parser_e_duplicate_message_label,tostr(p^.data.messageinf.i));
+           end;
+      end;
+
+    procedure TVMTWriter.insertstr(p : pprocdeftree;var at : pprocdeftree;var count:longint);
+
+      var
+         i : integer;
+
+      begin
+         if at=nil then
+           begin
+              at:=p;
+              inc(count);
+           end
+         else
+           begin
+              i:=CompareStr(p^.data.messageinf.str^,at^.data.messageinf.str^);
+              if i<0 then
+                insertstr(p,at^.l,count)
+              else if i>0 then
+                insertstr(p,at^.r,count)
+              else
+                Message1(parser_e_duplicate_message_label,p^.data.messageinf.str^);
+           end;
+      end;
+
+
+    procedure TVMTWriter.insertmsgint(p:TObject;arg:pointer);
+      var
+        i  : longint;
+        pd : Tprocdef;
+        pt : pprocdeftree;
+      begin
+        if tsym(p).typ<>procsym then
+          exit;
+        for i:=0 to Tprocsym(p).ProcdefList.Count-1 do
+          begin
+            pd:=tprocdef(Tprocsym(p).ProcdefList[i]);
+            if po_msgint in pd.procoptions then
+              begin
+                new(pt);
+                pt^.data:=pd;
+                pt^.l:=nil;
+                pt^.r:=nil;
+                insertint(pt,root,plongint(arg)^);
               end;
           end;
       end;
 
 
-    procedure tclassheader.intf_get_procdefs(ImplIntf:TImplementedInterface;IntfDef:TObjectDef);
+    procedure TVMTWriter.insertmsgstr(p:TObject;arg:pointer);
+      var
+        i  : longint;
+        pd : Tprocdef;
+        pt : pprocdeftree;
+      begin
+        if tsym(p).typ<>procsym then
+          exit;
+        for i:=0 to Tprocsym(p).ProcdefList.Count-1 do
+          begin
+            pd:=tprocdef(Tprocsym(p).ProcdefList[i]);
+            if po_msgstr in pd.procoptions then
+              begin
+                new(pt);
+                pt^.data:=pd;
+                pt^.l:=nil;
+                pt^.r:=nil;
+                insertstr(pt,root,plongint(arg)^);
+              end;
+          end;
+      end;
+
+
+    procedure TVMTWriter.writenames(p : pprocdeftree);
+      var
+        ca : pchar;
+        len : byte;
+      begin
+         current_asmdata.getdatalabel(p^.nl);
+         if assigned(p^.l) then
+           writenames(p^.l);
+         current_asmdata.asmlists[al_globals].concat(cai_align.create(const_align(sizeof(aint))));
+         current_asmdata.asmlists[al_globals].concat(Tai_label.Create(p^.nl));
+         len:=length(p^.data.messageinf.str^);
+         current_asmdata.asmlists[al_globals].concat(tai_const.create_8bit(len));
+         getmem(ca,len+1);
+         move(p^.data.messageinf.str[1],ca^,len);
+         ca[len]:=#0;
+         current_asmdata.asmlists[al_globals].concat(Tai_string.Create_pchar(ca,len));
+         if assigned(p^.r) then
+           writenames(p^.r);
+      end;
+
+    procedure TVMTWriter.writestrentry(p : pprocdeftree);
+
+      begin
+         if assigned(p^.l) then
+           writestrentry(p^.l);
+
+         { write name label }
+         current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(p^.nl));
+         current_asmdata.asmlists[al_globals].concat(Tai_const.Createname(p^.data.mangledname,0));
+
+         if assigned(p^.r) then
+           writestrentry(p^.r);
+     end;
+
+
+    function TVMTWriter.genstrmsgtab : tasmlabel;
+      var
+         count : aint;
+      begin
+         root:=nil;
+         count:=0;
+         { insert all message handlers into a tree, sorted by name }
+         _class.symtable.SymList.ForEachCall(@insertmsgstr,@count);
+
+         { write all names }
+         if assigned(root) then
+           writenames(root);
+
+         { now start writing of the message string table }
+         current_asmdata.getdatalabel(result);
+         current_asmdata.asmlists[al_globals].concat(cai_align.create(const_align(sizeof(aint))));
+         current_asmdata.asmlists[al_globals].concat(Tai_label.Create(result));
+         current_asmdata.asmlists[al_globals].concat(Tai_const.Create_aint(count));
+         if assigned(root) then
+           begin
+              writestrentry(root);
+              disposeprocdeftree(root);
+           end;
+      end;
+
+
+    procedure TVMTWriter.writeintentry(p : pprocdeftree);
+      begin
+         if assigned(p^.l) then
+           writeintentry(p^.l);
+
+         { write name label }
+         current_asmdata.asmlists[al_globals].concat(Tai_const.Create_32bit(p^.data.messageinf.i));
+         current_asmdata.asmlists[al_globals].concat(Tai_const.Createname(p^.data.mangledname,0));
+
+         if assigned(p^.r) then
+           writeintentry(p^.r);
+      end;
+
+
+    function TVMTWriter.genintmsgtab : tasmlabel;
+      var
+         r : tasmlabel;
+         count : longint;
+      begin
+         root:=nil;
+         count:=0;
+         { insert all message handlers into a tree, sorted by name }
+         _class.symtable.SymList.ForEachCall(@insertmsgint,@count);
+
+         { now start writing of the message string table }
+         current_asmdata.getdatalabel(r);
+         current_asmdata.asmlists[al_globals].concat(cai_align.create(const_align(sizeof(aint))));
+         current_asmdata.asmlists[al_globals].concat(Tai_label.Create(r));
+         genintmsgtab:=r;
+         current_asmdata.asmlists[al_globals].concat(Tai_const.Create_32bit(count));
+         if assigned(root) then
+           begin
+              writeintentry(root);
+              disposeprocdeftree(root);
+           end;
+      end;
+
+{$ifdef WITHDMT}
+
+{**************************************
+              DMT
+**************************************}
+
+    procedure TVMTWriter.insertdmtentry(p:TObject;arg:pointer);
+
+      var
+         hp : tprocdef;
+         pt : pprocdeftree;
+
+      begin
+         if tsym(p).typ=procsym then
+           begin
+              hp:=tprocsym(p).definition;
+              while assigned(hp) do
+                begin
+                   if (po_msgint in hp.procoptions) then
+                     begin
+                        new(pt);
+                        pt^.p:=hp;
+                        pt^.l:=nil;
+                        pt^.r:=nil;
+                        insertint(pt,root);
+                     end;
+                   hp:=hp.nextoverloaded;
+                end;
+           end;
+      end;
+
+    procedure TVMTWriter.writedmtindexentry(p : pprocdeftree);
+
+      begin
+         if assigned(p^.l) then
+           writedmtindexentry(p^.l);
+         al_globals.concat(Tai_const.Create_32bit(p^.data.messageinf.i));
+         if assigned(p^.r) then
+           writedmtindexentry(p^.r);
+      end;
+
+    procedure TVMTWriter.writedmtaddressentry(p : pprocdeftree);
+
+      begin
+         if assigned(p^.l) then
+           writedmtaddressentry(p^.l);
+         al_globals.concat(Tai_const_symbol.Createname(p^.data.mangledname,0));
+         if assigned(p^.r) then
+           writedmtaddressentry(p^.r);
+      end;
+
+    function TVMTWriter.gendmt : tasmlabel;
+
+      var
+         r : tasmlabel;
+
+      begin
+         root:=nil;
+         count:=0;
+         gendmt:=nil;
+         { insert all message handlers into a tree, sorted by number }
+         _class.symtable.SymList.ForEachCall(insertdmtentry);
+
+         if count>0 then
+           begin
+              current_asmdata.getdatalabel(r);
+              gendmt:=r;
+              al_globals.concat(cai_align.create(const_align(sizeof(aint))));
+              al_globals.concat(Tai_label.Create(r));
+              { entries for caching }
+              al_globals.concat(Tai_const.Create_ptr(0));
+              al_globals.concat(Tai_const.Create_ptr(0));
+
+              al_globals.concat(Tai_const.Create_32bit(count));
+              if assigned(root) then
+                begin
+                   writedmtindexentry(root);
+                   writedmtaddressentry(root);
+                   disposeprocdeftree(root);
+                end;
+           end;
+      end;
+
+{$endif WITHDMT}
+
+{**************************************
+        Published Methods
+**************************************}
+
+    procedure TVMTWriter.do_count_published_methods(p:TObject;arg:pointer);
+      var
+        i  : longint;
+        pd : tprocdef;
+      begin
+        if (tsym(p).typ<>procsym) then
+          exit;
+        for i:=0 to Tprocsym(p).ProcdefList.Count-1 do
+          begin
+            pd:=tprocdef(Tprocsym(p).ProcdefList[i]);
+            if (pd.procsym=tsym(p)) and
+               (sp_published in pd.symoptions) then
+              inc(plongint(arg)^);
+          end;
+      end;
+
+
+    procedure TVMTWriter.do_gen_published_methods(p:TObject;arg:pointer);
+      var
+        i  : longint;
+        l  : tasmlabel;
+        pd : tprocdef;
+      begin
+        if (tsym(p).typ<>procsym) then
+          exit;
+        for i:=0 to Tprocsym(p).ProcdefList.Count-1 do
+          begin
+            pd:=tprocdef(Tprocsym(p).ProcdefList[i]);
+            if (pd.procsym=tsym(p)) and
+               (sp_published in pd.symoptions) then
+              begin
+                current_asmdata.getdatalabel(l);
+
+                current_asmdata.asmlists[al_typedconsts].concat(cai_align.create(const_align(sizeof(aint))));
+                current_asmdata.asmlists[al_typedconsts].concat(Tai_label.Create(l));
+                current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_8bit(length(tsym(p).realname)));
+                current_asmdata.asmlists[al_typedconsts].concat(Tai_string.Create(tsym(p).realname));
+
+                current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(l));
+                if po_abstractmethod in pd.procoptions then
+                  current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(nil))
+                else
+                  current_asmdata.asmlists[al_globals].concat(Tai_const.Createname(pd.mangledname,0));
+              end;
+           end;
+      end;
+
+
+    function TVMTWriter.genpublishedmethodstable : tasmlabel;
+
+      var
+         l : tasmlabel;
+         count : longint;
+
+      begin
+         count:=0;
+         _class.symtable.SymList.ForEachCall(@do_count_published_methods,@count);
+         if count>0 then
+           begin
+              current_asmdata.getdatalabel(l);
+              current_asmdata.asmlists[al_globals].concat(cai_align.create(const_align(sizeof(aint))));
+              current_asmdata.asmlists[al_globals].concat(Tai_label.Create(l));
+              current_asmdata.asmlists[al_globals].concat(Tai_const.Create_32bit(count));
+              _class.symtable.SymList.ForEachCall(@do_gen_published_methods,nil);
+              genpublishedmethodstable:=l;
+           end
+         else
+           genpublishedmethodstable:=nil;
+      end;
+
+
+    function TVMTWriter.generate_field_table : tasmlabel;
       var
         i   : longint;
-        def : tdef;
-        hs,
-        prefix,
-        mappedname: string;
-        implprocdef: tprocdef;
+        sym : tsym;
+        fieldtable,
+        classtable : tasmlabel;
+        classindex,
+        fieldcount : longint;
+        classtablelist : TFPList;
       begin
-        prefix:=ImplIntf.IntfDef.symtable.name^+'.';
-        for i:=0 to IntfDef.symtable.DefList.Count-1 do
+        classtablelist:=TFPList.Create;
+        current_asmdata.getdatalabel(fieldtable);
+        current_asmdata.getdatalabel(classtable);
+        maybe_new_object_file(current_asmdata.asmlists[al_rtti]);
+        new_section(current_asmdata.asmlists[al_rtti],sec_rodata,classtable.name,const_align(sizeof(aint)));
+
+        { retrieve field info fields }
+        fieldcount:=0;
+        for i:=0 to _class.symtable.SymList.Count-1 do
           begin
-            def:=tdef(IntfDef.symtable.DefList[i]);
-            if def.typ=procdef then
+            sym:=tsym(_class.symtable.SymList[i]);
+            if (tsym(sym).typ=fieldvarsym) and
+               (sp_published in tsym(sym).symoptions) then
+             begin
+                if tfieldvarsym(sym).vardef.typ<>objectdef then
+                  internalerror(200611032);
+                classindex:=classtablelist.IndexOf(tfieldvarsym(sym).vardef);
+                if classindex=-1 then
+                  classtablelist.Add(tfieldvarsym(sym).vardef);
+                inc(fieldcount);
+             end;
+          end;
+
+        { write fields }
+        current_asmdata.asmlists[al_rtti].concat(Tai_label.Create(fieldtable));
+        current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_16bit(fieldcount));
+{$ifdef cpurequiresproperalignment}
+        current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
+{$endif cpurequiresproperalignment}
+        current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_sym(classtable));
+        for i:=0 to _class.symtable.SymList.Count-1 do
+          begin
+            sym:=tsym(_class.symtable.SymList[i]);
+            if (tsym(sym).typ=fieldvarsym) and
+               (sp_published in tsym(sym).symoptions) then
               begin
-                { Find implementing procdef
-                   1. Check for mapped name
-                   2. Use symbol name }
-                implprocdef:=nil;
-                hs:=prefix+tprocdef(def).procsym.name;
-                mappedname:=ImplIntf.GetMapping(hs);
-                if mappedname<>'' then
-                  implprocdef:=intf_search_procdef_by_name(tprocdef(def),mappedname);
-                if not assigned(implprocdef) then
-                  implprocdef:=intf_search_procdef_by_name(tprocdef(def),tprocdef(def).procsym.name);
-                { Add procdef to the implemented interface }
-                if assigned(implprocdef) then
-                  ImplIntf.AddImplProc(implprocdef)
-                else
-                  if ImplIntf.IntfDef.iitype = etStandard then
-                    Message1(sym_e_no_matching_implementation_found,tprocdef(def).fullprocname(false));
+{$ifdef cpurequiresproperalignment}
+                current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(AInt)));
+{$endif cpurequiresproperalignment}
+                current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_aint(tfieldvarsym(sym).fieldoffset));
+                classindex:=classtablelist.IndexOf(tfieldvarsym(sym).vardef);
+                if classindex=-1 then
+                  internalerror(200611033);
+                current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_16bit(classindex+1));
+                current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(length(tfieldvarsym(sym).realname)));
+                current_asmdata.asmlists[al_rtti].concat(Tai_string.Create(tfieldvarsym(sym).realname));
               end;
           end;
+
+        { generate the class table }
+        current_asmdata.asmlists[al_rtti].concat(cai_align.create(const_align(sizeof(aint))));
+        current_asmdata.asmlists[al_rtti].concat(Tai_label.Create(classtable));
+        current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_16bit(classtablelist.count));
+{$ifdef cpurequiresproperalignment}
+        current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
+{$endif cpurequiresproperalignment}
+        for i:=0 to classtablelist.Count-1 do
+          current_asmdata.asmlists[al_rtti].concat(Tai_const.Createname(tobjectdef(classtablelist[i]).vmt_mangledname,0));
+
+        classtablelist.free;
+        result:=fieldtable;
       end;
 
 
-    procedure tclassheader.intf_get_procdefs_recursive(ImplIntf:TImplementedInterface;IntfDef:TObjectDef);
+{**************************************
+           Interface tables
+**************************************}
+
+    function  TVMTWriter.intf_get_vtbl_name(AImplIntf:TImplementedInterface): string;
       begin
-        if assigned(IntfDef.childof) then
-          intf_get_procdefs_recursive(ImplIntf,IntfDef.childof);
-        intf_get_procdefs(ImplIntf,IntfDef);
+        result:=make_mangledname('VTBL',_class.owner,_class.objname^+'_$_'+AImplIntf.IntfDef.objname^);
       end;
 
 
-    function tclassheader.genintftable: tasmlabel;
+    procedure TVMTWriter.intf_create_vtbl(rawdata: TAsmList;AImplIntf:TImplementedInterface);
       var
-        ImplIntf  : TImplementedInterface;
-        intftable : tasmlabel;
-        i : longint;
+        pd : tprocdef;
+        vtblstr,
+        hs : string;
+        i  : longint;
       begin
-        { 1. step collect implementor functions into the tImplementedInterface.procdefs }
+        vtblstr:=intf_get_vtbl_name(AImplIntf);
+        section_symbol_start(rawdata,vtblstr,AT_DATA,true,sec_data,const_align(sizeof(aint)));
+        if assigned(AImplIntf.procdefs) then
+          begin
+            for i:=0 to AImplIntf.procdefs.count-1 do
+              begin
+                pd:=tprocdef(AImplIntf.procdefs[i]);
+                hs:=make_mangledname('WRPR',_class.owner,_class.objname^+'_$_'+AImplIntf.IntfDef.objname^+'_$_'+
+                                     tostr(i)+'_$_'+pd.mangledname);
+                { create reference }
+                rawdata.concat(Tai_const.Createname(hs,0));
+              end;
+           end;
+        section_symbol_end(rawdata,vtblstr);
+      end;
+
+
+    procedure TVMTWriter.intf_gen_intf_ref(rawdata: TAsmList;AImplIntf:TImplementedInterface);
+      var
+        iidlabel,
+        guidlabel : tasmlabel;
+        i: longint;
+      begin
+        { GUID }
+        if AImplIntf.IntfDef.objecttype in [odt_interfacecom] then
+          begin
+            { label for GUID }
+            current_asmdata.getdatalabel(guidlabel);
+            rawdata.concat(cai_align.create(const_align(sizeof(aint))));
+            rawdata.concat(Tai_label.Create(guidlabel));
+            with AImplIntf.IntfDef.iidguid^ do
+              begin
+                rawdata.concat(Tai_const.Create_32bit(longint(D1)));
+                rawdata.concat(Tai_const.Create_16bit(D2));
+                rawdata.concat(Tai_const.Create_16bit(D3));
+                for i:=Low(D4) to High(D4) do
+                  rawdata.concat(Tai_const.Create_8bit(D4[i]));
+              end;
+            current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(guidlabel));
+          end
+        else
+          begin
+            { nil for Corba interfaces }
+            current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(nil));
+          end;
+        { VTable }
+        current_asmdata.asmlists[al_globals].concat(Tai_const.Createname(intf_get_vtbl_name(AImplIntf.VtblImplIntf),0));
+        { IOffset field }
+        current_asmdata.asmlists[al_globals].concat(Tai_const.Create_aint(AImplIntf.VtblImplIntf.ioffset));
+        { IIDStr }
+        current_asmdata.getdatalabel(iidlabel);
+        rawdata.concat(cai_align.create(const_align(sizeof(aint))));
+        rawdata.concat(Tai_label.Create(iidlabel));
+        rawdata.concat(Tai_const.Create_8bit(length(AImplIntf.IntfDef.iidstr^)));
+        if AImplIntf.IntfDef.objecttype=odt_interfacecom then
+          rawdata.concat(Tai_string.Create(upper(AImplIntf.IntfDef.iidstr^)))
+        else
+          rawdata.concat(Tai_string.Create(AImplIntf.IntfDef.iidstr^));
+        current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(iidlabel));
+        { EntryType }
+        current_asmdata.asmlists[al_globals].concat(Tai_const.Create_aint(aint(AImplIntf.IntfDef.iitype)));
+        { EntryOffset }
+        current_asmdata.asmlists[al_globals].concat(Tai_const.Create_aint(aint(AImplIntf.IntfDef.iioffset)));
+      end;
+
+
+    function TVMTWriter.intf_write_table:TAsmLabel;
+      var
+        rawdata  : TAsmList;
+        i        : longint;
+        ImplIntf : TImplementedInterface;
+        intftablelab : tasmlabel;
+      begin
+        current_asmdata.getdatalabel(intftablelab);
+        current_asmdata.asmlists[al_globals].concat(cai_align.create(const_align(sizeof(aint))));
+        current_asmdata.asmlists[al_globals].concat(Tai_label.Create(intftablelab));
+        current_asmdata.asmlists[al_globals].concat(Tai_const.Create_aint(_class.ImplementedInterfaces.count));
+        rawdata:=TAsmList.Create;
+        { Write vtbls }
         for i:=0 to _class.ImplementedInterfaces.count-1 do
           begin
             ImplIntf:=TImplementedInterface(_class.ImplementedInterfaces[i]);
-            intf_get_procdefs_recursive(ImplIntf,ImplIntf.IntfDef);
+            if ImplIntf.VtblImplIntf=ImplIntf then
+              intf_create_vtbl(rawdata,ImplIntf);
           end;
-        { 2. Optimize interface tables to reuse wrappers }
-        intf_optimize_vtbls;
-        { 3. Calculate offsets in object map and Write interface tables }
-        current_asmdata.getdatalabel(intftable);
-        current_asmdata.asmlists[al_globals].concat(cai_align.create(const_align(sizeof(aint))));
-        current_asmdata.asmlists[al_globals].concat(Tai_label.Create(intftable));
-        intf_write_data;
-        genintftable:=intftable;
+        { Write vtbl references }
+        for i:=0 to _class.ImplementedInterfaces.count-1 do
+          begin
+            ImplIntf:=TImplementedInterface(_class.ImplementedInterfaces[i]);
+            intf_gen_intf_ref(rawdata,ImplIntf);
+          end;
+        { Write interface table }
+        current_asmdata.asmlists[al_globals].concatlist(rawdata);
+        rawdata.free;
+        result:=intftablelab;
       end;
 
 
   { Write interface identifiers to the data section }
-  procedure tclassheader.writeinterfaceids;
+  procedure TVMTWriter.writeinterfaceids;
     var
       i : longint;
       s : string;
@@ -1291,54 +1293,41 @@ implementation
     end;
 
 
-    procedure tclassheader.writevirtualmethods(List:TAsmList);
+    procedure TVMTWriter.writevirtualmethods(List:TAsmList);
       var
-         vmtentry : pvmtentry;
-         procdefcoll : pprocdefcoll;
-         i : longint;
+         pd : tprocdef;
+         i  : longint;
          procname : string;
 {$ifdef vtentry}
          hs : string;
 {$endif vtentry}
       begin
-         { walk trough all numbers for virtual methods and search }
-         { the method                                             }
-         for i:=0 to nextvirtnumber-1 do
-           begin
-              { walk trough all symbols }
-              vmtentry:=firstvmtentry;
-              while assigned(vmtentry) do
-                begin
-                   { walk trough all methods }
-                   procdefcoll:=vmtentry^.firstprocdef;
-                   while assigned(procdefcoll) do
-                     begin
-                        { writes the addresses to the VMT }
-                        { but only this which are declared as virtual }
-                        if (procdefcoll^.data.extnumber=i) and
-                           (po_virtualmethod in procdefcoll^.data.procoptions) then
-                          begin
-                            if (po_abstractmethod in procdefcoll^.data.procoptions) then
-                              procname:='FPC_ABSTRACTERROR'
-                            else
-                              procname:=procdefcoll^.data.mangledname;
-                            List.concat(Tai_const.createname(procname,0));
+        if not assigned(_class.VMTEntries) then
+          exit;
+        for i:=0 to _class.VMTEntries.Count-1 do
+         begin
+           pd:=tprocdef(_class.VMTEntries[i]);
+           if not(po_virtualmethod in pd.procoptions) then
+             internalerror(200611082);
+           if pd.extnumber<>i then
+             internalerror(200611083);
+           if (po_abstractmethod in pd.procoptions) then
+             procname:='FPC_ABSTRACTERROR'
+           else
+             procname:=pd.mangledname;
+           List.concat(Tai_const.createname(procname,0));
 {$ifdef vtentry}
-                            hs:='VTENTRY'+'_'+_class.vmt_mangledname+'$$'+tostr(_class.vmtmethodoffset(i) div sizeof(aint));
-                            current_asmdata.asmlists[al_globals].concat(tai_symbol.CreateName(hs,AT_DATA,0));
+           hs:='VTENTRY'+'_'+_class.vmt_mangledname+'$$'+tostr(_class.vmtmethodoffset(i) div sizeof(aint));
+           current_asmdata.asmlists[al_globals].concat(tai_symbol.CreateName(hs,AT_DATA,0));
 {$endif vtentry}
-                            break;
-                          end;
-                        procdefcoll:=procdefcoll^.next;
-                     end;
-                   vmtentry:=vmtentry^.next;
-                end;
-           end;
+         end;
+        { release VMTEntries, we don't need them anymore }
+        _class.VMTEntries.free;
+        _class.VMTEntries:=nil;
       end;
 
-    { generates the vmt for classes as well as for objects }
-    procedure tclassheader.writevmt;
 
+    procedure TVMTWriter.writevmt;
       var
          methodnametable,intmessagetable,
          strmessagetable,classnamelabel,
@@ -1365,7 +1354,7 @@ implementation
 
             { interface table }
             if _class.ImplementedInterfaces.count>0 then
-              interfacetable:=genintftable;
+              interfacetable:=intf_write_table;
 
             methodnametable:=genpublishedmethodstable;
             fieldtablelabel:=generate_field_table;
diff --git a/compiler/pdecl.pas b/compiler/pdecl.pas
index df96ef5b1b..4fb6a7f5ad 100644
--- a/compiler/pdecl.pas
+++ b/compiler/pdecl.pas
@@ -57,7 +57,7 @@ implementation
        { symtable }
        symconst,symbase,symtype,symdef,symtable,paramgr,defutil,
        { pass 1 }
-       nmat,nadd,ncal,nset,ncnv,ninl,ncon,nld,nflw,
+       nmat,nadd,ncal,nset,ncnv,ninl,ncon,nld,nflw,nobj,
        { codegen }
        ncgutil,
        { parser }
@@ -235,8 +235,6 @@ implementation
                       { add default calling convention }
                       handle_calling_convention(tabstractprocdef(hdef));
                     end;
-                   { write rtti/init tables }
-                   write_persistent_type_info(hdef);
                    if not skipequal then
                     begin
                       { get init value }
@@ -406,6 +404,7 @@ implementation
          istyperenaming : boolean;
          generictypelist : TFPObjectList;
          generictokenbuf : tdynamicarray;
+         vmtbuilder : TVMTBuilder;
       begin
          old_block_type:=block_type;
          block_type:=bt_type;
@@ -533,7 +532,19 @@ implementation
                        handle_calling_convention(tprocvardef(hdef));
                      end;
                   end;
-                objectdef,
+                objectdef :
+                  begin
+                    { Build VMT indexes, skip for type renaming and forward classes }
+                    if (hdef.typesym=newtype) and
+                       not(oo_is_forward in tobjectdef(hdef).objectoptions) then
+                      begin
+                        vmtbuilder:=TVMTBuilder.Create(tobjectdef(hdef));
+                        vmtbuilder.generate_vmt;
+                        vmtbuilder.free;
+                      end;
+                    try_consume_hintdirective(newtype.symoptions);
+                    consume(_SEMICOLON);
+                  end;
                 recorddef :
                   begin
                     try_consume_hintdirective(newtype.symoptions);
@@ -555,18 +566,6 @@ implementation
                { Generic is never a type renaming }
                hdef.typesym:=newtype;
              end;
-
-           { Write tables if there are no errors and we are the typesym that
-             defines this type, so this will not be done for simple type renamings }
-           if (hdef.typ<>errordef) and
-              (hdef.typesym=newtype) then
-            begin
-              { file position }
-              oldfilepos:=current_filepos;
-              current_filepos:=newtype.fileinfo;
-              write_persistent_type_info(hdef);
-              current_filepos:=oldfilepos;
-            end;
          until token<>_ID;
          typecanbeforward:=false;
          symtablestack.top.SymList.ForEachCall(@resolve_type_forward,nil);
diff --git a/compiler/pdecobj.pas b/compiler/pdecobj.pas
index 1bc8bc0e93..b81a64b929 100644
--- a/compiler/pdecobj.pas
+++ b/compiler/pdecobj.pas
@@ -179,8 +179,8 @@ implementation
               if assigned(def) and
                  (def.typ=procdef) then
                 begin
-                  tprocdef(def).extnumber:=aktobjectdef.lastvtableindex;
-                  inc(aktobjectdef.lastvtableindex);
+//                  tprocdef(def).extnumber:=aktobjectdef.lastvtableindex;
+//                  inc(aktobjectdef.lastvtableindex);
                   include(tprocdef(def).procoptions,po_virtualmethod);
                   tprocdef(def).forwarddef:=false;
                 end;
diff --git a/compiler/pmodules.pas b/compiler/pmodules.pas
index 2a66e2c106..71a243b0a0 100644
--- a/compiler/pmodules.pas
+++ b/compiler/pmodules.pas
@@ -43,7 +43,7 @@ implementation
        link,assemble,import,export,gendef,ppu,comprsrc,dbgbase,
        cresstr,procinfo,
        pexports,
-       scanner,pbase,pexpr,psystem,psub,pdecsub;
+       scanner,pbase,pexpr,psystem,psub,pdecsub,ptype;
 
 
     procedure create_objectfile;
@@ -1110,10 +1110,6 @@ implementation
          { do we need to add the variants unit? }
          maybeloadvariantsunit;
 
-         { generate debuginfo }
-         if (cs_debuginfo in current_settings.moduleswitches) then
-           debuginfo.inserttypeinfo;
-
          { generate wrappers for interfaces }
          gen_intf_wrappers(current_asmdata.asmlists[al_procedures],current_module.globalsymtable);
          gen_intf_wrappers(current_asmdata.asmlists[al_procedures],current_module.localsymtable);
@@ -1121,12 +1117,20 @@ implementation
          { generate pic helpers to load eip if necessary }
          gen_pic_helpers(current_asmdata.asmlists[al_procedures]);
 
+         { generate rtti/init tables }
+         write_persistent_type_info(current_module.globalsymtable);
+         write_persistent_type_info(current_module.localsymtable);
+
          { Tables }
          insertThreadVars;
 
          { Resource strings }
          GenerateResourceStrings;
 
+         { generate debuginfo }
+         if (cs_debuginfo in current_settings.moduleswitches) then
+           debuginfo.inserttypeinfo;
+
          { generate imports }
          if current_module.ImportLibraryList.Count>0 then
            importlib.generatelib;
@@ -1437,22 +1441,25 @@ implementation
            InsertPData;
 {$endif arm}
 
-         { generate debuginfo }
-         if (cs_debuginfo in current_settings.moduleswitches) then
-           debuginfo.inserttypeinfo;
-
          InsertThreadvars;
 
-         { generate wrappers for interfaces }
-         gen_intf_wrappers(current_asmdata.asmlists[al_procedures],current_module.localsymtable);
-
          { generate pic helpers to load eip if necessary }
          gen_pic_helpers(current_asmdata.asmlists[al_procedures]);
 
+         { generate rtti/init tables }
+         write_persistent_type_info(current_module.localsymtable);
+
+         { generate wrappers for interfaces }
+         gen_intf_wrappers(current_asmdata.asmlists[al_procedures],current_module.localsymtable);
+
          { generate imports }
          if current_module.ImportLibraryList.Count>0 then
            importlib.generatelib;
 
+         { generate debuginfo }
+         if (cs_debuginfo in current_settings.moduleswitches) then
+           debuginfo.inserttypeinfo;
+
          if islibrary or (target_info.system in system_unit_program_exports) then
            exportlib.generatelib;
 
diff --git a/compiler/psystem.pas b/compiler/psystem.pas
index c6cb3473b5..92987e163c 100644
--- a/compiler/psystem.pas
+++ b/compiler/psystem.pas
@@ -112,9 +112,6 @@ implementation
         begin
           result:=ttypesym.create(s,def);
           systemunit.insert(result);
-          { write always RTTI to get persistent typeinfo }
-          RTTIWriter.write_rtti(def,initrtti);
-          RTTIWriter.write_rtti(def,fullrtti);
         end;
 
       var
diff --git a/compiler/ptype.pas b/compiler/ptype.pas
index f10e0cf4f2..65716be714 100644
--- a/compiler/ptype.pas
+++ b/compiler/ptype.pas
@@ -26,7 +26,8 @@ unit ptype;
 interface
 
     uses
-       globtype,cclasses,symtype,symdef;
+       globtype,cclasses,
+       symtype,symdef,symbase;
 
     const
        { forward types should only be possible inside a TYPE statement }
@@ -50,7 +51,7 @@ interface
     procedure read_anon_type(var def : tdef;parseprocvardir:boolean);
 
     { generate persistent type information like VMT, RTTI and inittables }
-    procedure write_persistent_type_info(def : tdef);
+    procedure write_persistent_type_info(st:tsymtable);
 
 
 implementation
@@ -64,7 +65,7 @@ implementation
        { target }
        paramgr,
        { symtable }
-       symconst,symbase,symsym,symtable,
+       symconst,symsym,symtable,
        defutil,defcmp,
        { pass 1 }
        node,ncgrtti,nobj,
@@ -771,43 +772,61 @@ implementation
       end;
 
 
-    procedure write_persistent_type_info(def : tdef);
+    procedure write_persistent_type_info(st:tsymtable);
       var
-        ch  : tclassheader;
+        i : longint;
+        def : tdef;
+        vmtwriter  : TVMTWriter;
       begin
-        { generate persistent init/final tables when it's declared in the interface so it can
-          be reused in other used }
-        if def.owner.symtabletype=globalsymtable then
-          RTTIWriter.write_rtti(def,initrtti);
-
-        { for objects we should write the vmt and interfaces.
-          This need to be done after the rtti has been written, because
-          it can contain a reference to that data (PFV)
-          This is not for forward classes }
-        if (def.typ=objectdef) then
+        for i:=0 to st.DefList.Count-1 do
           begin
-            if not(oo_vmt_written in tobjectdef(def).objectoptions) and
-               not(oo_is_forward in tobjectdef(def).objectoptions) then
-              begin
-                ch:=tclassheader.create(tobjectdef(def));
-                { generate and check virtual methods, must be done
-                  before RTTI is written }
-                ch.genvmt;
-                { Generate RTTI for class }
-                RTTIWriter.write_rtti(def,fullrtti);
-                if is_interface(tobjectdef(def)) then
-                  ch.writeinterfaceids;
-                if (oo_has_vmt in tobjectdef(def).objectoptions) then
-                  ch.writevmt;
-                ch.free;
-                include(tobjectdef(def).objectoptions,oo_vmt_written);
-              end;
-          end
-        else
-          begin
-            { Always generate RTTI info for all types. This is to have typeinfo() return
-              the same pointer }
-            if def.owner.symtabletype=globalsymtable then
+            def:=tdef(st.DefList[i]);
+            if df_deleted in def.defoptions then
+              continue;
+            case def.typ of
+              recorddef :
+                write_persistent_type_info(trecorddef(def).symtable);
+              objectdef :
+                begin
+                  write_persistent_type_info(tobjectdef(def).symtable);
+                  { Write also VMT }
+                  if not(ds_vmt_written in def.defstates) and
+                     not(oo_is_forward in tobjectdef(def).objectoptions) then
+                    begin
+                      vmtwriter:=TVMTWriter.create(tobjectdef(def));
+                      if is_interface(tobjectdef(def)) then
+                        vmtwriter.writeinterfaceids;
+                      if (oo_has_vmt in tobjectdef(def).objectoptions) then
+                        vmtwriter.writevmt;
+                      vmtwriter.free;
+                      include(def.defstates,ds_vmt_written);
+                    end;
+                end;
+              procdef :
+                begin
+                  if assigned(tprocdef(def).localst) and
+                     (tprocdef(def).localst.symtabletype=localsymtable) then
+                    write_persistent_type_info(tprocdef(def).localst);
+                  if assigned(tprocdef(def).parast) then
+                    write_persistent_type_info(tprocdef(def).parast);
+                end;
+            end;
+            { generate always persistent tables for types in the interface so it can
+              be reused in other units and give always the same pointer location. }
+            { Init }
+            if (
+                assigned(def.typesym) and
+                (st.symtabletype=globalsymtable)
+               ) or
+               def.needs_inittable or
+               (ds_init_table_used in def.defstates) then
+              RTTIWriter.write_rtti(def,initrtti);
+            { RTTI }
+            if (
+                  assigned(def.typesym) and
+                  (st.symtabletype=globalsymtable)
+               ) or
+               (ds_rtti_table_used in def.defstates) then
               RTTIWriter.write_rtti(def,fullrtti);
           end;
       end;
diff --git a/compiler/symconst.pas b/compiler/symconst.pas
index d364355135..8710c8aff4 100644
--- a/compiler/symconst.pas
+++ b/compiler/symconst.pas
@@ -142,12 +142,6 @@ type
 
   { flags for a definition }
   tdefoption=(df_none,
-    { init data has been generated }
-    df_has_inittable,
-    { rtti data has been generated }
-    df_has_rttitable,
-    { dwarf debug info has been generated }
-    df_has_dwarf_dbg_info,
     { type is unique, i.e. declared with type = type <tdef>; }
     df_unique,
     { type is a generic }
@@ -159,6 +153,17 @@ type
   );
   tdefoptions=set of tdefoption;
 
+  tdefstate=(ds_none,
+    ds_vmt_written,
+    ds_rtti_table_used,
+    ds_init_table_used,
+    ds_rtti_table_written,
+    ds_init_table_written,
+    ds_dwarf_dbg_info_used,
+    ds_dwarf_dbg_info_written
+  );
+  tdefstates=set of tdefstate;
+
   { tsymlist entry types }
   tsltype = (sl_none,
     sl_load,
@@ -305,8 +310,7 @@ type
     oo_has_msgstr,
     oo_has_msgint,
     oo_can_have_published,{ the class has rtti, i.e. you can publish properties }
-    oo_has_default_property,
-    oo_vmt_written
+    oo_has_default_property
   );
   tobjectoptions=set of tobjectoption;
 
diff --git a/compiler/symdef.pas b/compiler/symdef.pas
index 06373729f5..3eb1823b45 100644
--- a/compiler/symdef.pas
+++ b/compiler/symdef.pas
@@ -227,6 +227,7 @@ interface
           objectoptions  : tobjectoptions;
           { to be able to have a variable vmt position }
           { and no vmt field for objects without virtuals }
+          vmtentries     : TFPObjectList;
           vmt_offset     : longint;
           writing_class_record_dbginfo : boolean;
           objecttype     : tobjecttyp;
@@ -919,9 +920,15 @@ implementation
         prefix : string[4];
       begin
         if rt=fullrtti then
-          prefix:='RTTI'
+          begin
+            prefix:='RTTI';
+            include(defstates,ds_rtti_table_used);
+          end
         else
-          prefix:='INIT';
+          begin
+            prefix:='INIT';
+            include(defstates,ds_init_table_used);
+          end;
         if assigned(typesym) and
            (owner.symtabletype in [staticsymtable,globalsymtable]) then
           result:=make_mangledname(prefix,owner,typesym.name)
@@ -2151,7 +2158,8 @@ implementation
 
     constructor tarraydef.create_from_pointer(def:tdef);
       begin
-         self.create(0,$7fffffff,s32inttype);
+         { use -1 so that the elecount will not overflow }
+         self.create(0,$7fffffff-1,s32inttype);
          arrayoptions:=[ado_IsConvertedPointer];
          setelementdef(def);
       end;
@@ -3560,6 +3568,7 @@ implementation
         childof:=nil;
         symtable:=tObjectSymtable.create(self,n,current_settings.packrecords);
         { create space for vmt !! }
+        vmtentries:=nil;
         vmt_offset:=0;
         lastvtableindex:=0;
         set_parent(c);
@@ -3593,6 +3602,7 @@ implementation
          tObjectSymtable(symtable).fieldalignment:=ppufile.getbyte;
          tObjectSymtable(symtable).recordalignment:=ppufile.getbyte;
          vmt_offset:=ppufile.getlongint;
+         vmtentries:=nil;
          ppufile.getderef(childofderef);
          ppufile.getsmallset(objectoptions);
 
@@ -3658,6 +3668,11 @@ implementation
              dispose(iidguid);
              iidguid:=nil;
            end;
+         if assigned(vmtentries) then
+           begin
+             vmtentries.free;
+             vmtentries:=nil;
+           end;
          inherited destroy;
       end;
 
@@ -3687,6 +3702,11 @@ implementation
             for i:=0 to ImplementedInterfaces.count-1 do
               tobjectdef(result).ImplementedInterfaces.Add(TImplementedInterface(ImplementedInterfaces[i]).Getcopy);
           end;
+        if assigned(vmtentries) then
+          begin
+            tobjectdef(result).vmtentries:=TFPobjectList.Create(false);
+            tobjectdef(result).vmtentries.Assign(vmtentries);
+          end;
       end;
 
 
diff --git a/compiler/symtype.pas b/compiler/symtype.pas
index 75161b4ef3..2557d1d588 100644
--- a/compiler/symtype.pas
+++ b/compiler/symtype.pas
@@ -60,8 +60,9 @@ interface
          dwarf_lab : tasmsymbol;
          { stabs debugging }
          stab_number : word;
-         dbg_state  : tdefdbgstatus;
-         defoptions : tdefoptions;
+         dbg_state   : tdefdbgstatus;
+         defoptions  : tdefoptions;
+         defstates   : tdefstates;
          constructor create(dt:tdeftyp);
          procedure buildderef;virtual;abstract;
          procedure buildderefimpl;virtual;abstract;
@@ -193,7 +194,7 @@ interface
        current_object_option : tsymoptions = [sp_public];
 
     function  FindUnitSymtable(st:TSymtable):TSymtable;
-    
+
 
 implementation
 
diff --git a/compiler/utils/ppudump.pp b/compiler/utils/ppudump.pp
index 9cfcd053e8..1b79c2cf54 100644
--- a/compiler/utils/ppudump.pp
+++ b/compiler/utils/ppudump.pp
@@ -741,35 +741,54 @@ end;
 
 procedure readcommondef(const s:string);
 type
+  { flags for a definition }
   tdefoption=(df_none,
-    { init data has been generated }
-    df_has_inittable,
-    { rtti data has been generated }
-    df_has_rttitable,
-    { dwarf debug info has been generated }
-    df_has_dwarf_dbg_info,
     { type is unique, i.e. declared with type = type <tdef>; }
     df_unique,
     { type is a generic }
     df_generic,
     { type is a specialization of a generic type }
-    df_specialization
+    df_specialization,
+    { type is deleted does not to be stored in ppu }
+    df_deleted
   );
   tdefoptions=set of tdefoption;
+
+  tdefstate=(ds_none,
+    ds_vmt_written,
+    ds_rtti_table_used,
+    ds_init_table_used,
+    ds_rtti_table_written,
+    ds_init_table_written,
+    ds_dwarf_dbg_info_used,
+    ds_dwarf_dbg_info_written
+  );
+  tdefstates=set of tdefstate;
   tdefopt=record
     mask : tdefoption;
     str  : string[30];
   end;
+  tdefstateinfo=record
+    mask : tdefstate;
+    str  : string[30];
+  end;
 const
-  defopts=6;
+  defopts=3;
   defopt : array[1..defopts] of tdefopt=(
-     (mask:df_has_inittable;  str:'InitTable'),
-     (mask:df_has_rttitable;  str:'RTTITable'),
-     (mask:df_has_dwarf_dbg_info;  str:'Dwarf DbgInfo'),
      (mask:df_unique;         str:'Unique Type'),
      (mask:df_generic;        str:'Generic'),
      (mask:df_specialization; str:'Specialization')
   );
+  defstateinfos=7;
+  defstate : array[1..defstateinfos] of tdefstateinfo=(
+     (mask:ds_init_table_used;       str:'InitTable Used'),
+     (mask:ds_rtti_table_used;       str:'RTTITable Used'),
+     (mask:ds_init_table_written;    str:'InitTable Written'),
+     (mask:ds_rtti_table_written;    str:'RTTITable Written'),
+     (mask:ds_dwarf_dbg_info_used;   str:'Dwarf DbgInfo Used'),
+     (mask:ds_dwarf_dbg_info_written;str:'Dwarf DbgInfo Written'),
+     (mask:ds_vmt_written;           str:'VMT Written')
+  );
 var
   defoptions : tdefoptions;
   i      : longint;