@@ -438,7 +438,6 @@ public override bool VisitClassDecl(Class @class)
438438 var dict = $@ "global::System.Collections.Concurrent.ConcurrentDictionary<IntPtr, {
439439 printedClass } >" ;
440440 WriteLine ( "internal static readonly {0} NativeToManagedMap = new {0}();" , dict ) ;
441- WriteLine ( "protected internal void*[] __OriginalVTables;" ) ;
442441 }
443442 PopBlock ( NewLineKind . BeforeNextBlock ) ;
444443 }
@@ -1521,6 +1520,11 @@ public void GenerateVTable(Class @class)
15211520 if ( wrappedEntries . Any ( e => e . Method . IsDestructor ) )
15221521 WriteLine ( "private static void*[] __ManagedVTablesDtorOnly;" ) ;
15231522 WriteLine ( "private static void*[] _Thunks;" ) ;
1523+ WriteLine ( "private static void*[] __originalVTables;" ) ;
1524+ bool hasDynamicBase = @class . NeedsBase && @class . BaseClass . IsDynamic ;
1525+ Write ( $@ "protected internal { ( hasDynamicBase ? "override" : "virtual"
1526+ ) } void*[] __OriginalVTables => __originalVTables ?? " ) ;
1527+ SaveOriginalVTablePointers ( @class ) ;
15241528 NewLine ( ) ;
15251529
15261530 GenerateVTableClassSetup ( @class , wrappedEntries ) ;
@@ -1535,21 +1539,13 @@ private void GenerateVTableClassSetup(Class @class, IList<VTableComponent> wrapp
15351539 WriteLine ( "private void SetupVTables(bool {0} = false)" , destructorOnly ) ;
15361540 WriteOpenBraceAndIndent ( ) ;
15371541
1538- WriteLine ( "if (__OriginalVTables != null)" ) ;
1539- WriteLineIndent ( "return;" ) ;
1540-
1541- SaveOriginalVTablePointers ( @class ) ;
1542-
1543- NewLine ( ) ;
1544-
15451542 var hasVirtualDtor = wrappedEntries . Any ( e => e . Method . IsDestructor ) ;
15461543 if ( ! hasVirtualDtor )
15471544 {
15481545 WriteLine ( "if ({0})" , destructorOnly ) ;
15491546 WriteLineIndent ( "return;" ) ;
15501547 }
15511548
1552- // Get the _Thunks
15531549 WriteLine ( "if (_Thunks == null)" ) ;
15541550 WriteOpenBraceAndIndent ( ) ;
15551551 WriteLine ( "_Thunks = new void*[{0}];" , wrappedEntries . Count ) ;
@@ -1567,30 +1563,34 @@ private void GenerateVTableClassSetup(Class @class, IList<VTableComponent> wrapp
15671563 WriteLine ( "_Thunks[{0}] = Marshal.GetFunctionPointerForDelegate({1}).ToPointer();" ,
15681564 i , instance ) ;
15691565 }
1570- UnindentAndWriteCloseBrace ( ) ;
15711566
15721567 NewLine ( ) ;
15731568
15741569 if ( hasVirtualDtor )
1575- {
1576- WriteLine ( "if ({0})" , destructorOnly ) ;
1577- WriteOpenBraceAndIndent ( ) ;
1578- WriteLine ( "if (__ManagedVTablesDtorOnly == null)" ) ;
1579- WriteOpenBraceAndIndent ( ) ;
1570+ AllocateNewVTables ( @class , wrappedEntries , destructorOnly : true ) ;
15801571
1581- AllocateNewVTables ( @class , wrappedEntries , true ) ;
1572+ AllocateNewVTables ( @class , wrappedEntries , destructorOnly : false ) ;
15821573
1574+ Write ( "__originalVTables = " ) ;
1575+ SaveOriginalVTablePointers ( @class ) ;
1576+ UnindentAndWriteCloseBrace ( ) ;
1577+
1578+ NewLine ( ) ;
1579+ if ( hasVirtualDtor )
1580+ {
1581+ WriteLine ( $ "if ({ destructorOnly } )") ;
1582+ WriteOpenBraceAndIndent ( ) ;
1583+ AssignNewVTableEntries ( @class , "__ManagedVTablesDtorOnly" ) ;
15831584 UnindentAndWriteCloseBrace ( ) ;
15841585 WriteLine ( "else" ) ;
15851586 WriteOpenBraceAndIndent ( ) ;
1586- }
1587- WriteLine ( "if (__ManagedVTables == null)" ) ;
1588- WriteOpenBraceAndIndent ( ) ;
1589-
1590- AllocateNewVTables ( @class , wrappedEntries , false ) ;
1591-
1592- if ( hasVirtualDtor )
1587+ AssignNewVTableEntries ( @class , "__ManagedVTables" ) ;
15931588 UnindentAndWriteCloseBrace ( ) ;
1589+ }
1590+ else
1591+ {
1592+ AssignNewVTableEntries ( @class , "__ManagedVTables" ) ;
1593+ }
15941594
15951595 UnindentAndWriteCloseBrace ( ) ;
15961596 NewLine ( ) ;
@@ -1603,73 +1603,76 @@ private void AllocateNewVTables(Class @class, IList<VTableComponent> wrappedEntr
16031603 AllocateNewVTablesMS ( @class , wrappedEntries , destructorOnly ) ;
16041604 else
16051605 AllocateNewVTablesItanium ( @class , wrappedEntries , destructorOnly ) ;
1606+
1607+ NewLine ( ) ;
1608+ }
1609+
1610+ private void AssignNewVTableEntries ( Class @class , string table )
1611+ {
1612+ int size = Context . ParserOptions . IsMicrosoftAbi ?
1613+ @class . Layout . VTablePointers . Count : 1 ;
1614+
1615+ for ( int i = 0 ; i < size ; i ++ )
1616+ {
1617+ var offset = @class . Layout . VTablePointers [ i ] . Offset ;
1618+ WriteLine ( $ "*(void**) ({ Helpers . InstanceIdentifier } + { offset } ) = { table } [{ i } ];") ;
1619+ }
16061620 }
16071621
16081622 private void SaveOriginalVTablePointers ( Class @class )
16091623 {
16101624 if ( @class . IsDependent )
16111625 @class = @class . Specializations [ 0 ] ;
16121626
1627+ Write ( "new void*[] { " ) ;
1628+
16131629 if ( Context . ParserOptions . IsMicrosoftAbi )
1614- WriteLine ( "__OriginalVTables = new void*[] {{ {0} }};" ,
1615- string . Join ( ", " ,
1616- @class . Layout . VTablePointers . Select ( v =>
1617- $ "*(void**) ({ Helpers . InstanceIdentifier } + { v . Offset } )") ) ) ;
1630+ Write ( string . Join ( ", " , @class . Layout . VTablePointers . Select (
1631+ v => $ "*(void**) ({ Helpers . InstanceIdentifier } + { v . Offset } )") ) ) ;
16181632 else
1619- WriteLine (
1620- $@ "__OriginalVTables = new void*[] {{ *(void**) ({
1621- Helpers . InstanceIdentifier } + { @class . Layout . VTablePointers [ 0 ] . Offset } ) }};" ) ;
1633+ Write ( $@ "*(void**) ({ Helpers . InstanceIdentifier } + {
1634+ @class . Layout . VTablePointers [ 0 ] . Offset } )" ) ;
1635+
1636+ WriteLine ( " };" ) ;
16221637 }
16231638
16241639 private void AllocateNewVTablesMS ( Class @class , IList < VTableComponent > wrappedEntries ,
16251640 bool destructorOnly )
16261641 {
16271642 var managedVTables = destructorOnly ? "__ManagedVTablesDtorOnly" : "__ManagedVTables" ;
1628- WriteLine ( "{0 } = new void*[{1}];" , managedVTables , @class . Layout . VFTables . Count ) ;
1643+ WriteLine ( $ " { managedVTables } = new void*[{ @class . Layout . VFTables . Count } ];" ) ;
16291644
16301645 for ( int i = 0 ; i < @class . Layout . VFTables . Count ; i ++ )
16311646 {
1632- var vfptr = @class . Layout . VFTables [ i ] ;
1633- var size = vfptr . Layout . Components . Count ;
1634- WriteLine ( "var vfptr{0} = Marshal.AllocHGlobal({1} * {2});" ,
1635- i , size , Context . TargetInfo . PointerWidth / 8 ) ;
1636- WriteLine ( "{0}[{1}] = vfptr{1}.ToPointer();" , managedVTables , i ) ;
1647+ VFTableInfo vftable = @class . Layout . VFTables [ i ] ;
1648+ int size = vftable . Layout . Components . Count ;
1649+ string vfptr = $ "vfptr{ ( destructorOnly ? "_dtor" : string . Empty ) } { i } ";
1650+ WriteLine ( $@ "var { vfptr } = Marshal.AllocHGlobal({ size } * {
1651+ Context . TargetInfo . PointerWidth / 8 } );" ) ;
1652+ WriteLine ( $ "{ managedVTables } [{ i } ] = { vfptr } .ToPointer();") ;
16371653
1638- AllocateNewVTableEntries ( vfptr . Layout . Components , wrappedEntries ,
1654+ AllocateNewVTableEntries ( vftable . Layout . Components , wrappedEntries ,
16391655 @class . Layout . VTablePointers [ i ] . Offset , i , destructorOnly ) ;
16401656 }
1641-
1642- UnindentAndWriteCloseBrace ( ) ;
1643- NewLine ( ) ;
1644-
1645- for ( int i = 0 ; i < @class . Layout . VTablePointers . Count ; i ++ )
1646- {
1647- var offset = @class . Layout . VTablePointers [ i ] . Offset ;
1648- WriteLine ( $ "*(void**) ({ Helpers . InstanceIdentifier } + { offset } ) = { managedVTables } [{ i } ];") ;
1649- }
16501657 }
16511658
16521659 private void AllocateNewVTablesItanium ( Class @class , IList < VTableComponent > wrappedEntries ,
16531660 bool destructorOnly )
16541661 {
16551662 var managedVTables = destructorOnly ? "__ManagedVTablesDtorOnly" : "__ManagedVTables" ;
1656- WriteLine ( "{0 } = new void*[1];", managedVTables ) ;
1663+ WriteLine ( $ " { managedVTables } = new void*[1];") ;
16571664
1658- var size = @class . Layout . Layout . Components . Count ;
1659- var pointerSize = Context . TargetInfo . PointerWidth / 8 ;
1660- WriteLine ( "var vtptr = Marshal.AllocHGlobal({0} * {1});" , size , pointerSize ) ;
1665+ string suffix = destructorOnly ? "_dtor" : string . Empty ;
1666+ int size = @class . Layout . Layout . Components . Count ;
1667+ uint pointerSize = Context . TargetInfo . PointerWidth / 8 ;
1668+ WriteLine ( $ "var vtptr{ suffix } = Marshal.AllocHGlobal({ size } * { pointerSize } );") ;
16611669
1662- WriteLine ( "var vfptr0 = vtptr + {0} * {1};" , VTables . ItaniumOffsetToTopAndRTTI , pointerSize ) ;
1663- WriteLine ( "{0}[0] = vfptr0.ToPointer();" , managedVTables ) ;
1670+ WriteLine ( $@ "var vfptr{ suffix } 0 = vtptr{ suffix } + {
1671+ VTables . ItaniumOffsetToTopAndRTTI } * { pointerSize } ;" ) ;
1672+ WriteLine ( $ "{ managedVTables } [0] = vfptr{ suffix } 0.ToPointer();") ;
16641673
16651674 AllocateNewVTableEntries ( @class . Layout . Layout . Components ,
16661675 wrappedEntries , @class . Layout . VTablePointers [ 0 ] . Offset , 0 , destructorOnly ) ;
1667-
1668- UnindentAndWriteCloseBrace ( ) ;
1669- NewLine ( ) ;
1670-
1671- var offset = @class . Layout . VTablePointers [ 0 ] . Offset ;
1672- WriteLine ( $ "*(void**) ({ Helpers . InstanceIdentifier } + { offset } ) = { managedVTables } [0];") ;
16731676 }
16741677
16751678 private void AllocateNewVTableEntries ( IList < VTableComponent > entries ,
@@ -1684,7 +1687,8 @@ private void AllocateNewVTableEntries(IList<VTableComponent> entries,
16841687
16851688 var nativeVftableEntry = $@ "*(void**) (new IntPtr(*(void**) {
16861689 Helpers . InstanceIdentifier } ) + { vptrOffset } + { offset } )" ;
1687- var managedVftableEntry = $ "*(void**) (vfptr{ tableIndex } + { offset } )";
1690+ string vfptr = $ "vfptr{ ( destructorOnly ? "_dtor" : string . Empty ) } { tableIndex } ";
1691+ var managedVftableEntry = $ "*(void**) ({ vfptr } + { offset } )";
16881692
16891693 if ( ( entry . Kind == VTableComponentKind . FunctionPointer ||
16901694 entry . Kind == VTableComponentKind . DeletingDtorPointer ) &&
@@ -2207,17 +2211,7 @@ private void GenerateNativeConstructor(Class @class)
22072211 var setupVTables = ! @class . IsAbstractImpl && hasVTables && dtor ? . IsVirtual == true ;
22082212 if ( setupVTables )
22092213 {
2210- WriteLine ( "if (skipVTables)" ) ;
2211- Indent ( ) ;
2212- }
2213-
2214- if ( @class . IsAbstractImpl || hasVTables )
2215- SaveOriginalVTablePointers ( @class ) ;
2216-
2217- if ( setupVTables )
2218- {
2219- Unindent ( ) ;
2220- WriteLine ( "else" ) ;
2214+ WriteLine ( "if (!skipVTables)" ) ;
22212215 Indent ( ) ;
22222216 GenerateVTableClassSetupCall ( @class , destructorOnly : true ) ;
22232217 Unindent ( ) ;
0 commit comments