From 3d6f6f214c910e5a334e4a9b0bdfb6a1caf961f7 Mon Sep 17 00:00:00 2001 From: Alexander Corrado Date: Thu, 11 Aug 2011 02:51:33 -0400 Subject: [PATCH] Correctly adjust vtable indexes to account for removed duplicates (see commit ec4699b for explanation of problem) --- src/Mono.Cxxi/Abi/Impl/ItaniumTypeInfo.cs | 6 ++++-- src/Mono.Cxxi/CppTypeInfo.cs | 15 ++++++++++++--- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/Mono.Cxxi/Abi/Impl/ItaniumTypeInfo.cs b/src/Mono.Cxxi/Abi/Impl/ItaniumTypeInfo.cs index a4a09424..aaa5dcfd 100644 --- a/src/Mono.Cxxi/Abi/Impl/ItaniumTypeInfo.cs +++ b/src/Mono.Cxxi/Abi/Impl/ItaniumTypeInfo.cs @@ -65,15 +65,17 @@ namespace Mono.Cxxi.Abi { base.AddBase (baseType, addVTable); } */ - protected override bool OnVTableDuplicate (ref int iter, PInvokeSignature sig, PInvokeSignature dup) + protected override bool OnVTableDuplicate (ref int iter, ref int adj, PInvokeSignature sig, PInvokeSignature dup) { - var isOverride = base.OnVTableDuplicate (ref iter, sig, dup); + var isOverride = base.OnVTableDuplicate (ref iter, ref adj, sig, dup); if (isOverride && sig.Type == MethodType.NativeDtor) { // also remove that pesky extra dtor virtual_methods.RemoveAt (iter + 1); vt_overrides.Remove (1); vt_delegate_types.Remove (1); + vtable_index_adjustments.Add (0); + adj--; return true; } diff --git a/src/Mono.Cxxi/CppTypeInfo.cs b/src/Mono.Cxxi/CppTypeInfo.cs index 98723164..b7d8941a 100644 --- a/src/Mono.Cxxi/CppTypeInfo.cs +++ b/src/Mono.Cxxi/CppTypeInfo.cs @@ -82,6 +82,8 @@ namespace Mono.Cxxi { protected LazyGeneratedList vt_overrides; protected List base_classes; + protected List vtable_index_adjustments; + protected int native_size_without_padding; // <- this refers to the size of all the fields declared in the nativeLayout struct protected int field_offset_padding_without_vtptr; protected int gchandle_offset_delta; @@ -110,6 +112,8 @@ namespace Mono.Cxxi { vt_overrides = new LazyGeneratedList (virtual_methods.Count, i => Library.Abi.GetManagedOverrideTrampoline (this, i)); VTableOverrides = new ReadOnlyCollection (vt_overrides); + vtable_index_adjustments = new List (virtual_methods.Count); + if (nativeLayout != null) native_size_without_padding = nativeLayout.GetFields ().Any ()? Marshal.SizeOf (nativeLayout) : 0; } @@ -341,29 +345,33 @@ namespace Mono.Cxxi { public virtual T GetAdjustedVirtualCall (CppInstancePtr instance, int derivedVirtualMethodIndex) where T : class /* Delegate */ { - return VTable.GetVirtualCallDelegate (instance, BaseVTableSlots + derivedVirtualMethodIndex); + var base_adjusted = BaseVTableSlots + derivedVirtualMethodIndex; + return VTable.GetVirtualCallDelegate (instance, base_adjusted + vtable_index_adjustments [base_adjusted]); } protected virtual void RemoveVTableDuplicates () { // check that any virtual methods overridden in a subclass are only included once var vsignatures = new Dictionary (MethodSignature.EqualityComparer); + var adjustment = 0; for (int i = 0; i < virtual_methods.Count; i++) { + vtable_index_adjustments.Add (adjustment); + var sig = virtual_methods [i]; if (sig == null) continue; PInvokeSignature existing; if (vsignatures.TryGetValue (sig, out existing)) { - OnVTableDuplicate (ref i, sig, existing); + OnVTableDuplicate (ref i, ref adjustment, sig, existing); } else { vsignatures.Add (sig, sig); } } } - protected virtual bool OnVTableDuplicate (ref int iter, PInvokeSignature sig, PInvokeSignature dup) + protected virtual bool OnVTableDuplicate (ref int iter, ref int adj, PInvokeSignature sig, PInvokeSignature dup) { // This predicate ensures that duplicates are only removed // if declared in different classes (i.e. overridden methods). @@ -373,6 +381,7 @@ namespace Mono.Cxxi { virtual_methods.RemoveAt (iter--); vt_overrides.Remove (1); vt_delegate_types.Remove (1); + adj--; return true; }