From 2169aac55937a40e4155deccfd1cbc706c10ee76 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Tue, 23 Mar 2021 15:46:00 -0700 Subject: [PATCH 1/3] When marshalling a layout class, fall-back to dynamically marshalling the type if it doesn't match the static type in the signature. --- src/coreclr/vm/corelib.h | 4 + src/coreclr/vm/ilmarshalers.cpp | 92 ++++++++++++++++++- src/coreclr/vm/ilmarshalers.h | 1 + src/coreclr/vm/metasig.h | 4 + src/coreclr/vm/mlinfo.cpp | 8 ++ .../Interop/LayoutClass/LayoutClassNative.cpp | 24 ++++- .../Interop/LayoutClass/LayoutClassTest.cs | 69 +++++++++++++- 7 files changed, 198 insertions(+), 4 deletions(-) diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h index 3b870b718d1352..34c8b33bb2bdc6 100644 --- a/src/coreclr/vm/corelib.h +++ b/src/coreclr/vm/corelib.h @@ -477,6 +477,10 @@ DEFINE_METHOD(MARSHAL, ALLOC_CO_TASK_MEM, AllocCoTa DEFINE_METHOD(MARSHAL, FREE_CO_TASK_MEM, FreeCoTaskMem, SM_IntPtr_RetVoid) DEFINE_FIELD(MARSHAL, SYSTEM_MAX_DBCS_CHAR_SIZE, SystemMaxDBCSCharSize) +DEFINE_METHOD(MARSHAL, STRUCTURE_TO_PTR, StructureToPtr, SM_Obj_IntPtr_Bool_RetVoid) +DEFINE_METHOD(MARSHAL, PTR_TO_STRUCTURE, PtrToStructure, SM_IntPtr_Obj_RetVoid) +DEFINE_METHOD(MARSHAL, DESTROY_STRUCTURE, DestroyStructure, SM_IntPtr_Type_RetVoid) + DEFINE_CLASS(NATIVELIBRARY, Interop, NativeLibrary) DEFINE_METHOD(NATIVELIBRARY, LOADLIBRARYCALLBACKSTUB, LoadLibraryCallbackStub, SM_Str_AssemblyBase_Bool_UInt_RetIntPtr) diff --git a/src/coreclr/vm/ilmarshalers.cpp b/src/coreclr/vm/ilmarshalers.cpp index 564cc8f10a95ee..13ccc303853071 100644 --- a/src/coreclr/vm/ilmarshalers.cpp +++ b/src/coreclr/vm/ilmarshalers.cpp @@ -2261,7 +2261,22 @@ void ILLayoutClassPtrMarshalerBase::EmitClearNativeTemp(ILCodeStream* pslILEmit) } } +bool ILLayoutClassPtrMarshalerBase::EmitExactTypeCheck(ILCodeStream* pslILEmit, ILCodeLabel* isNotMatchingTypeLabel) +{ + if (m_pargs->m_pMT->IsSealed()) + { + // If the provided type cannot be derived from, then we don't need to emit the type check. + return false; + } + EmitLoadManagedValue(pslILEmit); + pslILEmit->EmitCALL(METHOD__OBJECT__GET_TYPE, 1, 1); + pslILEmit->EmitLDTOKEN(pslILEmit->GetToken(m_pargs->m_pMT)); + pslILEmit->EmitCALL(METHOD__TYPE__GET_TYPE_FROM_HANDLE, 1, 1); + pslILEmit->EmitCALLVIRT(pslILEmit->GetToken(CoreLibBinder::GetMethod(METHOD__OBJECT__EQUALS)), 1, 1); + pslILEmit->EmitBRFALSE(isNotMatchingTypeLabel); + return true; +} void ILLayoutClassPtrMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) { @@ -2278,6 +2293,9 @@ void ILLayoutClassPtrMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* psl pslILEmit->EmitLDC(uNativeSize); pslILEmit->EmitINITBLK(); + ILCodeLabel* isNotMatchingTypeLabel = pslILEmit->NewCodeLabel(); + bool emittedTypeCheck = EmitExactTypeCheck(pslILEmit, isNotMatchingTypeLabel); + MethodDesc* pStructMarshalStub = NDirect::CreateStructMarshalILStub(m_pargs->m_pMT); EmitLoadManagedValue(pslILEmit); @@ -2287,6 +2305,18 @@ void ILLayoutClassPtrMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* psl EmitLoadCleanupWorkList(pslILEmit); pslILEmit->EmitCALL(pslILEmit->GetToken(pStructMarshalStub), 4, 0); + + if (emittedTypeCheck) + { + pslILEmit->EmitBR(pNullRefLabel); + + pslILEmit->EmitLabel(isNotMatchingTypeLabel); + EmitLoadManagedValue(pslILEmit); + EmitLoadNativeValue(pslILEmit); + pslILEmit->EmitLDC(0); + pslILEmit->EmitCALL(METHOD__MARSHAL__STRUCTURE_TO_PTR, 3, 0); + } + pslILEmit->EmitLabel(pNullRefLabel); } @@ -2299,6 +2329,9 @@ void ILLayoutClassPtrMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* psl EmitLoadManagedValue(pslILEmit); pslILEmit->EmitBRFALSE(pNullRefLabel); + ILCodeLabel* isNotMatchingTypeLabel = pslILEmit->NewCodeLabel(); + bool emittedTypeCheck = EmitExactTypeCheck(pslILEmit, isNotMatchingTypeLabel); + MethodDesc* pStructMarshalStub = NDirect::CreateStructMarshalILStub(m_pargs->m_pMT); EmitLoadManagedValue(pslILEmit); @@ -2308,6 +2341,15 @@ void ILLayoutClassPtrMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* psl EmitLoadCleanupWorkList(pslILEmit); pslILEmit->EmitCALL(pslILEmit->GetToken(pStructMarshalStub), 4, 0); + if (emittedTypeCheck) + { + pslILEmit->EmitBR(pNullRefLabel); + + pslILEmit->EmitLabel(isNotMatchingTypeLabel); + EmitLoadNativeValue(pslILEmit); + EmitLoadManagedValue(pslILEmit); + pslILEmit->EmitCALL(METHOD__MARSHAL__PTR_TO_STRUCTURE, 2, 0); + } pslILEmit->EmitLabel(pNullRefLabel); } @@ -2315,6 +2357,10 @@ void ILLayoutClassPtrMarshaler::EmitClearNativeContents(ILCodeStream * pslILEmit { STANDARD_VM_CONTRACT; + ILCodeLabel* isNotMatchingTypeLabel = pslILEmit->NewCodeLabel(); + ILCodeLabel* cleanedUpLabel = pslILEmit->NewCodeLabel(); + bool emittedTypeCheck = EmitExactTypeCheck(pslILEmit, isNotMatchingTypeLabel); + MethodDesc* pStructMarshalStub = NDirect::CreateStructMarshalILStub(m_pargs->m_pMT); EmitLoadManagedValue(pslILEmit); @@ -2324,6 +2370,19 @@ void ILLayoutClassPtrMarshaler::EmitClearNativeContents(ILCodeStream * pslILEmit EmitLoadCleanupWorkList(pslILEmit); pslILEmit->EmitCALL(pslILEmit->GetToken(pStructMarshalStub), 4, 0); + + if (emittedTypeCheck) + { + pslILEmit->EmitBR(cleanedUpLabel); + + pslILEmit->EmitLabel(isNotMatchingTypeLabel); + EmitLoadNativeValue(pslILEmit); + EmitLoadManagedValue(pslILEmit); + pslILEmit->EmitCALL(METHOD__OBJECT__GET_TYPE, 1, 1); + pslILEmit->EmitCALL(METHOD__MARSHAL__DESTROY_STRUCTURE, 2, 0); + } + + pslILEmit->EmitLabel(cleanedUpLabel); } @@ -2338,6 +2397,9 @@ void ILBlittablePtrMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslIL EmitLoadNativeValue(pslILEmit); pslILEmit->EmitBRFALSE(pNullRefLabel); + ILCodeLabel* isNotMatchingTypeLabel = pslILEmit->NewCodeLabel(); + bool emittedTypeCheck = EmitExactTypeCheck(pslILEmit, isNotMatchingTypeLabel); + EmitLoadNativeValue(pslILEmit); // dest EmitLoadManagedValue(pslILEmit); @@ -2346,6 +2408,17 @@ void ILBlittablePtrMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslIL pslILEmit->EmitLDC(uNativeSize); // size pslILEmit->EmitCPBLK(); + + if (emittedTypeCheck) + { + pslILEmit->EmitBR(pNullRefLabel); + + pslILEmit->EmitLabel(isNotMatchingTypeLabel); + EmitLoadManagedValue(pslILEmit); + EmitLoadNativeValue(pslILEmit); + pslILEmit->EmitLDC(0); + pslILEmit->EmitCALL(METHOD__MARSHAL__STRUCTURE_TO_PTR, 3, 0); + } pslILEmit->EmitLabel(pNullRefLabel); } @@ -2357,6 +2430,9 @@ void ILBlittablePtrMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslIL UINT uNativeSize = m_pargs->m_pMT->GetNativeSize(); int fieldDef = pslILEmit->GetToken(CoreLibBinder::GetField(FIELD__RAW_DATA__DATA)); + ILCodeLabel* isNotMatchingTypeLabel = pslILEmit->NewCodeLabel(); + bool emittedTypeCheck = EmitExactTypeCheck(pslILEmit, isNotMatchingTypeLabel); + EmitLoadManagedValue(pslILEmit); pslILEmit->EmitBRFALSE(pNullRefLabel); @@ -2368,12 +2444,26 @@ void ILBlittablePtrMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslIL pslILEmit->EmitLDC(uNativeSize); // size pslILEmit->EmitCPBLK(); + + if (emittedTypeCheck) + { + pslILEmit->EmitBR(pNullRefLabel); + + pslILEmit->EmitLabel(isNotMatchingTypeLabel); + EmitLoadNativeValue(pslILEmit); + EmitLoadManagedValue(pslILEmit); + pslILEmit->EmitCALL(METHOD__MARSHAL__PTR_TO_STRUCTURE, 2, 0); + } + pslILEmit->EmitLabel(pNullRefLabel); } bool ILBlittablePtrMarshaler::CanMarshalViaPinning() { - return IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags) && !IsFieldMarshal(m_dwMarshalFlags); + return IsCLRToNative(m_dwMarshalFlags) && + !IsByref(m_dwMarshalFlags) && + !IsFieldMarshal(m_dwMarshalFlags) && + m_pargs->m_pMT->IsSealed(); // We can't marshal via pinning if we might need to marshal differently at runtime. } void ILBlittablePtrMarshaler::EmitMarshalViaPinning(ILCodeStream* pslILEmit) diff --git a/src/coreclr/vm/ilmarshalers.h b/src/coreclr/vm/ilmarshalers.h index 12a1824ca7ba31..ba07cd5b55c175 100644 --- a/src/coreclr/vm/ilmarshalers.h +++ b/src/coreclr/vm/ilmarshalers.h @@ -2791,6 +2791,7 @@ class ILLayoutClassPtrMarshalerBase : public ILMarshaler bool NeedsClearNative() override; void EmitClearNative(ILCodeStream* pslILEmit) override; void EmitClearNativeTemp(ILCodeStream* pslILEmit) override; + bool EmitExactTypeCheck(ILCodeStream* pslILEmit, ILCodeLabel* isNotMatchingTypeLabel); }; class ILLayoutClassPtrMarshaler : public ILLayoutClassPtrMarshalerBase diff --git a/src/coreclr/vm/metasig.h b/src/coreclr/vm/metasig.h index 84948f65242cdb..a8f5b28aca14d1 100644 --- a/src/coreclr/vm/metasig.h +++ b/src/coreclr/vm/metasig.h @@ -592,6 +592,10 @@ DEFINE_METASIG_T(SM(Array_Int_Array_Int_Int_RetVoid, C(ARRAY) i C(ARRAY) i i, v) DEFINE_METASIG_T(SM(Array_Int_Obj_RetVoid, C(ARRAY) i j, v)) DEFINE_METASIG_T(SM(Array_Int_PtrVoid_RetRefObj, C(ARRAY) i P(v), r(j))) +DEFINE_METASIG(SM(Obj_IntPtr_Bool_RetVoid, j I F, v)) +DEFINE_METASIG(SM(IntPtr_Obj_RetVoid, I j, v)) +DEFINE_METASIG_T(SM(IntPtr_Type_RetVoid, I C(TYPE), v)) + // Undefine macros in case we include the file again in the compilation unit #undef DEFINE_METASIG diff --git a/src/coreclr/vm/mlinfo.cpp b/src/coreclr/vm/mlinfo.cpp index 71788db9efd5d9..f77a07d054d78a 100644 --- a/src/coreclr/vm/mlinfo.cpp +++ b/src/coreclr/vm/mlinfo.cpp @@ -1133,6 +1133,8 @@ MarshalInfo::MarshalInfo(Module* pModule, CorElementType corElemType = ELEMENT_TYPE_END; m_pMT = NULL; m_pMD = pMD; + // For backward compatibility reasons, some marshalers imply [In, Out] behavior when marked as [Out]. + BOOL outImpliesInOut = FALSE; #ifdef FEATURE_COMINTEROP m_fDispItf = FALSE; @@ -1877,6 +1879,7 @@ MarshalInfo::MarshalInfo(Module* pModule, } m_type = IsFieldScenario() ? MARSHAL_TYPE_BLITTABLE_LAYOUTCLASS : MARSHAL_TYPE_BLITTABLEPTR; m_args.m_pMT = m_pMT; + outImpliesInOut = TRUE; } else if (m_pMT->HasLayout()) { @@ -2386,7 +2389,12 @@ MarshalInfo::MarshalInfo(Module* pModule, m_in = TRUE; m_out = FALSE; } + } + // For marshalers that expect [Out] behavior to match [In, Out] behavior, update that here. + if (m_out && outImpliesInOut) + { + m_in = TRUE; } } diff --git a/src/tests/Interop/LayoutClass/LayoutClassNative.cpp b/src/tests/Interop/LayoutClass/LayoutClassNative.cpp index 0bf0af967f0637..808bc8ffc95a89 100644 --- a/src/tests/Interop/LayoutClass/LayoutClassNative.cpp +++ b/src/tests/Interop/LayoutClass/LayoutClassNative.cpp @@ -5,7 +5,16 @@ #include typedef void *voidPtr; - + +struct EmptyBase +{ +}; + +struct DerivedSeqClass : public EmptyBase +{ + int a; +}; + struct SeqClass { int a; @@ -14,7 +23,7 @@ struct SeqClass }; struct ExpClass -{ +{ int a; int padding; //padding needs to be added here as we have added 8 byte offset. union @@ -46,6 +55,17 @@ DLL_EXPORT BOOL STDMETHODCALLTYPE SimpleSeqLayoutClassByRef(SeqClass* p) return TRUE; } +extern "C" +DLL_EXPORT BOOL STDMETHODCALLTYPE DerivedSeqLayoutClassByRef(EmptyBase* p, int expected) +{ + if(((DerivedSeqClass*)p)->a != expected) + { + printf("FAIL: p->a=%d, expected %d\n", ((DerivedSeqClass*)p)->a, expected); + return FALSE; + } + return TRUE; +} + extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE SimpleExpLayoutClassByRef(ExpClass* p) { diff --git a/src/tests/Interop/LayoutClass/LayoutClassTest.cs b/src/tests/Interop/LayoutClass/LayoutClassTest.cs index 32ecfcb3548f93..a3cf72c4c432e5 100644 --- a/src/tests/Interop/LayoutClass/LayoutClassTest.cs +++ b/src/tests/Interop/LayoutClass/LayoutClassTest.cs @@ -8,7 +8,23 @@ namespace PInvokeTests { [StructLayout(LayoutKind.Sequential)] - public class SeqClass + public class EmptyBase + { + } + + [StructLayout(LayoutKind.Sequential)] + public class SeqDerivedClass : EmptyBase + { + public int a; + + public SeqDerivedClass(int _a) + { + a = _a; + } + } + + [StructLayout(LayoutKind.Sequential)] + public sealed class SeqClass { public int a; public bool b; @@ -78,6 +94,17 @@ public Blittable(int _a) } } + [StructLayout(LayoutKind.Sequential)] + public sealed class SealedBlittable + { + public int a; + + public SealedBlittable(int _a) + { + a = _a; + } + } + public struct NestedLayout { public SeqClass value; @@ -99,6 +126,9 @@ class StructureTests [DllImport("LayoutClassNative")] private static extern bool SimpleSeqLayoutClassByRef(SeqClass p); + [DllImport("LayoutClassNative")] + private static extern bool DerivedSeqLayoutClassByRef(EmptyBase p, int expected); + [DllImport("LayoutClassNative")] private static extern bool SimpleExpLayoutClassByRef(ExpClass p); @@ -108,6 +138,12 @@ class StructureTests [DllImport("LayoutClassNative")] private static extern bool SimpleBlittableSeqLayoutClassByOutAttr([Out] Blittable p); + [DllImport("LayoutClassNative")] + private static extern bool SimpleBlittableSeqLayoutClassByRef(SealedBlittable p); + + [DllImport("LayoutClassNative")] + private static extern bool SimpleBlittableSeqLayoutClassByOutAttr([Out] SealedBlittable p); + [DllImport("LayoutClassNative")] private static extern bool SimpleNestedLayoutClassByValue(NestedLayout p); @@ -123,6 +159,15 @@ public static void SequentialClass() Assert.IsTrue(SimpleSeqLayoutClassByRef(p)); } + public static void DerivedClassWithEmptyBase() + { + Console.WriteLine($"Running {nameof(DerivedClassWithEmptyBase)}..."); + + string s = "before"; + var p = new SeqDerivedClass(42); + Assert.IsTrue(DerivedSeqLayoutClassByRef(p, 42)); + } + public static void ExplicitClass() { Console.WriteLine($"Running {nameof(ExplicitClass)}..."); @@ -150,6 +195,25 @@ public static void BlittableClassByOutAttr() Assert.AreEqual(expected, p.a); } + public static void SealedBlittableClass() + { + Console.WriteLine($"Running {nameof(SealedBlittableClass)}..."); + + SealedBlittable p = new SealedBlittable(10); + Assert.IsTrue(SimpleBlittableSeqLayoutClassByRef(p)); + } + + public static void SealedBlittableClassByOutAttr() + { + Console.WriteLine($"Running {nameof(SealedBlittableClassByOutAttr)}..."); + + int a = 10; + int expected = a + 1; + SealedBlittable p = new SealedBlittable(a); + Assert.IsTrue(SimpleBlittableSeqLayoutClassByOutAttr(p)); + Assert.AreEqual(expected, p.a); + } + public static void NestedLayoutClass() { Console.WriteLine($"Running {nameof(NestedLayoutClass)}..."); @@ -175,9 +239,12 @@ public static int Main(string[] argv) try { SequentialClass(); + DerivedClassWithEmptyBase(); ExplicitClass(); BlittableClass(); + SealedBlittableClass(); BlittableClassByOutAttr(); + SealedBlittableClassByOutAttr(); NestedLayoutClass(); RecursiveNativeLayout(); } From b31169d50d92e12b6d01d949e85e3e9d122d41a9 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Tue, 23 Mar 2021 16:28:37 -0700 Subject: [PATCH 2/3] Allocate the correct amount of space for the native data based on the runtime type. --- src/coreclr/vm/corelib.h | 1 + src/coreclr/vm/ilmarshalers.cpp | 38 +++++++++++++++++++++++++++++++-- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h index 34c8b33bb2bdc6..a07cd457fa4143 100644 --- a/src/coreclr/vm/corelib.h +++ b/src/coreclr/vm/corelib.h @@ -480,6 +480,7 @@ DEFINE_FIELD(MARSHAL, SYSTEM_MAX_DBCS_CHAR_SIZE, SystemMax DEFINE_METHOD(MARSHAL, STRUCTURE_TO_PTR, StructureToPtr, SM_Obj_IntPtr_Bool_RetVoid) DEFINE_METHOD(MARSHAL, PTR_TO_STRUCTURE, PtrToStructure, SM_IntPtr_Obj_RetVoid) DEFINE_METHOD(MARSHAL, DESTROY_STRUCTURE, DestroyStructure, SM_IntPtr_Type_RetVoid) +DEFINE_METHOD(MARSHAL, SIZEOF_TYPE, SizeOf, SM_Type_RetInt) DEFINE_CLASS(NATIVELIBRARY, Interop, NativeLibrary) DEFINE_METHOD(NATIVELIBRARY, LOADLIBRARYCALLBACKSTUB, LoadLibraryCallbackStub, SM_Str_AssemblyBase_Bool_UInt_RetIntPtr) diff --git a/src/coreclr/vm/ilmarshalers.cpp b/src/coreclr/vm/ilmarshalers.cpp index 13ccc303853071..faa65a1fdf0aa5 100644 --- a/src/coreclr/vm/ilmarshalers.cpp +++ b/src/coreclr/vm/ilmarshalers.cpp @@ -2146,14 +2146,31 @@ void ILLayoutClassPtrMarshalerBase::EmitConvertSpaceCLRToNative(ILCodeStream* ps EmitLoadManagedValue(pslILEmit); pslILEmit->EmitBRFALSE(pNullRefLabel); + + ILCodeLabel* pTypeMismatchedLabel = pslILEmit->NewCodeLabel(); + bool emittedTypeCheck = EmitExactTypeCheck(pslILEmit, pTypeMismatchedLabel); + DWORD sizeLocal = pslILEmit->NewLocal(LocalDesc(ELEMENT_TYPE_I4)); + pslILEmit->EmitLDC(uNativeSize); + if (emittedTypeCheck) + { + ILCodeLabel* pHaveSizeLabel = pslILEmit->NewCodeLabel(); + pslILEmit->EmitBR(pHaveSizeLabel); + pslILEmit->EmitLabel(pTypeMismatchedLabel); + EmitLoadManagedValue(pslILEmit); + pslILEmit->EmitCALL(METHOD__OBJECT__GET_TYPE, 1, 1); + pslILEmit->EmitCALL(METHOD__MARSHAL__SIZEOF_TYPE, 1, 1); + pslILEmit->EmitLabel(pHaveSizeLabel); + } + pslILEmit->EmitSTLOC(sizeLocal); + pslILEmit->EmitLDLOC(sizeLocal); pslILEmit->EmitCALL(METHOD__MARSHAL__ALLOC_CO_TASK_MEM, 1, 1); pslILEmit->EmitDUP(); // for INITBLK EmitStoreNativeValue(pslILEmit); // initialize local block we just allocated pslILEmit->EmitLDC(0); - pslILEmit->EmitLDC(uNativeSize); + pslILEmit->EmitLDLOC(sizeLocal); pslILEmit->EmitINITBLK(); pslILEmit->EmitLabel(pNullRefLabel); @@ -2178,14 +2195,31 @@ void ILLayoutClassPtrMarshalerBase::EmitConvertSpaceCLRToNativeTemp(ILCodeStream EmitLoadManagedValue(pslILEmit); pslILEmit->EmitBRFALSE(pNullRefLabel); + ILCodeLabel* pTypeMismatchedLabel = pslILEmit->NewCodeLabel(); + bool emittedTypeCheck = EmitExactTypeCheck(pslILEmit, pTypeMismatchedLabel); + DWORD sizeLocal = pslILEmit->NewLocal(LocalDesc(ELEMENT_TYPE_I4)); + pslILEmit->EmitLDC(uNativeSize); + if (emittedTypeCheck) + { + ILCodeLabel* pHaveSizeLabel = pslILEmit->NewCodeLabel(); + pslILEmit->EmitBR(pHaveSizeLabel); + pslILEmit->EmitLabel(pTypeMismatchedLabel); + EmitLoadManagedValue(pslILEmit); + pslILEmit->EmitCALL(METHOD__OBJECT__GET_TYPE, 1, 1); + pslILEmit->EmitCALL(METHOD__MARSHAL__SIZEOF_TYPE, 1, 1); + pslILEmit->EmitLabel(pHaveSizeLabel); + } + pslILEmit->EmitSTLOC(sizeLocal); + pslILEmit->EmitLDLOC(sizeLocal); + pslILEmit->EmitLOCALLOC(); pslILEmit->EmitDUP(); // for INITBLK EmitStoreNativeValue(pslILEmit); // initialize local block we just allocated pslILEmit->EmitLDC(0); - pslILEmit->EmitLDC(uNativeSize); + pslILEmit->EmitLDLOC(sizeLocal); pslILEmit->EmitINITBLK(); pslILEmit->EmitLabel(pNullRefLabel); From 1b335d768f44059d00295458ec71aee16fbc5a9f Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Wed, 24 Mar 2021 10:12:09 -0700 Subject: [PATCH 3/3] Apply suggestions from code review --- src/coreclr/vm/ilmarshalers.cpp | 4 +++- src/coreclr/vm/mlinfo.cpp | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/coreclr/vm/ilmarshalers.cpp b/src/coreclr/vm/ilmarshalers.cpp index faa65a1fdf0aa5..0c753e6929b1cd 100644 --- a/src/coreclr/vm/ilmarshalers.cpp +++ b/src/coreclr/vm/ilmarshalers.cpp @@ -2297,6 +2297,8 @@ void ILLayoutClassPtrMarshalerBase::EmitClearNativeTemp(ILCodeStream* pslILEmit) bool ILLayoutClassPtrMarshalerBase::EmitExactTypeCheck(ILCodeStream* pslILEmit, ILCodeLabel* isNotMatchingTypeLabel) { + STANDARD_VM_CONTRACT; + if (m_pargs->m_pMT->IsSealed()) { // If the provided type cannot be derived from, then we don't need to emit the type check. @@ -2497,7 +2499,7 @@ bool ILBlittablePtrMarshaler::CanMarshalViaPinning() return IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags) && !IsFieldMarshal(m_dwMarshalFlags) && - m_pargs->m_pMT->IsSealed(); // We can't marshal via pinning if we might need to marshal differently at runtime. + m_pargs->m_pMT->IsSealed(); // We can't marshal via pinning if we might need to marshal differently at runtime. See calls to EmitExactTypeCheck where we check the runtime type of the object being marshalled. } void ILBlittablePtrMarshaler::EmitMarshalViaPinning(ILCodeStream* pslILEmit) diff --git a/src/coreclr/vm/mlinfo.cpp b/src/coreclr/vm/mlinfo.cpp index f77a07d054d78a..a6f8852aa3670a 100644 --- a/src/coreclr/vm/mlinfo.cpp +++ b/src/coreclr/vm/mlinfo.cpp @@ -1133,7 +1133,7 @@ MarshalInfo::MarshalInfo(Module* pModule, CorElementType corElemType = ELEMENT_TYPE_END; m_pMT = NULL; m_pMD = pMD; - // For backward compatibility reasons, some marshalers imply [In, Out] behavior when marked as [Out]. + // [Compat] For backward compatibility reasons, some marshalers imply [In, Out] behavior when marked as [Out]. BOOL outImpliesInOut = FALSE; #ifdef FEATURE_COMINTEROP