Skip to content

Commit 0922217

Browse files
ddobrevtritao
authored andcommitted
Made the original virtual tables static too
Virtual tables are the same object per class in C++. Signed-off-by: Dimitar Dobrev <[email protected]>
1 parent 0da9c46 commit 0922217

File tree

1 file changed

+64
-70
lines changed

1 file changed

+64
-70
lines changed

src/Generator/Generators/CSharp/CSharpSources.cs

Lines changed: 64 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)