From: Jeremy Koritzinsky Date: Wed, 19 Jun 2019 00:26:10 +0000 (-0700) Subject: ILMarshaler Refactor (#21227) X-Git-Tag: accepted/tizen/unified/20190813.215958~40^2~109 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=70febbad4bbe23326c26480b2848cdfe9fc8450c;p=platform%2Fupstream%2Fcoreclr.git ILMarshaler Refactor (#21227) * Add support for fields to ILStubMarshalHome objects. * Make the specific code streams in the ILMarshaler private members. * Make home members private. * Move the IL code stream members back to being protected for the marshalers that override EmitMarshalArgumentCLRToNative instead of EmitMarshalArgumentContents/Space. * Convert virtual specifiers in overrides to override specifiers. * Remove unused and undefined member. * Cleanup a few missed virtual/override specifiers. * Refactor setup methods. Refactor some of the overrides to duplicate less code. * Refactor the setup stream and add some comments around how the ArgumentOverride/ReturnOverride marshalling system works. * Use the cleanup work list in SafeHandle marshalling since the work list is now implemented entirely in managed code. * Generalize DelegateCleanupWorkListElement -> KeepAliveCleanupWorkListElement and rename the managed entry point to match. * Refactor direct usage of the cleanup code stream in non-overridden marshalers to use the cleanup work list instead. * Refactor AsAny marshalling to fit into the regular ILMarshaler code-paths. * Move ILArgIteratorMarshaler over to the full ILMarshaler infrastructure. * Port ILBlittablePtrMarshaler over to not directly reference m_pcsMarshal. * Make the specific code streams private and have ILNativeArrayMarshaler fetch the one it needs from the NDirectStubLinker. * Devirtualize a method on ILMarshaler. * Fix broken metasig * Revert "Use the cleanup work list in SafeHandle marshalling since the work list is now implemented entirely in managed code." This reverts commit aedcdfb4830475ff8f4d582147cdc0eb497dd681. * Fix ILArgIteratorMarshaler. * Take 2 on using the cleanup work list for SafeHandles * Remove unused field * SafeHandleMarshaler doesn't need to have extra cleanup code when using the CleanupWorkList. * Move the rest of the SafeHandle marshalling into ArgumentOverride. * Moved Pinned Native Array special case into an ArgumentOverride. * Devirtualize * Remove invalid field hometype. * Make ILMarshaler::m_pslNDirect private. * Native Array marshalling fixes. * Fix STLOC->LDLOC mistakes. * Add override hook to allow a marshaler to request that byval contents are always converted to native even when not marked as In (i.e. explicitly marked only as Out). Used in AsAny for byval arrays. * PR Feedback. * Add explicit pinning path to ilmarshalers. * Move implementation of ILNativeArrayMarshaler::CanMarshalViaPinning to ilmarshalers.cpp. * Add missing override specifier. * Don't create a managed marshaler if we are able to marshal via pinning. Remove extraneous checks against pinning. * Convert ILWSTRMarshaler to use the MarshalViaPinning functions for its pinning fast-path. * Enable LPWSTR marshalling to fall back to allocating on the heap for large strings when stack-allocating for native space (byref in-only semantics). * PR Feedback. --- diff --git a/src/System.Private.CoreLib/src/System/StubHelpers.cs b/src/System.Private.CoreLib/src/System/StubHelpers.cs index 0f9ee4e..d84d1b7 100644 --- a/src/System.Private.CoreLib/src/System/StubHelpers.cs +++ b/src/System.Private.CoreLib/src/System/StubHelpers.cs @@ -1485,21 +1485,21 @@ namespace System.StubHelpers } } - // Keeps a Delegate instance alive across the full Managed->Native call. + // Keeps an object instance alive across the full Managed->Native call. // This ensures that users don't have to call GC.KeepAlive after passing a struct or class // that has a delegate field to native code. - internal sealed class DelegateCleanupWorkListElement : CleanupWorkListElement + internal sealed class KeepAliveCleanupWorkListElement : CleanupWorkListElement { - public DelegateCleanupWorkListElement(Delegate del) + public KeepAliveCleanupWorkListElement(object obj) { - m_del = del; + m_obj = obj; } - private Delegate m_del; + private object m_obj; protected override void DestroyCore() { - GC.KeepAlive(m_del); + GC.KeepAlive(m_obj); } } @@ -1562,9 +1562,9 @@ namespace System.StubHelpers return element.AddRef(); } - internal static void AddToCleanupList(ref CleanupWorkListElement pCleanupWorkList, Delegate del) + internal static void KeepAliveViaCleanupList(ref CleanupWorkListElement pCleanupWorkList, object obj) { - DelegateCleanupWorkListElement element = new DelegateCleanupWorkListElement(del); + KeepAliveCleanupWorkListElement element = new KeepAliveCleanupWorkListElement(obj); CleanupWorkListElement.AddToCleanupList(ref pCleanupWorkList, element); } diff --git a/src/vm/fieldmarshaler.cpp b/src/vm/fieldmarshaler.cpp index 8691f2b..c1f512f 100644 --- a/src/vm/fieldmarshaler.cpp +++ b/src/vm/fieldmarshaler.cpp @@ -3064,7 +3064,7 @@ VOID FieldMarshaler_Delegate::UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNat if (*pCLRValue != NULL && ppCleanupWorkListOnStack != NULL) { // Call StubHelpers.AddToCleanupList to ensure the delegate is kept alive across the full native call. - MethodDescCallSite AddToCleanupList(METHOD__STUBHELPERS__ADD_TO_CLEANUP_LIST_DELEGATE); + MethodDescCallSite AddToCleanupList(METHOD__STUBHELPERS__KEEP_ALIVE_VIA_CLEANUP_LIST); ARG_SLOT args[] = { diff --git a/src/vm/ilmarshalers.cpp b/src/vm/ilmarshalers.cpp index 19db7df..146ad7c 100644 --- a/src/vm/ilmarshalers.cpp +++ b/src/vm/ilmarshalers.cpp @@ -78,17 +78,17 @@ void ILReflectionObjectMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* p if (IsCLRToNative(m_dwMarshalFlags)) { - // keep the object alive across the call-out to native + EmitLoadCleanupWorkList(pslILEmit); if (tokStruct__m_object != 0) { - EmitLoadManagedHomeAddr(m_pcsUnmarshal); - m_pcsUnmarshal->EmitLDFLD(tokStruct__m_object); + EmitLoadManagedHomeAddr(pslILEmit); + pslILEmit->EmitLDFLD(tokStruct__m_object); } else { - EmitLoadManagedValue(m_pcsUnmarshal); + EmitLoadManagedValue(pslILEmit); } - m_pcsUnmarshal->EmitCALL(METHOD__GC__KEEP_ALIVE, 1, 0); + pslILEmit->EmitCALL(METHOD__STUBHELPERS__KEEP_ALIVE_VIA_CLEANUP_LIST, 2, 0); } } @@ -128,18 +128,11 @@ void ILDelegateMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit EmitLoadManagedValue(pslILEmit); pslILEmit->EmitCALL(METHOD__MARSHAL__GET_FUNCTION_POINTER_FOR_DELEGATE, 1, 1); EmitStoreNativeValue(pslILEmit); + EmitLoadCleanupWorkList(pslILEmit); + EmitLoadManagedValue(pslILEmit); + pslILEmit->EmitCALL(METHOD__STUBHELPERS__KEEP_ALIVE_VIA_CLEANUP_LIST, 2, 0); pslILEmit->EmitLabel(pNullLabel); - - // - // @TODO: is there a better way to do this? - // - if (IsCLRToNative(m_dwMarshalFlags)) - { - // keep the delegate ref alive across the call-out to native - EmitLoadManagedValue(m_pcsUnmarshal); - m_pcsUnmarshal->EmitCALL(METHOD__GC__KEEP_ALIVE, 1, 0); - } } void ILDelegateMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) @@ -308,41 +301,6 @@ void ILWSTRMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) pslILEmit->EmitLabel(pIsNullLabel); } -bool ILWSTRMarshaler::NeedsClearNative() -{ - LIMITED_METHOD_CONTRACT; - - // will evaluate to true iff there is something CoTaskMemAlloc'ed that we need to free - bool needsClear = (IsByref(m_dwMarshalFlags) && IsOut(m_dwMarshalFlags)) || IsRetval(m_dwMarshalFlags); - - // m_fCoMemoryAllocated => needsClear - // (if we allocated the memory, we will free it; for byref [out] and retval we free memory allocated by the callee) - _ASSERTE(!m_fCoMemoryAllocated || needsClear); - - return needsClear; -} - -void ILWSTRMarshaler::EmitClearNative(ILCodeStream* pslILEmit) -{ - STANDARD_VM_CONTRACT; - - EmitLoadNativeValue(pslILEmit); - // static void CoTaskMemFree(IntPtr ptr) - pslILEmit->EmitCALL(METHOD__MARSHAL__FREE_CO_TASK_MEM, 1, 0); -} - -void ILWSTRMarshaler::EmitClearNativeTemp(ILCodeStream* pslILEmit) -{ - LIMITED_METHOD_CONTRACT; - UNREACHABLE_MSG("The string is either pinned or a copy is stack-allocated, NeedsClearNative should have returned false"); -} - -bool ILWSTRMarshaler::CanUsePinnedManagedString(DWORD dwMarshalFlags) -{ - LIMITED_METHOD_CONTRACT; - return IsCLRToNative(dwMarshalFlags) && !IsByref(dwMarshalFlags) && IsIn(dwMarshalFlags) && !IsOut(dwMarshalFlags); -} - // // input stack: 0: managed string // output stack: 0: (string_length+1) * sizeof(WCHAR) @@ -363,8 +321,6 @@ void ILWSTRMarshaler::EmitConvertSpaceAndContentsCLRToNative(ILCodeStream* pslIL { STANDARD_VM_CONTRACT; - INDEBUG(m_fCoMemoryAllocated = true); - ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel(); DWORD dwLengthLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I4); @@ -400,73 +356,87 @@ void ILWSTRMarshaler::EmitConvertSpaceAndContentsCLRToNative(ILCodeStream* pslIL pslILEmit->EmitLabel(pNullRefLabel); } -void ILWSTRMarshaler::EmitConvertSpaceAndContentsCLRToNativeTemp(ILCodeStream* pslILEmit) +void ILWSTRMarshaler::EmitMarshalViaPinning(ILCodeStream* pslILEmit) { STANDARD_VM_CONTRACT; - if (CanUsePinnedManagedString(m_dwMarshalFlags)) - { - LocalDesc locDesc = GetManagedType(); - locDesc.MakePinned(); - DWORD dwPinnedLocal = pslILEmit->NewLocal(locDesc); - int fieldDef = pslILEmit->GetToken(MscorlibBinder::GetField(FIELD__STRING__M_FIRST_CHAR)); - ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel(); - - pslILEmit->EmitLoadNullPtr(); - EmitStoreNativeValue(pslILEmit); + LocalDesc locDesc = GetManagedType(); + locDesc.MakePinned(); + DWORD dwPinnedLocal = pslILEmit->NewLocal(locDesc); + int fieldDef = pslILEmit->GetToken(MscorlibBinder::GetField(FIELD__STRING__M_FIRST_CHAR)); + ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel(); + + pslILEmit->EmitLoadNullPtr(); + EmitStoreNativeValue(pslILEmit); - EmitLoadManagedValue(pslILEmit); - pslILEmit->EmitBRFALSE(pNullRefLabel); + EmitLoadManagedValue(pslILEmit); + pslILEmit->EmitBRFALSE(pNullRefLabel); - EmitLoadManagedValue(pslILEmit); - pslILEmit->EmitSTLOC(dwPinnedLocal); - pslILEmit->EmitLDLOC(dwPinnedLocal); - pslILEmit->EmitLDFLDA(fieldDef); - EmitStoreNativeValue(pslILEmit); + EmitLoadManagedValue(pslILEmit); + pslILEmit->EmitSTLOC(dwPinnedLocal); + pslILEmit->EmitLDLOC(dwPinnedLocal); + pslILEmit->EmitLDFLDA(fieldDef); + EmitStoreNativeValue(pslILEmit); - if (g_pConfig->InteropLogArguments()) - { - m_pslNDirect->EmitLogNativeArgument(pslILEmit, dwPinnedLocal); - } + EmitLogNativeArgumentsIfNeeded(pslILEmit, dwPinnedLocal); - pslILEmit->EmitLabel(pNullRefLabel); + pslILEmit->EmitLabel(pNullRefLabel); +} - } - else - { - ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel(); - DWORD dwLengthLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I4); - - pslILEmit->EmitLoadNullPtr(); - EmitStoreNativeValue(pslILEmit); - - EmitLoadManagedValue(pslILEmit); - pslILEmit->EmitBRFALSE(pNullRefLabel); - - EmitLoadManagedValue(pslILEmit); - EmitCheckManagedStringLength(pslILEmit); +void ILWSTRMarshaler::EmitConvertSpaceAndContentsCLRToNativeTemp(ILCodeStream* pslILEmit) +{ + STANDARD_VM_CONTRACT; + + ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel(); + DWORD dwLengthLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I4); + + pslILEmit->EmitLoadNullPtr(); + EmitStoreNativeValue(pslILEmit); + + EmitLoadManagedValue(pslILEmit); + pslILEmit->EmitBRFALSE(pNullRefLabel); + + EmitLoadManagedValue(pslILEmit); + EmitCheckManagedStringLength(pslILEmit); - // cb + pslILEmit->EmitSTLOC(dwLengthLocalNum); - pslILEmit->EmitDUP(); - pslILEmit->EmitSTLOC(dwLengthLocalNum); + ILCodeLabel* pAllocRejoin = pslILEmit->NewCodeLabel(); + ILCodeLabel* pNoOptimize = pslILEmit->NewCodeLabel(); + m_dwLocalBuffer = pslILEmit->NewLocal(ELEMENT_TYPE_I); - // cb + // LocalBuffer = 0 + pslILEmit->EmitLoadNullPtr(); + pslILEmit->EmitSTLOC(m_dwLocalBuffer); - pslILEmit->EmitLOCALLOC(); // @TODO: add a non-localloc path for large strings - EmitStoreNativeValue(pslILEmit); + pslILEmit->EmitLDLOC(dwLengthLocalNum); + // if (alloc_size_in_bytes > MAX_LOCAL_BUFFER_LENGTH) goto NoOptimize + pslILEmit->EmitDUP(); + pslILEmit->EmitLDC(MAX_LOCAL_BUFFER_LENGTH); + pslILEmit->EmitCGT_UN(); + pslILEmit->EmitBRTRUE(pNoOptimize); - EmitLoadManagedValue(pslILEmit); - EmitLoadNativeValue(pslILEmit); + pslILEmit->EmitLOCALLOC(); + pslILEmit->EmitDUP(); + pslILEmit->EmitSTLOC(m_dwLocalBuffer); + pslILEmit->EmitBR(pAllocRejoin); - // src, dst + pslILEmit->EmitLabel(pNoOptimize); - pslILEmit->EmitLDLOC(dwLengthLocalNum); // length - - // static void System.String.InternalCopy(String src, IntPtr dest,int len) - pslILEmit->EmitCALL(METHOD__STRING__INTERNAL_COPY, 3, 0); - pslILEmit->EmitLabel(pNullRefLabel); - } + pslILEmit->EmitCALL(METHOD__MARSHAL__ALLOC_CO_TASK_MEM, 1, 1); + pslILEmit->EmitLabel(pAllocRejoin); + EmitStoreNativeValue(pslILEmit); + + EmitLoadManagedValue(pslILEmit); + EmitLoadNativeValue(pslILEmit); + + // src, dst + + pslILEmit->EmitLDLOC(dwLengthLocalNum); // length + + // static void System.String.InternalCopy(String src, IntPtr dest,int len) + pslILEmit->EmitCALL(METHOD__STRING__INTERNAL_COPY, 3, 0); + pslILEmit->EmitLabel(pNullRefLabel); } // @@ -1130,7 +1100,7 @@ void ILValueClassMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEm pslILEmit->EmitLDTOKEN(managedVCToken); // pMT pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1); // Convert RTH to IntPtr - m_pslNDirect->LoadCleanupWorkList(pslILEmit); + EmitLoadCleanupWorkList(pslILEmit); pslILEmit->EmitCALL(METHOD__VALUECLASSMARSHALER__CONVERT_TO_NATIVE, 4, 0); // void ConvertToNative(IntPtr dst, IntPtr src, IntPtr pMT, ref CleanupWorkListElement pCleanupWorkList) } @@ -1398,8 +1368,9 @@ void ILInterfaceMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmi // // The fix is to extend the lifetime of the argument across the call to native by doing a GC.KeepAlive // keep the delegate ref alive across the call-out to native - EmitLoadManagedValue(m_pcsUnmarshal); - m_pcsUnmarshal->EmitCALL(METHOD__GC__KEEP_ALIVE, 1, 0); + EmitLoadCleanupWorkList(pslILEmit); + EmitLoadManagedValue(pslILEmit); + pslILEmit->EmitCALL(METHOD__STUBHELPERS__KEEP_ALIVE_VIA_CLEANUP_LIST, 2, 0); } } @@ -1599,16 +1570,17 @@ bool ILVBByValStrWMarshaler::IsNativePassedByRef() return false; } +void ILVBByValStrWMarshaler::EmitSetupArgumentForMarshalling(ILCodeStream* pslILEmit) +{ + m_dwLocalBuffer = pslILEmit->NewLocal(ELEMENT_TYPE_I); + pslILEmit->EmitLoadNullPtr(); + pslILEmit->EmitSTLOC(m_dwLocalBuffer); +} + void ILVBByValStrWMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) { STANDARD_VM_CONTRACT; - ILCodeStream *pcsSetup = m_pslNDirect->GetSetupCodeStream(); - m_dwLocalBuffer = pcsSetup->NewLocal(ELEMENT_TYPE_I); - pcsSetup->EmitLoadNullPtr(); - pcsSetup->EmitSTLOC(m_dwLocalBuffer); - - ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel(); m_dwCCHLocal = pslILEmit->NewLocal(ELEMENT_TYPE_I4); DWORD dwNumBytesLocal = pslILEmit->NewLocal(ELEMENT_TYPE_I4); @@ -2013,10 +1985,7 @@ void ILHSTRINGMarshaler::EmitConvertCLRToHSTRINGReference(ILCodeStream* pslILEmi pslILEmit->EmitLDLOCA(dwHStringHeaderLocal); pslILEmit->EmitCALL(METHOD__HSTRINGMARSHALER__CONVERT_TO_NATIVE_REFERENCE, 2, 1); - if (g_pConfig->InteropLogArguments()) - { - m_pslNDirect->EmitLogNativeArgument(pslILEmit, dwPinnedStringLocal); - } + EmitLogNativeArgumentsIfNeeded(pslILEmit, dwPinnedStringLocal); EmitStoreNativeValue(pslILEmit); } @@ -2407,7 +2376,7 @@ void ILLayoutClassPtrMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* psl EmitLoadManagedValue(pslILEmit); EmitLoadNativeValue(pslILEmit); - m_pslNDirect->LoadCleanupWorkList(pslILEmit); + EmitLoadCleanupWorkList(pslILEmit); // static void FmtClassUpdateNativeInternal(object obj, byte* pNative, IntPtr pOptionalCleanupList); @@ -2491,43 +2460,41 @@ void ILBlittablePtrMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslIL pslILEmit->EmitLabel(pNullRefLabel); } -void ILBlittablePtrMarshaler::EmitMarshalArgumentCLRToNative() +bool ILBlittablePtrMarshaler::CanUsePinnedLayoutClass() { - CONTRACTL - { - STANDARD_VM_CHECK; - PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags)); - } - CONTRACTL_END; + return IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags); +} - EmitSetupSigAndDefaultHomesCLRToNative(); +void ILBlittablePtrMarshaler::EmitConvertSpaceAndContentsCLRToNativeTemp(ILCodeStream* pslILEmit) +{ + STANDARD_VM_CONTRACT; - // - // marshal - // + if (CanUsePinnedLayoutClass()) + { + ILCodeLabel* pSkipAddLabel = pslILEmit->NewCodeLabel(); + LocalDesc managedTypePinned = GetManagedType(); + managedTypePinned.MakePinned(); + DWORD dwPinnedLocal = pslILEmit->NewLocal(managedTypePinned); - ILCodeLabel* pSkipAddLabel = m_pcsMarshal->NewCodeLabel(); - LocalDesc managedTypePinned = GetManagedType(); - managedTypePinned.MakePinned(); - DWORD dwPinnedLocal = m_pcsMarshal->NewLocal(managedTypePinned); + EmitLoadManagedValue(pslILEmit); - EmitLoadManagedValue(m_pcsMarshal); - - m_pcsMarshal->EmitSTLOC(dwPinnedLocal); - m_pcsMarshal->EmitLDLOC(dwPinnedLocal); - m_pcsMarshal->EmitCONV_U(); - m_pcsMarshal->EmitDUP(); - m_pcsMarshal->EmitBRFALSE(pSkipAddLabel); - m_pcsMarshal->EmitLDC(Object::GetOffsetOfFirstField()); - m_pcsMarshal->EmitADD(); - m_pcsMarshal->EmitLabel(pSkipAddLabel); + pslILEmit->EmitSTLOC(dwPinnedLocal); + pslILEmit->EmitLDLOC(dwPinnedLocal); + pslILEmit->EmitCONV_U(); + pslILEmit->EmitDUP(); + pslILEmit->EmitBRFALSE(pSkipAddLabel); + pslILEmit->EmitLDC(Object::GetOffsetOfFirstField()); + pslILEmit->EmitADD(); + pslILEmit->EmitLabel(pSkipAddLabel); + + EmitLogNativeArgumentsIfNeeded(pslILEmit, dwPinnedLocal); - if (g_pConfig->InteropLogArguments()) + EmitStoreNativeValue(pslILEmit); + } + else { - m_pslNDirect->EmitLogNativeArgument(m_pcsMarshal, dwPinnedLocal); + ILLayoutClassPtrMarshalerBase::EmitConvertSpaceAndContentsCLRToNativeTemp(pslILEmit); } - - EmitStoreNativeValue(m_pcsMarshal); } @@ -2598,78 +2565,6 @@ MarshalerOverrideStatus ILHandleRefMarshaler::ReturnOverride(NDirectStubLinker* return DISALLOWED; } -LocalDesc ILSafeHandleMarshaler::GetManagedType() -{ - STANDARD_VM_CONTRACT; - - return LocalDesc(MscorlibBinder::GetClass(CLASS__SAFE_HANDLE)); -} - -LocalDesc ILSafeHandleMarshaler::GetNativeType() -{ - LIMITED_METHOD_CONTRACT; - - return LocalDesc(ELEMENT_TYPE_I); -} - -bool ILSafeHandleMarshaler::NeedsClearNative() -{ - LIMITED_METHOD_CONTRACT; - return true; -} - -void ILSafeHandleMarshaler::EmitClearNative(ILCodeStream* pslILEmit) -{ - STANDARD_VM_CONTRACT; - - _ASSERTE(IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags)); - - // call StubHelpers::SafeHandleRelease - EmitLoadManagedValue(pslILEmit); - pslILEmit->EmitCALL(METHOD__STUBHELPERS__SAFE_HANDLE_RELEASE, 1, 0); -} - -void ILSafeHandleMarshaler::EmitMarshalArgumentCLRToNative() -{ - CONTRACTL - { - STANDARD_VM_CHECK; - PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags)); - } - CONTRACTL_END; - - EmitSetupSigAndDefaultHomesCLRToNative(); - - // by-value CLR-to-native SafeHandle is always passed in-only regardless of [In], [Out] - // marshal and cleanup communicate via an extra local and are both emitted in this method - - // bool = false - ILCodeStream *pcsSetup = m_pslNDirect->GetSetupCodeStream(); - DWORD dwHandleAddRefedLocalNum = pcsSetup->NewLocal(ELEMENT_TYPE_BOOLEAN); - - pcsSetup->EmitLDC(0); - pcsSetup->EmitSTLOC(dwHandleAddRefedLocalNum); - - // = StubHelpers::SafeHandleAddRef(, ref ) - EmitLoadManagedValue(m_pcsMarshal); - m_pcsMarshal->EmitLDLOCA(dwHandleAddRefedLocalNum); - m_pcsMarshal->EmitCALL(METHOD__STUBHELPERS__SAFE_HANDLE_ADD_REF, 2, 1); - EmitStoreNativeValue(m_pcsMarshal); - - // cleanup: - // if () StubHelpers.SafeHandleRelease() - ILCodeStream *pcsCleanup = m_pslNDirect->GetCleanupCodeStream(); - ILCodeLabel *pSkipClearNativeLabel = pcsCleanup->NewCodeLabel(); - - pcsCleanup->EmitLDLOC(dwHandleAddRefedLocalNum); - pcsCleanup->EmitBRFALSE(pSkipClearNativeLabel); - - EmitClearNativeTemp(pcsCleanup); - m_pslNDirect->SetCleanupNeeded(); - - pcsCleanup->EmitLabel(pSkipClearNativeLabel); -} - MarshalerOverrideStatus ILSafeHandleMarshaler::ArgumentOverride(NDirectStubLinker* psl, BOOL byref, BOOL fin, @@ -2693,10 +2588,9 @@ MarshalerOverrideStatus ILSafeHandleMarshaler::ArgumentOverride(NDirectStubLinke if (fManagedToNative) { + pslIL->SetStubTargetArgType(ELEMENT_TYPE_I); if (byref) { - pslIL->SetStubTargetArgType(ELEMENT_TYPE_I); - // The specific SafeHandle subtype we're dealing with here. MethodTable *pHandleType = pargs->m_pMT; @@ -2841,14 +2735,13 @@ MarshalerOverrideStatus ILSafeHandleMarshaler::ArgumentOverride(NDirectStubLinke } else { - // Avoid using the cleanup list in this common case for perf reasons (cleanup list is - // unmanaged and destroying it means excessive managed<->native transitions; in addition, - // as X86 IL stubs do not use interop frames, there's nothing protecting the cleanup list - // and the SafeHandle references must be GC handles which does not help perf either). - // - // This code path generates calls to StubHelpers.SafeHandleAddRef and SafeHandleRelease. - // NICE: Could SafeHandle.DangerousAddRef and DangerousRelease be implemented in managed? - return HANDLEASNORMAL; + DWORD dwNativeHandle = pslIL->NewLocal(ELEMENT_TYPE_I); + psl->LoadCleanupWorkList(pslIL); + pslIL->EmitLDARG(argidx); + pslIL->EmitCALL(METHOD__STUBHELPERS__ADD_TO_CLEANUP_LIST_SAFEHANDLE, 2, 1); + pslIL->EmitSTLOC(dwNativeHandle); + + pslILDispatch->EmitLDLOC(dwNativeHandle); } return OVERRIDDEN; @@ -3406,56 +3299,35 @@ bool ILArgIteratorMarshaler::SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* return true; } -void ILArgIteratorMarshaler::EmitMarshalArgumentCLRToNative() +void ILArgIteratorMarshaler::EmitConvertSpaceAndContentsCLRToNative(ILCodeStream* pslILEmit) { - CONTRACTL - { - STANDARD_VM_CHECK; - PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags)); - } - CONTRACTL_END; - - EmitSetupSigAndDefaultHomesCLRToNative(); - - // - // marshal - // + STANDARD_VM_CONTRACT; // Allocate enough memory for va_list - DWORD dwVaListSizeLocal = m_pcsMarshal->NewLocal(LocalDesc(ELEMENT_TYPE_U4)); - EmitLoadManagedHomeAddr(m_pcsMarshal); - m_pcsMarshal->EmitCALL(METHOD__STUBHELPERS__CALC_VA_LIST_SIZE, 1, 1); - m_pcsMarshal->EmitSTLOC(dwVaListSizeLocal); - m_pcsMarshal->EmitLDLOC(dwVaListSizeLocal); - m_pcsMarshal->EmitLOCALLOC(); - EmitStoreNativeValue(m_pcsMarshal); - - // void MarshalToUnmanagedVaListInternal(cbVaListSize, va_list, VARARGS* data) - EmitLoadNativeValue(m_pcsMarshal); - m_pcsMarshal->EmitLDLOC(dwVaListSizeLocal); - EmitLoadManagedHomeAddr(m_pcsMarshal); - m_pcsMarshal->EmitCALL(METHOD__STUBHELPERS__MARSHAL_TO_UNMANAGED_VA_LIST_INTERNAL, 3, 0); + DWORD dwVaListSizeLocal = pslILEmit->NewLocal(LocalDesc(ELEMENT_TYPE_U4)); + EmitLoadManagedHomeAddr(pslILEmit); + pslILEmit->EmitCALL(METHOD__STUBHELPERS__CALC_VA_LIST_SIZE, 1, 1); + pslILEmit->EmitSTLOC(dwVaListSizeLocal); + pslILEmit->EmitLDLOC(dwVaListSizeLocal); + pslILEmit->EmitLOCALLOC(); + EmitStoreNativeValue(pslILEmit); + + // void MarshalToUnmanagedVaListInternal(va_list, uint vaListSize, VARARGS* data) + EmitLoadNativeValue(pslILEmit); + pslILEmit->EmitLDLOC(dwVaListSizeLocal); + EmitLoadManagedHomeAddr(pslILEmit); + pslILEmit->EmitCALL(METHOD__STUBHELPERS__MARSHAL_TO_UNMANAGED_VA_LIST_INTERNAL, 3, 0); } -void ILArgIteratorMarshaler::EmitMarshalArgumentNativeToCLR() +void ILArgIteratorMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) { - CONTRACTL - { - STANDARD_VM_CHECK; - PRECONDITION(!IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags)); - } - CONTRACTL_END; - - EmitSetupSigAndDefaultHomesNativeToCLR(); - - EmitLoadNativeValue(m_pcsMarshal); - EmitLoadManagedHomeAddr(m_pcsMarshal); + EmitLoadNativeValue(pslILEmit); + EmitLoadManagedHomeAddr(pslILEmit); // void MarshalToManagedVaList(va_list va, VARARGS *dataout) - m_pcsMarshal->EmitCALL(METHOD__STUBHELPERS__MARSHAL_TO_MANAGED_VA_LIST_INTERNAL, 2, 0); + pslILEmit->EmitCALL(METHOD__STUBHELPERS__MARSHAL_TO_MANAGED_VA_LIST_INTERNAL, 2, 0); } - LocalDesc ILArrayWithOffsetMarshaler::GetNativeType() { LIMITED_METHOD_CONTRACT; @@ -3679,75 +3551,54 @@ bool ILAsAnyMarshalerBase::SupportsReturnMarshal(DWORD dwMarshalFlags, UINT* pEr return false; } -void ILAsAnyMarshalerBase::EmitMarshalArgumentCLRToNative() +void ILAsAnyMarshalerBase::EmitCreateMngdMarshaler(ILCodeStream* pslILEmit) { CONTRACTL { - STANDARD_VM_CHECK; - PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags)); - CONSISTENCY_CHECK(LOCAL_NUM_UNUSED == m_dwMarshalerLocalNum); + THROWS; + GC_TRIGGERS; + MODE_ANY; + CONSISTENCY_CHECK(LOCAL_NUM_UNUSED == m_dwMngdMarshalerLocalNum); } CONTRACTL_END; - EmitSetupSigAndDefaultHomesCLRToNative(); - - BYTE inout = (IsIn(m_dwMarshalFlags) ? ML_IN : 0) | (IsOut(m_dwMarshalFlags) ? ML_OUT : 0); - BYTE fIsAnsi = IsAnsi() ? 1 : 0; - BYTE fBestFit = m_pargs->m_pMarshalInfo->GetBestFitMapping(); - BYTE fThrow = m_pargs->m_pMarshalInfo->GetThrowOnUnmappableChar(); - - DWORD dwFlags = 0; - - dwFlags |= inout << 24; - dwFlags |= fIsAnsi << 16; - dwFlags |= fThrow << 8; - dwFlags |= fBestFit << 0; - - // - // marshal - // - LocalDesc marshalerType(MscorlibBinder::GetClass(CLASS__ASANY_MARSHALER)); - m_dwMarshalerLocalNum = m_pcsMarshal->NewLocal(marshalerType); - DWORD dwTmpLocalNum = m_pcsMarshal->NewLocal(ELEMENT_TYPE_I); + m_dwMngdMarshalerLocalNum = pslILEmit->NewLocal(marshalerType); + DWORD dwTmpLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I); - m_pcsMarshal->EmitLDC(sizeof(MngdNativeArrayMarshaler)); - m_pcsMarshal->EmitLOCALLOC(); - m_pcsMarshal->EmitSTLOC(dwTmpLocalNum); + pslILEmit->EmitLDC(sizeof(MngdNativeArrayMarshaler)); + pslILEmit->EmitLOCALLOC(); + pslILEmit->EmitSTLOC(dwTmpLocalNum); // marshaler = new AsAnyMarshaler(local_buffer) - m_pcsMarshal->EmitLDLOCA(m_dwMarshalerLocalNum); - m_pcsMarshal->EmitINITOBJ(m_pcsMarshal->GetToken(marshalerType.InternalToken)); + pslILEmit->EmitLDLOCA(m_dwMngdMarshalerLocalNum); + pslILEmit->EmitINITOBJ(pslILEmit->GetToken(marshalerType.InternalToken)); - m_pcsMarshal->EmitLDLOCA(m_dwMarshalerLocalNum); - m_pcsMarshal->EmitLDLOC(dwTmpLocalNum); - m_pcsMarshal->EmitCALL(METHOD__ASANY_MARSHALER__CTOR, 2, 0); + pslILEmit->EmitLDLOCA(m_dwMngdMarshalerLocalNum); + pslILEmit->EmitLDLOC(dwTmpLocalNum); + pslILEmit->EmitCALL(METHOD__ASANY_MARSHALER__CTOR, 2, 0); +} +void ILAsAnyMarshalerBase::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) +{ // nativeValue = marshaler.ConvertToNative(managedValue, flags); - m_pcsMarshal->EmitLDLOCA(m_dwMarshalerLocalNum); - EmitLoadManagedValue(m_pcsMarshal); - m_pcsMarshal->EmitLDC(dwFlags); - m_pcsMarshal->EmitCALL(METHOD__ASANY_MARSHALER__CONVERT_TO_NATIVE, 3, 1); - EmitStoreNativeValue(m_pcsMarshal); - - // - // unmarshal - // - if (IsOut(m_dwMarshalFlags)) - { - // marshaler.ConvertToManaged(managedValue, nativeValue) - m_pcsUnmarshal->EmitLDLOCA(m_dwMarshalerLocalNum); - EmitLoadManagedValue(m_pcsUnmarshal); - EmitLoadNativeValue(m_pcsUnmarshal); - m_pcsUnmarshal->EmitCALL(METHOD__ASANY_MARSHALER__CONVERT_TO_MANAGED, 3, 0); - } + EmitLoadMngdMarshalerAddr(pslILEmit); + EmitLoadManagedValue(pslILEmit); + pslILEmit->EmitLDC(GetAsAnyFlags()); + pslILEmit->EmitCALL(METHOD__ASANY_MARSHALER__CONVERT_TO_NATIVE, 3, 1); + EmitStoreNativeValue(pslILEmit); +} - // - // cleanup - // - EmitCleanupCLRToNativeTemp(); +void ILAsAnyMarshalerBase::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) +{ + // marshaler.ConvertToManaged(managedValue, nativeValue) + EmitLoadMngdMarshalerAddr(pslILEmit); + EmitLoadManagedValue(pslILEmit); + EmitLoadNativeValue(pslILEmit); + pslILEmit->EmitCALL(METHOD__ASANY_MARSHALER__CONVERT_TO_MANAGED, 3, 0); } + bool ILAsAnyMarshalerBase::NeedsClearNative() { LIMITED_METHOD_CONTRACT; @@ -3759,7 +3610,7 @@ void ILAsAnyMarshalerBase::EmitClearNativeTemp(ILCodeStream* pslILEmit) STANDARD_VM_CONTRACT; // marshaler.ClearNative(nativeHome) - pslILEmit->EmitLDLOCA(m_dwMarshalerLocalNum); + EmitLoadMngdMarshalerAddr(pslILEmit); EmitLoadNativeValue(pslILEmit); pslILEmit->EmitCALL(METHOD__ASANY_MARSHALER__CLEAR_NATIVE, 2, 0); } @@ -3806,24 +3657,9 @@ void ILMngdMarshaler::EmitCallMngdMarshalerMethod(ILCodeStream* pslILEmit, Metho } } -bool ILNativeArrayMarshaler::UsePinnedArraySpecialCase() -{ - if (IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags) && (NULL == OleVariant::GetMarshalerForVarType(m_pargs->na.m_vt, TRUE))) - { - return true; - } - - return false; -} - void ILNativeArrayMarshaler::EmitCreateMngdMarshaler(ILCodeStream* pslILEmit) { STANDARD_VM_CONTRACT; - - if (UsePinnedArraySpecialCase()) - { - return; - } m_dwMngdMarshalerLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I); @@ -3855,8 +3691,12 @@ void ILNativeArrayMarshaler::EmitCreateMngdMarshaler(ILCodeStream* pslILEmit) pslILEmit->EmitCALL(METHOD__MNGD_NATIVE_ARRAY_MARSHALER__CREATE_MARSHALER, 3, 0); } +bool ILNativeArrayMarshaler::CanMarshalViaPinning() +{ + return IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags) && (NULL == OleVariant::GetMarshalerForVarType(m_pargs->na.m_vt, TRUE)); +} -void ILNativeArrayMarshaler::EmitMarshalArgumentCLRToNative() +void ILNativeArrayMarshaler::EmitMarshalViaPinning(ILCodeStream* pslILEmit) { CONTRACTL { @@ -3865,56 +3705,44 @@ void ILNativeArrayMarshaler::EmitMarshalArgumentCLRToNative() } CONTRACTL_END; - if (UsePinnedArraySpecialCase()) - { - // - // Replicate ML_PINNEDISOMORPHICARRAY_C2N_EXPRESS behavior -- note that this - // gives in/out semantics "for free" even if the app doesn't specify one or - // the other. Since there is no enforcement of this, apps blithely depend - // on it. - // + // + // Replicate ML_PINNEDISOMORPHICARRAY_C2N_EXPRESS behavior -- note that this + // gives in/out semantics "for free" even if the app doesn't specify one or + // the other. Since there is no enforcement of this, apps blithely depend + // on it. + // - EmitSetupSigAndDefaultHomesCLRToNative(); - - LocalDesc managedType = GetManagedType(); - managedType.MakePinned(); - - DWORD dwPinnedLocal = m_pcsMarshal->NewLocal(managedType); - ILCodeLabel* pNullRefLabel = m_pcsMarshal->NewCodeLabel(); - - m_pcsMarshal->EmitLoadNullPtr(); - EmitStoreNativeValue(m_pcsMarshal); - - EmitLoadManagedValue(m_pcsMarshal); - m_pcsMarshal->EmitBRFALSE(pNullRefLabel); - - // COMPAT: We cannot generate the same code that the C# compiler generates for - // a fixed() statement on an array since we need to provide a non-null value - // for a 0-length array. For compat reasons, we need to preserve old behavior. - // Additionally, we need to ensure that we do not pass non-null for a zero-length - // array when interacting with GDI/GDI+ since they fail on null arrays but succeed - // on 0-length arrays. - EmitLoadManagedValue(m_pcsMarshal); - m_pcsMarshal->EmitSTLOC(dwPinnedLocal); - m_pcsMarshal->EmitLDLOC(dwPinnedLocal); - m_pcsMarshal->EmitCONV_I(); - // Optimize marshalling by emitting the data ptr offset directly into the IL stream - // instead of doing an FCall to recalulate it each time when possible. - m_pcsMarshal->EmitLDC(ArrayBase::GetDataPtrOffset(m_pargs->m_pMarshalInfo->GetArrayElementTypeHandle().MakeSZArray().GetMethodTable())); - m_pcsMarshal->EmitADD(); - EmitStoreNativeValue(m_pcsMarshal); - - if (g_pConfig->InteropLogArguments()) - { - m_pslNDirect->EmitLogNativeArgument(m_pcsMarshal, dwPinnedLocal); - } + LocalDesc managedType = GetManagedType(); + managedType.MakePinned(); - m_pcsMarshal->EmitLabel(pNullRefLabel); - } - else - { - ILMngdMarshaler::EmitMarshalArgumentCLRToNative(); - } + DWORD dwPinnedLocal = pslILEmit->NewLocal(managedType); + ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel(); + + pslILEmit->EmitLoadNullPtr(); + EmitStoreNativeValue(pslILEmit); + + EmitLoadManagedValue(pslILEmit); + pslILEmit->EmitBRFALSE(pNullRefLabel); + + // COMPAT: We cannot generate the same code that the C# compiler generates for + // a fixed() statement on an array since we need to provide a non-null value + // for a 0-length array. For compat reasons, we need to preserve old behavior. + // Additionally, we need to ensure that we do not pass non-null for a zero-length + // array when interacting with GDI/GDI+ since they fail on null arrays but succeed + // on 0-length arrays. + EmitLoadManagedValue(pslILEmit); + pslILEmit->EmitSTLOC(dwPinnedLocal); + pslILEmit->EmitLDLOC(dwPinnedLocal); + pslILEmit->EmitCONV_I(); + // Optimize marshalling by emitting the data ptr offset directly into the IL stream + // instead of doing an FCall to recalulate it each time when possible. + pslILEmit->EmitLDC(ArrayBase::GetDataPtrOffset(m_pargs->m_pMarshalInfo->GetArrayElementTypeHandle().MakeSZArray().GetMethodTable())); + pslILEmit->EmitADD(); + EmitStoreNativeValue(pslILEmit); + + EmitLogNativeArgumentsIfNeeded(pslILEmit, dwPinnedLocal); + + pslILEmit->EmitLabel(pNullRefLabel); } // @@ -4029,7 +3857,7 @@ void ILNativeArrayMarshaler::EmitLoadElementCount(ILCodeStream* pslILEmit) unsigned countParamIdx = mops.countParamIdx; if (!IsCLRToNative(m_dwMarshalFlags)) { - int lcidParamIdx = m_pslNDirect->GetLCIDParamIdx(); + int lcidParamIdx = GetLCIDParamIndex(); if (lcidParamIdx >= 0 && (unsigned)lcidParamIdx <= countParamIdx) { @@ -4215,42 +4043,24 @@ void ILNativeArrayMarshaler::EmitClearNativeContents(ILCodeStream* pslILEmit) pslILEmit->EmitCALL(pslILEmit->GetToken(GetClearNativeContentsMethod()), 3, 0); } -void ILNativeArrayMarshaler::EmitNewSavedSizeArgLocal() +void ILNativeArrayMarshaler::EmitSetupArgumentForMarshalling(ILCodeStream* pslILEmit) { - STANDARD_VM_CONTRACT; - - _ASSERTE(m_dwSavedSizeArg == LOCAL_NUM_UNUSED); - ILCodeStream *pcsSetup = m_pslNDirect->GetSetupCodeStream(); - m_dwSavedSizeArg = pcsSetup->NewLocal(ELEMENT_TYPE_I4); - pcsSetup->EmitLDC(0); - pcsSetup->EmitSTLOC(m_dwSavedSizeArg); -} - -void ILNativeArrayMarshaler::EmitMarshalArgumentNativeToCLRByref() -{ - STANDARD_VM_CONTRACT; - if (IsByref(m_dwMarshalFlags)) { - EmitNewSavedSizeArgLocal(); + EmitNewSavedSizeArgLocal(pslILEmit); } - - ILMngdMarshaler::EmitMarshalArgumentNativeToCLRByref(); } -void ILNativeArrayMarshaler::EmitMarshalArgumentCLRToNativeByref() +void ILNativeArrayMarshaler::EmitNewSavedSizeArgLocal(ILCodeStream* pslILEmit) { STANDARD_VM_CONTRACT; - if (IsByref(m_dwMarshalFlags)) - { - EmitNewSavedSizeArgLocal(); - } - - ILMngdMarshaler::EmitMarshalArgumentCLRToNativeByref(); + _ASSERTE(m_dwSavedSizeArg == LOCAL_NUM_UNUSED); + m_dwSavedSizeArg = pslILEmit->NewLocal(ELEMENT_TYPE_I4); + pslILEmit->EmitLDC(0); + pslILEmit->EmitSTLOC(m_dwSavedSizeArg); } - #ifndef CROSSGEN_COMPILE FCIMPL3(void, MngdNativeArrayMarshaler::CreateMarshaler, MngdNativeArrayMarshaler* pThis, MethodTable* pMT, UINT32 dwFlags) @@ -4728,98 +4538,75 @@ void ILHiddenLengthArrayMarshaler::EmitCreateMngdMarshaler(ILCodeStream* pslILEm { STANDARD_VM_CONTRACT; - if (!CanUsePinnedArray()) - { - m_dwMngdMarshalerLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I); - - pslILEmit->EmitLDC(sizeof(MngdHiddenLengthArrayMarshaler)); - pslILEmit->EmitLOCALLOC(); - pslILEmit->EmitSTLOC(m_dwMngdMarshalerLocalNum); + m_dwMngdMarshalerLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I); + + pslILEmit->EmitLDC(sizeof(MngdHiddenLengthArrayMarshaler)); + pslILEmit->EmitLOCALLOC(); + pslILEmit->EmitSTLOC(m_dwMngdMarshalerLocalNum); - MethodTable *pElementMT = m_pargs->m_pMarshalInfo->GetArrayElementTypeHandle().GetMethodTable(); - pslILEmit->EmitLDLOC(m_dwMngdMarshalerLocalNum); - pslILEmit->EmitLDTOKEN(pslILEmit->GetToken(pElementMT)); - pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1); + MethodTable *pElementMT = m_pargs->m_pMarshalInfo->GetArrayElementTypeHandle().GetMethodTable(); + pslILEmit->EmitLDLOC(m_dwMngdMarshalerLocalNum); + pslILEmit->EmitLDTOKEN(pslILEmit->GetToken(pElementMT)); + pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1); - pslILEmit->EmitLDC(m_pargs->na.m_cbElementSize); - pslILEmit->EmitLDC(m_pargs->na.m_vt); + pslILEmit->EmitLDC(m_pargs->na.m_cbElementSize); + pslILEmit->EmitLDC(m_pargs->na.m_vt); - pslILEmit->EmitCALL(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CREATE_MARSHALER, 4, 0); - } + pslILEmit->EmitCALL(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CREATE_MARSHALER, 4, 0); } -void ILHiddenLengthArrayMarshaler::EmitMarshalArgumentCLRToNative() +void ILHiddenLengthArrayMarshaler::EmitMarshalViaPinning(ILCodeStream* pslILEmit) { - STANDARD_VM_CONTRACT; - - // If we can pin the array, then do that rather than marshaling it in a more heavy weight way - // Otherwise, fall back to doing a full marshal - if (CanUsePinnedArray()) - { - EmitSetupSigAndDefaultHomesCLRToNative(); - - LocalDesc managedType = GetManagedType(); - managedType.MakePinned(); - DWORD dwPinnedLocal = m_pcsMarshal->NewLocal(managedType); + LocalDesc managedType = GetManagedType(); + managedType.MakePinned(); + DWORD dwPinnedLocal = pslILEmit->NewLocal(managedType); - ILCodeLabel* pMarshalDoneLabel = m_pcsMarshal->NewCodeLabel(); + ILCodeLabel* pMarshalDoneLabel = pslILEmit->NewCodeLabel(); - // native = NULL - m_pcsMarshal->EmitLoadNullPtr(); - EmitStoreNativeValue(m_pcsMarshal); - - // if (managed == null) goto MarshalDone - EmitLoadManagedValue(m_pcsMarshal); - m_pcsMarshal->EmitBRFALSE(pMarshalDoneLabel); + // native = NULL + pslILEmit->EmitLoadNullPtr(); + EmitStoreNativeValue(pslILEmit); - // pinnedLocal = managed; - EmitLoadManagedValue(m_pcsMarshal); - m_pcsMarshal->EmitSTLOC(dwPinnedLocal); + // if (managed == null) goto MarshalDone + EmitLoadManagedValue(pslILEmit); + pslILEmit->EmitBRFALSE(pMarshalDoneLabel); - // native = pinnedLocal + dataOffset + // pinnedLocal = managed; + EmitLoadManagedValue(pslILEmit); + pslILEmit->EmitSTLOC(dwPinnedLocal); - // COMPAT: We cannot generate the same code that the C# compiler generates for - // a fixed() statement on an array since we need to provide a non-null value - // for a 0-length array. For compat reasons, we need to preserve old behavior. - EmitLoadManagedValue(m_pcsMarshal); - m_pcsMarshal->EmitSTLOC(dwPinnedLocal); - m_pcsMarshal->EmitLDLOC(dwPinnedLocal); - m_pcsMarshal->EmitCONV_I(); - // Optimize marshalling by emitting the data ptr offset directly into the IL stream - // instead of doing an FCall to recalulate it each time. - m_pcsMarshal->EmitLDC(ArrayBase::GetDataPtrOffset(m_pargs->m_pMarshalInfo->GetArrayElementTypeHandle().MakeSZArray().GetMethodTable())); - m_pcsMarshal->EmitADD(); - EmitStoreNativeValue(m_pcsMarshal); + // native = pinnedLocal + dataOffset - if (g_pConfig->InteropLogArguments()) - { - m_pslNDirect->EmitLogNativeArgument(m_pcsMarshal, dwPinnedLocal); - } + // COMPAT: We cannot generate the same code that the C# compiler generates for + // a fixed() statement on an array since we need to provide a non-null value + // for a 0-length array. For compat reasons, we need to preserve old behavior. + EmitLoadManagedValue(pslILEmit); + pslILEmit->EmitSTLOC(dwPinnedLocal); + pslILEmit->EmitLDLOC(dwPinnedLocal); + pslILEmit->EmitCONV_I(); + // Optimize marshalling by emitting the data ptr offset directly into the IL stream + // instead of doing an FCall to recalulate it each time. + pslILEmit->EmitLDC(ArrayBase::GetDataPtrOffset(m_pargs->m_pMarshalInfo->GetArrayElementTypeHandle().MakeSZArray().GetMethodTable())); + pslILEmit->EmitADD(); + EmitStoreNativeValue(pslILEmit); - // MarshalDone: - m_pcsMarshal->EmitLabel(pMarshalDoneLabel); - } - else - { - ILMngdMarshaler::EmitMarshalArgumentCLRToNative(); - } + EmitLogNativeArgumentsIfNeeded(pslILEmit, dwPinnedLocal); + // MarshalDone: + pslILEmit->EmitLabel(pMarshalDoneLabel); } void ILHiddenLengthArrayMarshaler::EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit) { STANDARD_VM_CONTRACT; - if (!CanUsePinnedArray()) - { - EmitLoadMngdMarshaler(pslILEmit); - EmitLoadManagedHomeAddr(pslILEmit); - EmitLoadNativeHomeAddr(pslILEmit); - EmitLoadNativeArrayLength(pslILEmit); - - // MngdHiddenLengthArrayMarshaler::ConvertSpaceToManaged - pslILEmit->EmitCALL(pslILEmit->GetToken(GetConvertSpaceToManagedMethod()), 4, 0); - } + EmitLoadMngdMarshaler(pslILEmit); + EmitLoadManagedHomeAddr(pslILEmit); + EmitLoadNativeHomeAddr(pslILEmit); + EmitLoadNativeArrayLength(pslILEmit); + + // MngdHiddenLengthArrayMarshaler::ConvertSpaceToManaged + pslILEmit->EmitCALL(pslILEmit->GetToken(GetConvertSpaceToManagedMethod()), 4, 0); } void ILHiddenLengthArrayMarshaler::EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit) @@ -4831,7 +4618,7 @@ void ILHiddenLengthArrayMarshaler::EmitConvertSpaceCLRToNative(ILCodeStream* psl { if (IsByref(m_dwMarshalFlags) || IsRetval(m_dwMarshalFlags) || IsOut(m_dwMarshalFlags)) { - ILCodeLabel *pSkipGetLengthLabel = m_pcsMarshal->NewCodeLabel(); + ILCodeLabel *pSkipGetLengthLabel = pslILEmit->NewCodeLabel(); // nativeLen = 0 pslILEmit->EmitLDC(0); @@ -4858,82 +4645,76 @@ void ILHiddenLengthArrayMarshaler::EmitConvertSpaceCLRToNative(ILCodeStream* psl } } - if (!CanUsePinnedArray()) - { - ILMngdMarshaler::EmitConvertSpaceCLRToNative(pslILEmit); - } + ILMngdMarshaler::EmitConvertSpaceCLRToNative(pslILEmit); } void ILHiddenLengthArrayMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) { STANDARD_VM_CONTRACT; - if (!CanUsePinnedArray()) + if (m_pargs->na.m_vt == VTHACK_REDIRECTEDTYPE && + (m_pargs->na.m_redirectedTypeIndex == WinMDAdapter::RedirectedTypeIndex_System_Uri || + m_pargs->na.m_redirectedTypeIndex == WinMDAdapter::RedirectedTypeIndex_System_Collections_Specialized_NotifyCollectionChangedEventArgs || + m_pargs->na.m_redirectedTypeIndex == WinMDAdapter::RedirectedTypeIndex_System_ComponentModel_PropertyChangedEventArgs)) { - if (m_pargs->na.m_vt == VTHACK_REDIRECTEDTYPE && - (m_pargs->na.m_redirectedTypeIndex == WinMDAdapter::RedirectedTypeIndex_System_Uri || - m_pargs->na.m_redirectedTypeIndex == WinMDAdapter::RedirectedTypeIndex_System_Collections_Specialized_NotifyCollectionChangedEventArgs || - m_pargs->na.m_redirectedTypeIndex == WinMDAdapter::RedirectedTypeIndex_System_ComponentModel_PropertyChangedEventArgs)) - { - // System.Uri/NotifyCollectionChangedEventArgs don't live in mscorlib so there's no marshaling helper to call - inline the loop - DWORD dwLoopCounterLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I4); - DWORD dwNativePtrLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I); - ILCodeLabel *pConditionLabel = pslILEmit->NewCodeLabel(); - ILCodeLabel *pLoopBodyLabel = pslILEmit->NewCodeLabel(); + // System.Uri/NotifyCollectionChangedEventArgs don't live in mscorlib so there's no marshaling helper to call - inline the loop + DWORD dwLoopCounterLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I4); + DWORD dwNativePtrLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I); + ILCodeLabel *pConditionLabel = pslILEmit->NewCodeLabel(); + ILCodeLabel *pLoopBodyLabel = pslILEmit->NewCodeLabel(); - // for (IntPtr ptr = pNative, int i = 0; ... - pslILEmit->EmitLDC(0); - pslILEmit->EmitSTLOC(dwLoopCounterLocalNum); - EmitLoadNativeValue(pslILEmit); - pslILEmit->EmitSTLOC(dwNativePtrLocalNum); - pslILEmit->EmitBR(pConditionLabel); - - // *ptr = EmitConvertCLR*ToWinRT*(pManaged[i]); - pslILEmit->EmitLabel(pLoopBodyLabel); - pslILEmit->EmitLDLOC(dwNativePtrLocalNum); - EmitLoadManagedValue(pslILEmit); - pslILEmit->EmitLDLOC(dwLoopCounterLocalNum); - pslILEmit->EmitLDELEM_REF(); + // for (IntPtr ptr = pNative, int i = 0; ... + pslILEmit->EmitLDC(0); + pslILEmit->EmitSTLOC(dwLoopCounterLocalNum); + EmitLoadNativeValue(pslILEmit); + pslILEmit->EmitSTLOC(dwNativePtrLocalNum); + pslILEmit->EmitBR(pConditionLabel); - switch (m_pargs->na.m_redirectedTypeIndex) - { - case WinMDAdapter::RedirectedTypeIndex_System_Uri: - ILUriMarshaler::EmitConvertCLRUriToWinRTUri(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetLoaderAllocator()); - break; + // *ptr = EmitConvertCLR*ToWinRT*(pManaged[i]); + pslILEmit->EmitLabel(pLoopBodyLabel); + pslILEmit->EmitLDLOC(dwNativePtrLocalNum); + EmitLoadManagedValue(pslILEmit); + pslILEmit->EmitLDLOC(dwLoopCounterLocalNum); + pslILEmit->EmitLDELEM_REF(); - case WinMDAdapter::RedirectedTypeIndex_System_Collections_Specialized_NotifyCollectionChangedEventArgs: - ILNCCEventArgsMarshaler::EmitConvertCLREventArgsToWinRTEventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetLoaderAllocator()); - break; + switch (m_pargs->na.m_redirectedTypeIndex) + { + case WinMDAdapter::RedirectedTypeIndex_System_Uri: + ILUriMarshaler::EmitConvertCLRUriToWinRTUri(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetLoaderAllocator()); + break; - case WinMDAdapter::RedirectedTypeIndex_System_ComponentModel_PropertyChangedEventArgs: - ILPCEventArgsMarshaler::EmitConvertCLREventArgsToWinRTEventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetLoaderAllocator()); - break; + case WinMDAdapter::RedirectedTypeIndex_System_Collections_Specialized_NotifyCollectionChangedEventArgs: + ILNCCEventArgsMarshaler::EmitConvertCLREventArgsToWinRTEventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetLoaderAllocator()); + break; - default: UNREACHABLE(); - } + case WinMDAdapter::RedirectedTypeIndex_System_ComponentModel_PropertyChangedEventArgs: + ILPCEventArgsMarshaler::EmitConvertCLREventArgsToWinRTEventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetLoaderAllocator()); + break; - pslILEmit->EmitSTIND_I(); - - // ... i++, ptr += IntPtr.Size ... - pslILEmit->EmitLDLOC(dwLoopCounterLocalNum); - pslILEmit->EmitLDC(1); - pslILEmit->EmitADD(); - pslILEmit->EmitSTLOC(dwLoopCounterLocalNum); - pslILEmit->EmitLDLOC(dwNativePtrLocalNum); - pslILEmit->EmitLDC(sizeof(LPVOID)); - pslILEmit->EmitADD(); - pslILEmit->EmitSTLOC(dwNativePtrLocalNum); - - // ... i < pManaged.Length; ... - pslILEmit->EmitLabel(pConditionLabel); - pslILEmit->EmitLDLOC(dwLoopCounterLocalNum); - EmitLoadNativeArrayLength(pslILEmit); - pslILEmit->EmitBLT(pLoopBodyLabel); - } - else - { - ILMngdMarshaler::EmitConvertContentsCLRToNative(pslILEmit); + default: UNREACHABLE(); } + + pslILEmit->EmitSTIND_I(); + + // ... i++, ptr += IntPtr.Size ... + pslILEmit->EmitLDLOC(dwLoopCounterLocalNum); + pslILEmit->EmitLDC(1); + pslILEmit->EmitADD(); + pslILEmit->EmitSTLOC(dwLoopCounterLocalNum); + pslILEmit->EmitLDLOC(dwNativePtrLocalNum); + pslILEmit->EmitLDC(sizeof(LPVOID)); + pslILEmit->EmitADD(); + pslILEmit->EmitSTLOC(dwNativePtrLocalNum); + + // ... i < pManaged.Length; ... + pslILEmit->EmitLabel(pConditionLabel); + pslILEmit->EmitLDLOC(dwLoopCounterLocalNum); + EmitLoadNativeArrayLength(pslILEmit); + pslILEmit->EmitBLT(pLoopBodyLabel); + } + else + { + ILMngdMarshaler::EmitConvertContentsCLRToNative(pslILEmit); } } @@ -4941,72 +4722,69 @@ void ILHiddenLengthArrayMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* { STANDARD_VM_CONTRACT; - if (!CanUsePinnedArray()) + if (m_pargs->na.m_vt == VTHACK_REDIRECTEDTYPE && + (m_pargs->na.m_redirectedTypeIndex == WinMDAdapter::RedirectedTypeIndex_System_Uri || + m_pargs->na.m_redirectedTypeIndex == WinMDAdapter::RedirectedTypeIndex_System_Collections_Specialized_NotifyCollectionChangedEventArgs || + m_pargs->na.m_redirectedTypeIndex == WinMDAdapter::RedirectedTypeIndex_System_ComponentModel_PropertyChangedEventArgs)) { - if (m_pargs->na.m_vt == VTHACK_REDIRECTEDTYPE && - (m_pargs->na.m_redirectedTypeIndex == WinMDAdapter::RedirectedTypeIndex_System_Uri || - m_pargs->na.m_redirectedTypeIndex == WinMDAdapter::RedirectedTypeIndex_System_Collections_Specialized_NotifyCollectionChangedEventArgs || - m_pargs->na.m_redirectedTypeIndex == WinMDAdapter::RedirectedTypeIndex_System_ComponentModel_PropertyChangedEventArgs)) - { - // System.Uri/NotifyCollectionChangedEventArgs don't live in mscorlib so there's no marshaling helper to call - inline the loop - DWORD dwLoopCounterLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I4); - DWORD dwNativePtrLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I); - ILCodeLabel *pConditionLabel = pslILEmit->NewCodeLabel(); - ILCodeLabel *pLoopBodyLabel = pslILEmit->NewCodeLabel(); + // System.Uri/NotifyCollectionChangedEventArgs don't live in mscorlib so there's no marshaling helper to call - inline the loop + DWORD dwLoopCounterLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I4); + DWORD dwNativePtrLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I); + ILCodeLabel *pConditionLabel = pslILEmit->NewCodeLabel(); + ILCodeLabel *pLoopBodyLabel = pslILEmit->NewCodeLabel(); - // for (IntPtr ptr = pNative, int i = 0; ... - pslILEmit->EmitLDC(0); - pslILEmit->EmitSTLOC(dwLoopCounterLocalNum); - EmitLoadNativeValue(pslILEmit); - pslILEmit->EmitSTLOC(dwNativePtrLocalNum); - pslILEmit->EmitBR(pConditionLabel); + // for (IntPtr ptr = pNative, int i = 0; ... + pslILEmit->EmitLDC(0); + pslILEmit->EmitSTLOC(dwLoopCounterLocalNum); + EmitLoadNativeValue(pslILEmit); + pslILEmit->EmitSTLOC(dwNativePtrLocalNum); + pslILEmit->EmitBR(pConditionLabel); - // pManaged[i] = EmitConvertWinRT*ToCLR*(*ptr); - pslILEmit->EmitLabel(pLoopBodyLabel); - EmitLoadManagedValue(pslILEmit); - pslILEmit->EmitLDLOC(dwLoopCounterLocalNum); - pslILEmit->EmitLDLOC(dwNativePtrLocalNum); - pslILEmit->EmitLDIND_I(); + // pManaged[i] = EmitConvertWinRT*ToCLR*(*ptr); + pslILEmit->EmitLabel(pLoopBodyLabel); + EmitLoadManagedValue(pslILEmit); + pslILEmit->EmitLDLOC(dwLoopCounterLocalNum); + pslILEmit->EmitLDLOC(dwNativePtrLocalNum); + pslILEmit->EmitLDIND_I(); - switch (m_pargs->na.m_redirectedTypeIndex) - { - case WinMDAdapter::RedirectedTypeIndex_System_Uri: - ILUriMarshaler::EmitConvertWinRTUriToCLRUri(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetLoaderAllocator()); - break; + switch (m_pargs->na.m_redirectedTypeIndex) + { + case WinMDAdapter::RedirectedTypeIndex_System_Uri: + ILUriMarshaler::EmitConvertWinRTUriToCLRUri(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetLoaderAllocator()); + break; - case WinMDAdapter::RedirectedTypeIndex_System_Collections_Specialized_NotifyCollectionChangedEventArgs: - ILNCCEventArgsMarshaler::EmitConvertWinRTEventArgsToCLREventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetLoaderAllocator()); - break; + case WinMDAdapter::RedirectedTypeIndex_System_Collections_Specialized_NotifyCollectionChangedEventArgs: + ILNCCEventArgsMarshaler::EmitConvertWinRTEventArgsToCLREventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetLoaderAllocator()); + break; - case WinMDAdapter::RedirectedTypeIndex_System_ComponentModel_PropertyChangedEventArgs: - ILPCEventArgsMarshaler::EmitConvertWinRTEventArgsToCLREventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetLoaderAllocator()); - break; + case WinMDAdapter::RedirectedTypeIndex_System_ComponentModel_PropertyChangedEventArgs: + ILPCEventArgsMarshaler::EmitConvertWinRTEventArgsToCLREventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetLoaderAllocator()); + break; - default: UNREACHABLE(); - } - - pslILEmit->EmitSTELEM_REF(); - - // ... i++, ptr += IntPtr.Size) - pslILEmit->EmitLDLOC(dwLoopCounterLocalNum); - pslILEmit->EmitLDC(1); - pslILEmit->EmitADD(); - pslILEmit->EmitSTLOC(dwLoopCounterLocalNum); - pslILEmit->EmitLDLOC(dwNativePtrLocalNum); - pslILEmit->EmitLDC(sizeof(LPVOID)); - pslILEmit->EmitADD(); - pslILEmit->EmitSTLOC(dwNativePtrLocalNum); - - // ... i < pManaged.Length; ... - pslILEmit->EmitLabel(pConditionLabel); - pslILEmit->EmitLDLOC(dwLoopCounterLocalNum); - EmitLoadNativeArrayLength(pslILEmit); - pslILEmit->EmitBLT(pLoopBodyLabel); - } - else - { - ILMngdMarshaler::EmitConvertContentsNativeToCLR(pslILEmit); + default: UNREACHABLE(); } + + pslILEmit->EmitSTELEM_REF(); + + // ... i++, ptr += IntPtr.Size) + pslILEmit->EmitLDLOC(dwLoopCounterLocalNum); + pslILEmit->EmitLDC(1); + pslILEmit->EmitADD(); + pslILEmit->EmitSTLOC(dwLoopCounterLocalNum); + pslILEmit->EmitLDLOC(dwNativePtrLocalNum); + pslILEmit->EmitLDC(sizeof(LPVOID)); + pslILEmit->EmitADD(); + pslILEmit->EmitSTLOC(dwNativePtrLocalNum); + + // ... i < pManaged.Length; ... + pslILEmit->EmitLabel(pConditionLabel); + pslILEmit->EmitLDLOC(dwLoopCounterLocalNum); + EmitLoadNativeArrayLength(pslILEmit); + pslILEmit->EmitBLT(pLoopBodyLabel); + } + else + { + ILMngdMarshaler::EmitConvertContentsNativeToCLR(pslILEmit); } } @@ -5016,43 +4794,37 @@ void ILHiddenLengthArrayMarshaler::EmitClearNative(ILCodeStream* pslILEmit) EmitClearNativeContents(pslILEmit); - if (!CanUsePinnedArray()) - { - EmitLoadNativeValue(pslILEmit); - pslILEmit->EmitCALL(pslILEmit->GetToken(GetClearNativeMethod()), 1, 0); - } + EmitLoadNativeValue(pslILEmit); + pslILEmit->EmitCALL(pslILEmit->GetToken(GetClearNativeMethod()), 1, 0); } void ILHiddenLengthArrayMarshaler::EmitClearNativeContents(ILCodeStream* pslILEmit) { STANDARD_VM_CONTRACT; - if (!CanUsePinnedArray()) + MethodDesc *pMD = GetClearNativeContentsMethod(); + if (pMD != NULL) { - MethodDesc *pMD = GetClearNativeContentsMethod(); - if (pMD != NULL) - { - MetaSig sig(pMD); - UINT numArgs = sig.NumFixedArgs(); - - if (numArgs == 3) - { - EmitLoadMngdMarshaler(pslILEmit); - } - else - { - _ASSERTE(numArgs == 2); - } + MetaSig sig(pMD); + UINT numArgs = sig.NumFixedArgs(); - EmitLoadNativeHomeAddr(pslILEmit); - EmitLoadNativeArrayLength(pslILEmit); - pslILEmit->EmitCALL(pslILEmit->GetToken(pMD), numArgs, 0); + if (numArgs == 3) + { + EmitLoadMngdMarshaler(pslILEmit); } + else + { + _ASSERTE(numArgs == 2); + } + + EmitLoadNativeHomeAddr(pslILEmit); + EmitLoadNativeArrayLength(pslILEmit); + pslILEmit->EmitCALL(pslILEmit->GetToken(pMD), numArgs, 0); } } // Determine if we can simply pin the managed array, rather than doing a full marshal -bool ILHiddenLengthArrayMarshaler::CanUsePinnedArray() +bool ILHiddenLengthArrayMarshaler::CanMarshalViaPinning() { STANDARD_VM_CONTRACT; diff --git a/src/vm/ilmarshalers.h b/src/vm/ilmarshalers.h index 61ff142..e2f81c3 100644 --- a/src/vm/ilmarshalers.h +++ b/src/vm/ilmarshalers.h @@ -42,6 +42,7 @@ public: void InitHome(MarshalHomeType homeType, DWORD dwHomeIndex) { LIMITED_METHOD_CONTRACT; + m_homeType = homeType; m_dwHomeIndex = dwHomeIndex; } @@ -214,17 +215,16 @@ protected: #endif // _DEBUG OverrideProcArgs* m_pargs; - NDirectStubLinker* m_pslNDirect; - ILCodeStream* m_pcsMarshal; - ILCodeStream* m_pcsUnmarshal; UINT m_argidx; - DWORD m_dwMarshalFlags; + DWORD m_dwMngdMarshalerLocalNum; +private: + ILCodeStream* m_pcsMarshal; + ILCodeStream* m_pcsUnmarshal; ILStubMarshalHome m_nativeHome; ILStubMarshalHome m_managedHome; - - DWORD m_dwMngdMarshalerLocalNum; + NDirectStubLinker* m_pslNDirect; public: @@ -245,6 +245,7 @@ public: m_pslNDirect = pslNDirect; } +private: void Init(ILCodeStream* pcsMarshal, ILCodeStream* pcsUnmarshal, UINT argidx, @@ -352,6 +353,14 @@ protected: m_nativeHome.EmitStoreHomeAddr(pslILEmit); } + void EmitLogNativeArgumentsIfNeeded(ILCodeStream* pslILEmit, DWORD dwPinnedLocal) + { + if (g_pConfig->InteropLogArguments()) + { + m_pslNDirect->EmitLogNativeArgument(pslILEmit, dwPinnedLocal); + } + } + public: virtual bool SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID) @@ -398,7 +407,15 @@ public: // before we were able to marshal them. Therefore this must not happen within the try block so we don't try // to use marshalers that have not been initialized. Potentially leaking unmanaged resources is by-design and // there's not much we can do about it (we cannot do cleanup if we cannot create the marshaler). - EmitCreateMngdMarshaler(m_pslNDirect->GetSetupCodeStream()); + // Some marshalers have a managed marshaler for the general path but can pin on the fast path. + // If we're in a scenario where this marshaler can pin on a by-value managed->native call, + // we know that we don't need a managed marshaler since we will just pin. + if (!CanMarshalViaPinning()) + { + EmitCreateMngdMarshaler(m_pslNDirect->GetSetupCodeStream()); + } + + EmitSetupArgumentForMarshalling(m_pslNDirect->GetSetupCodeStream()); if (IsCLRToNative(dwMarshalFlags)) { @@ -443,7 +460,13 @@ public: CONTRACTL_END; Init(pcsMarshal, pcsUnmarshal, hiddenArgIndex, dwMarshalFlags, pargs); - EmitCreateMngdMarshaler(m_pslNDirect->GetSetupCodeStream()); + + if (!CanMarshalViaPinning()) + { + EmitCreateMngdMarshaler(m_pslNDirect->GetSetupCodeStream()); + } + + EmitSetupArgumentForMarshalling(m_pslNDirect->GetSetupCodeStream()); // Create a local to be the home of the length parameter DWORD dwManagedLocalHome = m_pcsMarshal->NewLocal(GetManagedType()); @@ -536,7 +559,7 @@ public: #endif // FEATURE_COMINTEROP - virtual void EmitSetupArgument(ILCodeStream* pslILEmit) + void EmitSetupArgumentForDispatch(ILCodeStream* pslILEmit) { STANDARD_VM_CONTRACT; @@ -564,7 +587,7 @@ public: } } - virtual void EmitMarshalReturnValue( + void EmitMarshalReturnValue( ILCodeStream* pcsMarshal, ILCodeStream* pcsUnmarshal, ILCodeStream* pcsDispatch, @@ -811,7 +834,7 @@ protected: LIMITED_METHOD_CONTRACT; } - virtual void EmitLoadMngdMarshaler(ILCodeStream* pslILEmit) + void EmitLoadMngdMarshaler(ILCodeStream* pslILEmit) { CONTRACTL { @@ -825,6 +848,30 @@ protected: pslILEmit->EmitLDLOC(m_dwMngdMarshalerLocalNum); } + void EmitLoadMngdMarshalerAddr(ILCodeStream* pslILEmit) + { + CONTRACTL + { + THROWS; + GC_TRIGGERS; + MODE_ANY; + } + CONTRACTL_END; + + CONSISTENCY_CHECK((DWORD)-1 != m_dwMngdMarshalerLocalNum); + pslILEmit->EmitLDLOCA(m_dwMngdMarshalerLocalNum); + } + + void EmitLoadCleanupWorkList(ILCodeStream* pslILEmit) + { + m_pslNDirect->LoadCleanupWorkList(pslILEmit); + } + + int GetLCIDParamIndex() + { + return m_pslNDirect->GetLCIDParamIdx(); + } + void EmitSetupSigAndDefaultHomesCLRToNative() { CONTRACTL @@ -884,7 +931,7 @@ protected: } } - virtual void EmitMarshalArgumentCLRToNative() + void EmitMarshalArgumentCLRToNative() { CONTRACTL { @@ -906,31 +953,39 @@ protected: } CONTRACTL_END; - // - // marshal - // - if (IsIn(m_dwMarshalFlags)) + if (CanMarshalViaPinning()) { - EmitConvertSpaceAndContentsCLRToNativeTemp(m_pcsMarshal); + // If we can marshal via pinning, all we need to do to marshal is pin. + EmitMarshalViaPinning(m_pcsMarshal); } else { - EmitConvertSpaceCLRToNativeTemp(m_pcsMarshal); - } + // + // marshal + // + if (IsIn(m_dwMarshalFlags) || AlwaysConvertByValContentsCLRToNative()) + { + EmitConvertSpaceAndContentsCLRToNativeTemp(m_pcsMarshal); + } + else + { + EmitConvertSpaceCLRToNativeTemp(m_pcsMarshal); + } - // - // unmarshal - // - if (IsOut(m_dwMarshalFlags)) - { - if (IsIn(m_dwMarshalFlags)) + // + // unmarshal + // + if (IsOut(m_dwMarshalFlags)) { - EmitClearCLRContents(m_pcsUnmarshal); + if (IsIn(m_dwMarshalFlags)) + { + EmitClearCLRContents(m_pcsUnmarshal); + } + EmitConvertContentsNativeToCLR(m_pcsUnmarshal); } - EmitConvertContentsNativeToCLR(m_pcsUnmarshal); + + EmitCleanupCLRToNativeTemp(); } - - EmitCleanupCLRToNativeTemp(); } void EmitSetupSigAndDefaultHomesCLRToNativeByref(bool fBlittable = false) @@ -1081,6 +1136,18 @@ protected: } } + void EmitMarshalArgumentAddressCLRToNative() + { + EmitLoadManagedHomeAddr(m_pcsMarshal); + EmitStoreNativeHomeAddr(m_pcsMarshal); + } + + void EmitMarshalArgumentAddressNativeToCLR() + { + EmitLoadNativeHomeAddr(m_pcsMarshal); + EmitStoreManagedHomeAddr(m_pcsMarshal); + } + // Emits cleanup code that runs only if an exception is thrown during execution of an IL stub (its try // block to be precise). The goal is to roll back allocations of native resources that may have already // happened to prevent leaks, and also clear output arguments to prevent passing out invalid data - most @@ -1167,7 +1234,7 @@ protected: } } - virtual void EmitMarshalArgumentNativeToCLR() + void EmitMarshalArgumentNativeToCLR() { CONTRACTL { @@ -1325,6 +1392,11 @@ protected: virtual LocalDesc GetNativeType() = 0; virtual LocalDesc GetManagedType() = 0; + virtual void EmitSetupArgumentForMarshalling(ILCodeStream* pslILEmit) + { + LIMITED_METHOD_CONTRACT; + } + // // Native-to-CLR // @@ -1371,7 +1443,10 @@ protected: EmitConvertSpaceCLRToNative(pslILEmit); EmitConvertContentsCLRToNative(pslILEmit); } - + + // Emits marshalling code to allocate space and convert a value from a CLR value to a native value. + // Usable in situations where temporary (i.e. pinned or stack-allocated) space is usable. + // For marshalling scenarios that require heap-allocated space, call EmitConvertSpaceAndContentsCLRToNative. virtual void EmitConvertSpaceAndContentsCLRToNativeTemp(ILCodeStream* pslILEmit) { WRAPPER_NO_CONTRACT; @@ -1419,6 +1494,17 @@ protected: LIMITED_METHOD_CONTRACT; } + virtual bool CanMarshalViaPinning() + { + LIMITED_METHOD_CONTRACT; + return false; + } + + virtual void EmitMarshalViaPinning(ILCodeStream* pslILEmit) + { + LIMITED_METHOD_CONTRACT; + } + virtual void EmitReInitNative(ILCodeStream* pslILEmit) { STANDARD_VM_CONTRACT; @@ -1435,7 +1521,7 @@ protected: EmitStoreNativeValue(pslILEmit); } - virtual bool IsManagedPassedByRef() + bool IsManagedPassedByRef() { LIMITED_METHOD_CONTRACT; return IsByref(m_dwMarshalFlags); @@ -1449,7 +1535,16 @@ protected: void EmitInterfaceClearNative(ILCodeStream* pslILEmit); + virtual bool AlwaysConvertByValContentsCLRToNative() + { + LIMITED_METHOD_CONTRACT; + return false; + } + public: + + // Extension point to allow a marshaler to conditionally override all of the ILMarshaler logic with its own or block marshalling when marshalling an argument. + // See MarshalInfo::GetArgumentOverrideProc for the implementation. static MarshalerOverrideStatus ArgumentOverride(NDirectStubLinker* psl, BOOL byref, BOOL fin, @@ -1464,6 +1559,8 @@ public: return HANDLEASNORMAL; } + // Extension point to allow a marshaler to conditionally override all of the ILMarshaler logic with its own or block marshalling when marshalling a return value. + // See MarshalInfo::GetReturnOverrideProc for the implementation. static MarshalerOverrideStatus ReturnOverride(NDirectStubLinker* psl, BOOL fManagedToNative, BOOL fHresultSwap, @@ -1478,13 +1575,13 @@ public: class ILCopyMarshalerBase : public ILMarshaler { - virtual LocalDesc GetManagedType() + LocalDesc GetManagedType() override { WRAPPER_NO_CONTRACT; return GetNativeType(); } - virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) + void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override { STANDARD_VM_CONTRACT; @@ -1492,7 +1589,7 @@ class ILCopyMarshalerBase : public ILMarshaler EmitStoreNativeValue(pslILEmit); } - virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) + void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override { STANDARD_VM_CONTRACT; @@ -1513,7 +1610,7 @@ class ILCopyMarshalerBase : public ILMarshaler // This method was changed to pin instead of copy in Dev10 in order // to match the original ML behavior. // - virtual void EmitMarshalArgumentCLRToNativeByref() + void EmitMarshalArgumentCLRToNativeByref() override { CONTRACTL { @@ -1527,9 +1624,8 @@ class ILCopyMarshalerBase : public ILMarshaler // // marshal // - EmitLoadManagedHomeAddr(m_pcsMarshal); - EmitStoreNativeHomeAddr(m_pcsMarshal); - + EmitMarshalArgumentAddressCLRToNative(); + // // no unmarshaling is necessary since we directly passed the pinned byref to native, // the argument is therefore automatically in/out @@ -1547,7 +1643,7 @@ class ILCopyMarshalerBase : public ILMarshaler // need to pin the pointer - if it is pointing to GC heap, it must have been // pinned on the way to unmanaged. // - virtual void EmitMarshalArgumentNativeToCLRByref() + void EmitMarshalArgumentNativeToCLRByref() override { CONTRACTL { @@ -1561,8 +1657,7 @@ class ILCopyMarshalerBase : public ILMarshaler // // marshal // - EmitLoadNativeHomeAddr(m_pcsMarshal); - EmitStoreManagedHomeAddr(m_pcsMarshal); + EmitMarshalArgumentAddressNativeToCLR(); // // no unmarshaling is necessary since we directly passed the pointer to managed @@ -1796,10 +1891,10 @@ public: }; protected: - virtual LocalDesc GetNativeType(); - virtual LocalDesc GetManagedType(); - virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit); - virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit); + LocalDesc GetNativeType() override; + LocalDesc GetManagedType() override; + void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override; + void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override; }; class ILReflectionObjectMarshaler : public ILMarshaler @@ -1813,11 +1908,11 @@ public: }; protected: - virtual LocalDesc GetManagedType(); - virtual LocalDesc GetNativeType(); - virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit); - virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit); - virtual BinderFieldID GetStructureFieldID() {LIMITED_METHOD_CONTRACT; return (BinderFieldID)0;} + LocalDesc GetManagedType() override; + LocalDesc GetNativeType() override; + void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override; + void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override; + virtual BinderFieldID GetStructureFieldID() { LIMITED_METHOD_CONTRACT; return (BinderFieldID)0; } virtual BinderFieldID GetObjectFieldID() = 0; virtual BinderClassID GetManagedTypeBinderID() = 0; }; @@ -1825,25 +1920,25 @@ protected: class ILRuntimeTypeHandleMarshaler : public ILReflectionObjectMarshaler { protected: - virtual BinderFieldID GetStructureFieldID() { LIMITED_METHOD_CONTRACT; return FIELD__RT_TYPE_HANDLE__M_TYPE; } - virtual BinderFieldID GetObjectFieldID() { LIMITED_METHOD_CONTRACT; return FIELD__CLASS__TYPEHANDLE; } - virtual BinderClassID GetManagedTypeBinderID() { LIMITED_METHOD_CONTRACT; return CLASS__RT_TYPE_HANDLE; } + BinderFieldID GetStructureFieldID() override { LIMITED_METHOD_CONTRACT; return FIELD__RT_TYPE_HANDLE__M_TYPE; } + BinderFieldID GetObjectFieldID() override { LIMITED_METHOD_CONTRACT; return FIELD__CLASS__TYPEHANDLE; } + BinderClassID GetManagedTypeBinderID() override { LIMITED_METHOD_CONTRACT; return CLASS__RT_TYPE_HANDLE; } }; class ILRuntimeMethodHandleMarshaler : public ILReflectionObjectMarshaler { protected: - virtual BinderFieldID GetStructureFieldID() { LIMITED_METHOD_CONTRACT; return FIELD__METHOD_HANDLE__METHOD; } - virtual BinderFieldID GetObjectFieldID() { LIMITED_METHOD_CONTRACT; return FIELD__STUBMETHODINFO__HANDLE; } - virtual BinderClassID GetManagedTypeBinderID() { LIMITED_METHOD_CONTRACT; return CLASS__METHOD_HANDLE; } + BinderFieldID GetStructureFieldID() override { LIMITED_METHOD_CONTRACT; return FIELD__METHOD_HANDLE__METHOD; } + BinderFieldID GetObjectFieldID() override { LIMITED_METHOD_CONTRACT; return FIELD__STUBMETHODINFO__HANDLE; } + BinderClassID GetManagedTypeBinderID() override { LIMITED_METHOD_CONTRACT; return CLASS__METHOD_HANDLE; } }; class ILRuntimeFieldHandleMarshaler : public ILReflectionObjectMarshaler { protected: - virtual BinderFieldID GetStructureFieldID() { LIMITED_METHOD_CONTRACT; return FIELD__FIELD_HANDLE__M_FIELD; } - virtual BinderFieldID GetObjectFieldID() { LIMITED_METHOD_CONTRACT; return FIELD__RT_FIELD_INFO__HANDLE; } - virtual BinderClassID GetManagedTypeBinderID() { LIMITED_METHOD_CONTRACT; return CLASS__FIELD_HANDLE; } + BinderFieldID GetStructureFieldID() override { LIMITED_METHOD_CONTRACT; return FIELD__FIELD_HANDLE__M_FIELD; } + BinderFieldID GetObjectFieldID() override { LIMITED_METHOD_CONTRACT; return FIELD__RT_FIELD_INFO__HANDLE; } + BinderClassID GetManagedTypeBinderID() override { LIMITED_METHOD_CONTRACT; return CLASS__FIELD_HANDLE; } }; class ILBoolMarshaler : public ILMarshaler @@ -1855,10 +1950,10 @@ public: virtual int GetNativeFalseValue() = 0; protected: - virtual LocalDesc GetNativeType(); - virtual LocalDesc GetManagedType(); - virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit); - virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit); + LocalDesc GetNativeType() override; + LocalDesc GetManagedType() override; + void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override; + void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override; }; class ILWinBoolMarshaler : public ILBoolMarshaler @@ -1872,19 +1967,19 @@ public: }; protected: - virtual CorElementType GetNativeBoolElementType() + CorElementType GetNativeBoolElementType() override { LIMITED_METHOD_CONTRACT; return ELEMENT_TYPE_I4; } - virtual int GetNativeTrueValue() + int GetNativeTrueValue() override { LIMITED_METHOD_CONTRACT; return 1; } - virtual int GetNativeFalseValue() + int GetNativeFalseValue() override { LIMITED_METHOD_CONTRACT; return 0; @@ -1902,19 +1997,19 @@ public: }; protected: - virtual CorElementType GetNativeBoolElementType() + CorElementType GetNativeBoolElementType() override { LIMITED_METHOD_CONTRACT; return ELEMENT_TYPE_I1; } - virtual int GetNativeTrueValue() + int GetNativeTrueValue() override { LIMITED_METHOD_CONTRACT; return 1; } - virtual int GetNativeFalseValue() + int GetNativeFalseValue() override { LIMITED_METHOD_CONTRACT; return 0; @@ -1933,19 +2028,19 @@ public: }; protected: - virtual CorElementType GetNativeBoolElementType() + CorElementType GetNativeBoolElementType() override { LIMITED_METHOD_CONTRACT; return ELEMENT_TYPE_I2; } - virtual int GetNativeTrueValue() + int GetNativeTrueValue() override { LIMITED_METHOD_CONTRACT; return VARIANT_TRUE; } - virtual int GetNativeFalseValue() + int GetNativeFalseValue() override { LIMITED_METHOD_CONTRACT; return VARIANT_FALSE; @@ -1953,59 +2048,6 @@ protected: }; #endif // FEATURE_COMINTEROP -class ILWSTRMarshaler : public ILMarshaler -{ -public: - enum - { - c_fInOnly = FALSE, - c_nativeSize = sizeof(void *), - c_CLRSize = sizeof(OBJECTREF), - }; - -#ifdef _DEBUG - bool m_fCoMemoryAllocated; - - ILWSTRMarshaler() - { - LIMITED_METHOD_CONTRACT; - m_fCoMemoryAllocated = false; - } -#endif // _DEBUG - - - virtual bool SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID) - { - if (IsOut(dwMarshalFlags) && !IsByref(dwMarshalFlags) && IsCLRToNative(dwMarshalFlags)) - { - *pErrorResID = IDS_EE_BADMARSHAL_STRING_OUT; - return false; - } - - return true; - } - -protected: - virtual LocalDesc GetNativeType(); - virtual LocalDesc GetManagedType(); - - virtual void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit); - virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit); - virtual void EmitConvertSpaceAndContentsCLRToNative(ILCodeStream* pslILEmit); - virtual void EmitConvertSpaceAndContentsCLRToNativeTemp(ILCodeStream* pslILEmit); - - virtual void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit); - virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit); - - virtual bool NeedsClearNative(); - virtual void EmitClearNative(ILCodeStream* pslILEmit); - virtual void EmitClearNativeTemp(ILCodeStream* pslILEmit); - - static bool CanUsePinnedManagedString(DWORD dwMarshalFlags); - static void EmitCheckManagedStringLength(ILCodeStream* pslILEmit); - static void EmitCheckNativeStringLength(ILCodeStream* pslILEmit); -}; - // A marshaler that makes run-time decision based on argument size whether native space will // be allocated using localloc or on the heap. The ctor argument is a heap free function. class ILOptimizedAllocMarshaler : public ILMarshaler @@ -2018,9 +2060,9 @@ public: LIMITED_METHOD_CONTRACT; } - virtual LocalDesc GetNativeType(); - virtual bool NeedsClearNative(); - virtual void EmitClearNative(ILCodeStream* pslILEmit); + LocalDesc GetNativeType() override; + bool NeedsClearNative() override; + void EmitClearNative(ILCodeStream* pslILEmit) override; protected: const BinderMethodID m_idClearNative; @@ -2049,11 +2091,11 @@ public: LIMITED_METHOD_CONTRACT; } - virtual LocalDesc GetManagedType(); - virtual void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit); - virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit); - virtual void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit); - virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit); + LocalDesc GetManagedType() override; + void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit) override; + void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override; + void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit) override; + void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override; }; class ILWSTRBufferMarshaler : public ILOptimizedAllocMarshaler @@ -2078,11 +2120,11 @@ public: LIMITED_METHOD_CONTRACT; } - virtual LocalDesc GetManagedType(); - virtual void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit); - virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit); - virtual void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit); - virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit); + LocalDesc GetManagedType() override; + void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit) override; + void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override; + void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit) override; + void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override; }; class ILCSTRBufferMarshaler : public ILOptimizedAllocMarshaler @@ -2107,11 +2149,11 @@ public: LIMITED_METHOD_CONTRACT; } - virtual LocalDesc GetManagedType(); - virtual void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit); - virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit); - virtual void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit); - virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit); + LocalDesc GetManagedType() override; + void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit) override; + void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override; + void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit) override; + void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override; }; @@ -2171,13 +2213,17 @@ public: c_CLRSize = sizeof(SAFEHANDLE), }; - virtual LocalDesc GetManagedType(); - virtual LocalDesc GetNativeType(); - - virtual bool NeedsClearNative(); - virtual void EmitClearNative(ILCodeStream* pslILEmit); - - virtual void EmitMarshalArgumentCLRToNative(); + LocalDesc GetManagedType() override + { + LIMITED_METHOD_CONTRACT; + return LocalDesc(); + } + + LocalDesc GetNativeType() override + { + LIMITED_METHOD_CONTRACT; + return LocalDesc(); + } static MarshalerOverrideStatus ArgumentOverride(NDirectStubLinker* psl, BOOL byref, @@ -2209,13 +2255,13 @@ public: public: - LocalDesc GetManagedType() + LocalDesc GetManagedType() override { LIMITED_METHOD_CONTRACT; return LocalDesc(); } - LocalDesc GetNativeType() + LocalDesc GetNativeType() override { LIMITED_METHOD_CONTRACT; return LocalDesc(); @@ -2250,13 +2296,13 @@ public: }; protected: - virtual LocalDesc GetNativeType(); - virtual LocalDesc GetManagedType(); - virtual void EmitReInitNative(ILCodeStream* pslILEmit); - virtual bool NeedsClearNative(); - virtual void EmitClearNative(ILCodeStream * pslILEmit); - virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit); - virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit); + LocalDesc GetNativeType() override; + LocalDesc GetManagedType() override; + void EmitReInitNative(ILCodeStream* pslILEmit) override; + bool NeedsClearNative() override; + void EmitClearNative(ILCodeStream * pslILEmit) override; + void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override; + void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override; }; #ifdef FEATURE_COMINTEROP @@ -2271,13 +2317,13 @@ public: }; protected: - virtual LocalDesc GetNativeType(); - virtual LocalDesc GetManagedType(); - virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit); - virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit); - virtual bool NeedsClearNative(); - virtual void EmitClearNative(ILCodeStream* pslILEmit); - virtual void EmitReInitNative(ILCodeStream* pslILEmit); + LocalDesc GetNativeType() override; + LocalDesc GetManagedType() override; + void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override; + void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override; + bool NeedsClearNative() override; + void EmitClearNative(ILCodeStream* pslILEmit) override; + void EmitReInitNative(ILCodeStream* pslILEmit) override; }; #endif // FEATURE_COMINTEROP @@ -2292,11 +2338,11 @@ public: }; protected: - virtual LocalDesc GetNativeType(); - virtual LocalDesc GetManagedType(); - virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit); - virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit); - virtual void EmitReInitNative(ILCodeStream* pslILEmit); + LocalDesc GetNativeType() override; + LocalDesc GetManagedType() override; + void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override; + void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override; + void EmitReInitNative(ILCodeStream* pslILEmit) override; }; @@ -2311,11 +2357,11 @@ public: }; protected: - virtual LocalDesc GetNativeType(); - virtual LocalDesc GetManagedType(); - virtual void EmitReInitNative(ILCodeStream* pslILEmit); - virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit); - virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit); + LocalDesc GetNativeType() override; + LocalDesc GetManagedType() override; + void EmitReInitNative(ILCodeStream* pslILEmit) override; + void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override; + void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override; }; @@ -2331,12 +2377,12 @@ public: }; protected: - virtual LocalDesc GetNativeType(); - virtual LocalDesc GetManagedType(); - virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit); - virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit); - virtual bool NeedsClearNative(); - virtual void EmitClearNative(ILCodeStream* pslILEmit); + LocalDesc GetNativeType() override; + LocalDesc GetManagedType() override; + void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override; + void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override; + bool NeedsClearNative() override; + void EmitClearNative(ILCodeStream* pslILEmit) override; }; #endif // FEATURE_COMINTEROP @@ -2352,10 +2398,10 @@ public: }; protected: - virtual LocalDesc GetNativeType(); - virtual LocalDesc GetManagedType(); - virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit); - virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit); + LocalDesc GetNativeType() override; + LocalDesc GetManagedType() override; + void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override; + void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override; }; @@ -2371,7 +2417,7 @@ public: }; protected: - virtual LocalDesc GetNativeType() + LocalDesc GetNativeType() override { LIMITED_METHOD_CONTRACT; @@ -2381,7 +2427,7 @@ protected: return LocalDesc(ELEMENT_TYPE_I); } - virtual LocalDesc GetManagedType() + LocalDesc GetManagedType() override { STANDARD_VM_CONTRACT; @@ -2391,13 +2437,13 @@ protected: return LocalDesc(MscorlibBinder::GetClass(CLASS__ID)); } - virtual bool NeedsClearNative() + bool NeedsClearNative() override { LIMITED_METHOD_CONTRACT; return (IsByref(m_dwMarshalFlags) && IsOut(m_dwMarshalFlags)); } - virtual void EmitClearNative(ILCodeStream* pslILEmit) + void EmitClearNative(ILCodeStream* pslILEmit) override { STANDARD_VM_CONTRACT; @@ -2406,7 +2452,7 @@ protected: pslILEmit->EmitCALL(METHOD__MARSHAL__FREE_CO_TASK_MEM, 1, 0); } - virtual void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit) + void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit) override { STANDARD_VM_CONTRACT; @@ -2420,7 +2466,7 @@ protected: } } - virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) + void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override { STANDARD_VM_CONTRACT; @@ -2437,7 +2483,7 @@ protected: } } - virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) + void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override { STANDARD_VM_CONTRACT; @@ -2480,10 +2526,10 @@ public: }; protected: - virtual LocalDesc GetNativeType(); - virtual LocalDesc GetManagedType(); - virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit); - virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit); + LocalDesc GetNativeType() override; + LocalDesc GetManagedType() override; + void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override; + void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override; }; class ILVBByValStrWMarshaler : public ILMarshaler @@ -2510,17 +2556,18 @@ public: LIMITED_METHOD_CONTRACT; } - virtual bool SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID); - virtual bool SupportsReturnMarshal(DWORD dwMarshalFlags, UINT* pErrorResID); + bool SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID) override; + bool SupportsReturnMarshal(DWORD dwMarshalFlags, UINT* pErrorResID) override; protected: - virtual LocalDesc GetNativeType(); - virtual LocalDesc GetManagedType(); - virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit); - virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit); - virtual bool NeedsClearNative(); - virtual void EmitClearNative(ILCodeStream* pslILEmit); - virtual bool IsNativePassedByRef(); + LocalDesc GetNativeType() override; + LocalDesc GetManagedType() override; + void EmitSetupArgumentForMarshalling(ILCodeStream* pslILEmit) override; + void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override; + void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override; + bool NeedsClearNative() override; + void EmitClearNative(ILCodeStream* pslILEmit) override; + bool IsNativePassedByRef() override; DWORD m_dwCCHLocal; DWORD m_dwLocalBuffer; @@ -2542,17 +2589,17 @@ public: LIMITED_METHOD_CONTRACT; } - virtual bool SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID); - virtual bool SupportsReturnMarshal(DWORD dwMarshalFlags, UINT* pErrorResID); + bool SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID) override; + bool SupportsReturnMarshal(DWORD dwMarshalFlags, UINT* pErrorResID) override; protected: - virtual LocalDesc GetNativeType(); - virtual LocalDesc GetManagedType(); - virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit); - virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit); - virtual bool NeedsClearNative(); - virtual void EmitClearNative(ILCodeStream* pslILEmit); - virtual bool IsNativePassedByRef(); + LocalDesc GetNativeType() override; + LocalDesc GetManagedType() override; + void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override; + void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override; + bool NeedsClearNative() override; + void EmitClearNative(ILCodeStream* pslILEmit) override; + bool IsNativePassedByRef() override; DWORD m_dwCCHLocal; }; @@ -2568,17 +2615,17 @@ public: }; protected: - virtual LocalDesc GetNativeType(); - virtual LocalDesc GetManagedType(); + LocalDesc GetNativeType() override; + LocalDesc GetManagedType() override; - virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit); + void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override; void EmitConvertCLRToHSTRINGReference(ILCodeStream* pslILEmit); void EmitConvertCLRToHSTRING(ILCodeStream* pslILEmit); - virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit); + void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override; - virtual bool NeedsClearNative(); - virtual void EmitClearNative(ILCodeStream* pslILEmit); + bool NeedsClearNative() override; + void EmitClearNative(ILCodeStream* pslILEmit) override; }; #endif // FEATURE_COMINTEROP @@ -2606,12 +2653,67 @@ public: } protected: - virtual LocalDesc GetManagedType(); - virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit); - virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit); + LocalDesc GetManagedType() override; + void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override; + void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override; }; +class ILWSTRMarshaler : public ILOptimizedAllocMarshaler +{ +public: + enum + { + c_fInOnly = FALSE, + c_nativeSize = sizeof(void *), + c_CLRSize = sizeof(OBJECTREF), + }; + enum + { + // If required buffer length > MAX_LOCAL_BUFFER_LENGTH, don't optimize by allocating memory on stack + MAX_LOCAL_BUFFER_LENGTH = (MAX_PATH_FNAME + 1) * 2 + }; + + ILWSTRMarshaler() + :ILOptimizedAllocMarshaler(METHOD__MARSHAL__FREE_CO_TASK_MEM) + { + LIMITED_METHOD_CONTRACT; + } + + + bool SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID) override + { + if (IsOut(dwMarshalFlags) && !IsByref(dwMarshalFlags) && IsCLRToNative(dwMarshalFlags)) + { + *pErrorResID = IDS_EE_BADMARSHAL_STRING_OUT; + return false; + } + + return true; + } + +protected: + LocalDesc GetNativeType() override; + LocalDesc GetManagedType() override; + + void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit) override; + void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override; + void EmitConvertSpaceAndContentsCLRToNative(ILCodeStream* pslILEmit) override; + void EmitConvertSpaceAndContentsCLRToNativeTemp(ILCodeStream* pslILEmit) override; + + void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit) override; + void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override; + + bool CanMarshalViaPinning() override + { + LIMITED_METHOD_CONTRACT; + return IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags) && IsIn(m_dwMarshalFlags) && !IsOut(m_dwMarshalFlags); + } + void EmitMarshalViaPinning(ILCodeStream* pslILEmit) override; + + static void EmitCheckManagedStringLength(ILCodeStream* pslILEmit); + static void EmitCheckNativeStringLength(ILCodeStream* pslILEmit); +}; class ILCSTRMarshaler : public ILOptimizedAllocMarshaler { @@ -2636,9 +2738,9 @@ public: } protected: - virtual LocalDesc GetManagedType(); - virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit); - virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit); + LocalDesc GetManagedType() override; + void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override; + void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override; }; class ILBSTRMarshaler : public ILOptimizedAllocMarshaler @@ -2664,9 +2766,9 @@ public: } protected: - virtual LocalDesc GetManagedType(); - virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit); - virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit); + LocalDesc GetManagedType() override; + void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override; + void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override; }; class ILAnsiBSTRMarshaler : public ILMarshaler @@ -2680,12 +2782,12 @@ public: }; protected: - virtual LocalDesc GetNativeType(); - virtual LocalDesc GetManagedType(); - virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit); - virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit); - virtual bool NeedsClearNative(); - virtual void EmitClearNative(ILCodeStream* pslILEmit); + LocalDesc GetNativeType() override; + LocalDesc GetManagedType() override; + void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override; + void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override; + bool NeedsClearNative() override; + void EmitClearNative(ILCodeStream* pslILEmit) override; }; class ILLayoutClassPtrMarshalerBase : public ILMarshaler @@ -2698,15 +2800,15 @@ public: }; protected: - virtual LocalDesc GetNativeType(); - virtual LocalDesc GetManagedType(); - virtual void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit); - virtual void EmitConvertSpaceCLRToNativeTemp(ILCodeStream* pslILEmit); - virtual void EmitConvertSpaceAndContentsCLRToNativeTemp(ILCodeStream* pslILEmit); - virtual void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit); - virtual bool NeedsClearNative(); - virtual void EmitClearNative(ILCodeStream* pslILEmit); - virtual void EmitClearNativeTemp(ILCodeStream* pslILEmit); + LocalDesc GetNativeType() override; + LocalDesc GetManagedType() override; + void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit) override; + void EmitConvertSpaceCLRToNativeTemp(ILCodeStream* pslILEmit) override; + void EmitConvertSpaceAndContentsCLRToNativeTemp(ILCodeStream* pslILEmit) override; + void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit) override; + bool NeedsClearNative() override; + void EmitClearNative(ILCodeStream* pslILEmit) override; + void EmitClearNativeTemp(ILCodeStream* pslILEmit) override; }; class ILLayoutClassPtrMarshaler : public ILLayoutClassPtrMarshalerBase @@ -2718,9 +2820,9 @@ public: }; protected: - virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit); - virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit); - virtual void EmitClearNativeContents(ILCodeStream * pslILEmit); + void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override; + void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override; + void EmitClearNativeContents(ILCodeStream * pslILEmit) override; }; class ILBlittablePtrMarshaler : public ILLayoutClassPtrMarshalerBase @@ -2731,10 +2833,12 @@ public: c_fInOnly = FALSE, }; -protected: - virtual void EmitMarshalArgumentCLRToNative(); - virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit); - virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit); +protected: + void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override; + void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override; + void EmitConvertSpaceAndContentsCLRToNativeTemp(ILCodeStream* pslILEmit) override; +private: + bool CanUsePinnedLayoutClass(); }; class ILBlittableValueClassWithCopyCtorMarshaler : public ILMarshaler @@ -2783,11 +2887,14 @@ public: }; protected: - virtual LocalDesc GetNativeType(); - virtual LocalDesc GetManagedType(); - virtual bool SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID); - virtual void EmitMarshalArgumentCLRToNative(); - virtual void EmitMarshalArgumentNativeToCLR(); + LocalDesc GetNativeType() override; + LocalDesc GetManagedType() override; + bool SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID) override; + void EmitConvertSpaceAndContentsCLRToNative(ILCodeStream* pslILEmit) override; + void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override; + +private: + DWORD m_dwVaListSizeLocalNum; }; class ILArrayWithOffsetMarshaler : public ILMarshaler @@ -2809,15 +2916,15 @@ public: } protected: - virtual LocalDesc GetNativeType(); - virtual LocalDesc GetManagedType(); - virtual bool SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID); + LocalDesc GetNativeType() override; + LocalDesc GetManagedType() override; + bool SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID) override; - virtual void EmitConvertSpaceAndContentsCLRToNativeTemp(ILCodeStream* pslILEmit); - virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit); - virtual void EmitClearNativeTemp(ILCodeStream* pslILEmit); + void EmitConvertSpaceAndContentsCLRToNativeTemp(ILCodeStream* pslILEmit) override; + void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override; + void EmitClearNativeTemp(ILCodeStream* pslILEmit) override; - +private: DWORD m_dwCountLocalNum; DWORD m_dwOffsetLocalNum; DWORD m_dwPinnedLocalNum; @@ -2832,26 +2939,46 @@ public: c_CLRSize = sizeof(OBJECTREF), }; - ILAsAnyMarshalerBase() : - m_dwMarshalerLocalNum(-1) +protected: + + virtual bool IsAnsi() const = 0; + LocalDesc GetNativeType() override final; + LocalDesc GetManagedType() override final; + void EmitCreateMngdMarshaler(ILCodeStream* pslILEmit) override final; + bool SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID) override final; + bool SupportsReturnMarshal(DWORD dwMarshalFlags, UINT* pErrorResID) override final; + void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override final; + void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override final; + bool NeedsClearNative() override final; + void EmitClearNativeTemp(ILCodeStream* pslILEmit) override final; + bool AlwaysConvertByValContentsCLRToNative() override final { LIMITED_METHOD_CONTRACT; + return true; } -protected: +private: + // These flags correspond to System.StubHelpers.AsAnyMarshaler.AsAnyFlags.In and Out respectively. + // We have to pre-calculate the flags and emit them into the IL stream since the AsAny marshalers + // are effectively lazily resolved based on the runtime type of the object. static const BYTE ML_IN = 0x10; static const BYTE ML_OUT = 0x20; - virtual bool IsAnsi() = 0; - virtual LocalDesc GetNativeType(); - virtual LocalDesc GetManagedType(); - virtual bool SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID); - virtual bool SupportsReturnMarshal(DWORD dwMarshalFlags, UINT* pErrorResID); - virtual void EmitMarshalArgumentCLRToNative(); - virtual bool NeedsClearNative(); - virtual void EmitClearNativeTemp(ILCodeStream* pslILEmit); + DWORD GetAsAnyFlags() const + { + BYTE inout = (IsIn(m_dwMarshalFlags) ? ML_IN : 0) | (IsOut(m_dwMarshalFlags) ? ML_OUT : 0); + BYTE fIsAnsi = IsAnsi() ? 1 : 0; + BYTE fBestFit = m_pargs->m_pMarshalInfo->GetBestFitMapping(); + BYTE fThrow = m_pargs->m_pMarshalInfo->GetThrowOnUnmappableChar(); + + DWORD dwFlags = 0; - DWORD m_dwMarshalerLocalNum; + dwFlags |= inout << 24; + dwFlags |= fIsAnsi << 16; + dwFlags |= fThrow << 8; + dwFlags |= fBestFit << 0; + return dwFlags; + } }; class ILAsAnyWMarshaler : public ILAsAnyMarshalerBase @@ -2863,7 +2990,7 @@ public: }; protected: - virtual bool IsAnsi() + bool IsAnsi() const override { return false; } @@ -2878,7 +3005,7 @@ public: }; protected: - virtual bool IsAnsi() + bool IsAnsi() const override { return true; } @@ -2913,38 +3040,38 @@ public: } protected: - virtual LocalDesc GetNativeType(); - virtual LocalDesc GetManagedType(); + LocalDesc GetNativeType() override; + LocalDesc GetManagedType() override; - virtual void EmitCreateMngdMarshaler(ILCodeStream* pslILEmit) = 0; + void EmitCreateMngdMarshaler(ILCodeStream* pslILEmit) override = 0; virtual void EmitCallMngdMarshalerMethod(ILCodeStream* pslILEmit, MethodDesc *pMD); - virtual void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit) + void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit) override { WRAPPER_NO_CONTRACT; EmitCallMngdMarshalerMethod(pslILEmit, GetConvertSpaceToManagedMethod()); } - virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) + void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override { WRAPPER_NO_CONTRACT; EmitCallMngdMarshalerMethod(pslILEmit, GetConvertContentsToManagedMethod()); } - virtual void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit) + void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit) override { WRAPPER_NO_CONTRACT; EmitCallMngdMarshalerMethod(pslILEmit, GetConvertSpaceToNativeMethod()); } - virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) + void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override { WRAPPER_NO_CONTRACT; EmitCallMngdMarshalerMethod(pslILEmit, GetConvertContentsToNativeMethod()); } - virtual bool NeedsClearNative() + bool NeedsClearNative() override { LIMITED_METHOD_CONTRACT; @@ -2956,20 +3083,19 @@ protected: return false; } - virtual void EmitClearNative(ILCodeStream* pslILEmit) + void EmitClearNative(ILCodeStream* pslILEmit) override { WRAPPER_NO_CONTRACT; EmitCallMngdMarshalerMethod(pslILEmit, GetClearNativeMethod()); } - virtual void EmitClearNativeContents(ILCodeStream* pslILEmit) + void EmitClearNativeContents(ILCodeStream* pslILEmit) override { WRAPPER_NO_CONTRACT; EmitCallMngdMarshalerMethod(pslILEmit, GetClearNativeContentsMethod()); } - - virtual bool NeedsClearCLR() + bool NeedsClearCLR() override { LIMITED_METHOD_CONTRACT; @@ -2981,7 +3107,7 @@ protected: return false; } - virtual void EmitClearCLR(ILCodeStream* pslILEmit) + void EmitClearCLR(ILCodeStream* pslILEmit) override { WRAPPER_NO_CONTRACT; EmitCallMngdMarshalerMethod(pslILEmit, GetClearManagedMethod()); @@ -3027,27 +3153,26 @@ public: m_dwSavedSizeArg = LOCAL_NUM_UNUSED; } - virtual void EmitMarshalArgumentCLRToNative(); - virtual void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit); - virtual void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit); - virtual void EmitClearNative(ILCodeStream* pslILEmit); - virtual void EmitClearNativeContents(ILCodeStream* pslILEmit); - virtual void EmitMarshalArgumentNativeToCLRByref(); - virtual void EmitMarshalArgumentCLRToNativeByref(); + bool CanMarshalViaPinning() override; + + void EmitMarshalViaPinning(ILCodeStream* pslILEmit) override; + void EmitSetupArgumentForMarshalling(ILCodeStream* pslILEmit) override; + void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit) override; + void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit) override; + void EmitClearNative(ILCodeStream* pslILEmit) override; + void EmitClearNativeContents(ILCodeStream* pslILEmit) override; protected: - bool UsePinnedArraySpecialCase(); - BOOL CheckSizeParamIndexArg(const CREATE_MARSHALER_CARRAY_OPERANDS &mops, CorElementType *pElementType); // Calculate element count and load it on evaluation stack void EmitLoadElementCount(ILCodeStream* pslILEmit); - virtual void EmitCreateMngdMarshaler(ILCodeStream* pslILEmit); + void EmitCreateMngdMarshaler(ILCodeStream* pslILEmit) override; void EmitLoadNativeSize(ILCodeStream* pslILEmit); - void EmitNewSavedSizeArgLocal(); + void EmitNewSavedSizeArgLocal(ILCodeStream* pslILEmit); private : DWORD m_dwSavedSizeArg; @@ -3106,11 +3231,11 @@ public: protected: - virtual void EmitCreateMngdMarshaler(ILCodeStream* pslILEmit); - virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit); - virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit); + void EmitCreateMngdMarshaler(ILCodeStream* pslILEmit) override; + void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override; + void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override; - virtual void EmitReInitNative(ILCodeStream* pslILEmit) + void EmitReInitNative(ILCodeStream* pslILEmit) override { CONTRACTL { @@ -3191,25 +3316,25 @@ public: } protected: - virtual LocalDesc GetNativeType(); - virtual LocalDesc GetManagedType(); - - virtual void EmitCreateMngdMarshaler(ILCodeStream* pslILEmit); - virtual void EmitMarshalArgumentCLRToNative(); - virtual void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit); - virtual void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit); - virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit); - virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit); - virtual void EmitClearNative(ILCodeStream* pslILEmit); - virtual void EmitClearNativeContents(ILCodeStream* pslILEmit); + LocalDesc GetNativeType() override; + LocalDesc GetManagedType() override; + bool CanMarshalViaPinning() override; + + void EmitMarshalViaPinning(ILCodeStream* pslILEmit) override; + void EmitCreateMngdMarshaler(ILCodeStream* pslILEmit) override; + void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit) override; + void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit) override; + void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override; + void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override; + void EmitClearNative(ILCodeStream* pslILEmit) override; + void EmitClearNativeContents(ILCodeStream* pslILEmit) override; private: - bool CanUsePinnedArray(); void EmitLoadNativeArrayLength(ILCodeStream *pslILEmit); - virtual MethodDesc *GetConvertContentsToManagedMethod(); - virtual MethodDesc *GetConvertContentsToNativeMethod(); - virtual MethodDesc *GetClearNativeContentsMethod(); + MethodDesc *GetConvertContentsToManagedMethod() override; + MethodDesc *GetConvertContentsToNativeMethod() override; + MethodDesc *GetClearNativeContentsMethod() override; MethodDesc *GetExactMarshalerMethod(MethodDesc *pGenericMD); }; @@ -3260,7 +3385,7 @@ public: } protected: - virtual void EmitCreateMngdMarshaler(ILCodeStream* pslILEmit); + void EmitCreateMngdMarshaler(ILCodeStream* pslILEmit) override; }; class MngdRefCustomMarshaler @@ -3272,8 +3397,6 @@ public: static FCDECL3(void, ClearNative, MngdRefCustomMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome); static FCDECL3(void, ClearManaged, MngdRefCustomMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome); - static void DoClearNativeContents(MngdRefCustomMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome); - CustomMarshalerHelper* m_pCMHelper; }; @@ -3293,13 +3416,13 @@ public: static void EmitConvertWinRTUriToCLRUri(ILCodeStream* pslILEmit, LoaderAllocator* pLoader); protected: - virtual LocalDesc GetNativeType(); - virtual LocalDesc GetManagedType(); + LocalDesc GetNativeType() override; + LocalDesc GetManagedType() override; - virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit); - virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit); + void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override; + void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override; - virtual bool NeedsClearNative(); + bool NeedsClearNative() override; void EmitClearNative(ILCodeStream* pslILEmit); }; @@ -3317,13 +3440,13 @@ public: static void EmitConvertWinRTEventArgsToCLREventArgs(ILCodeStream* pslILEmit, LoaderAllocator* pLoader); protected: - virtual LocalDesc GetNativeType(); - virtual LocalDesc GetManagedType(); + LocalDesc GetNativeType() override; + LocalDesc GetManagedType() override; - virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit); - virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit); + void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override; + void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override; - virtual bool NeedsClearNative(); + bool NeedsClearNative() override; void EmitClearNative(ILCodeStream* pslILEmit); }; @@ -3341,13 +3464,13 @@ public: static void EmitConvertWinRTEventArgsToCLREventArgs(ILCodeStream* pslILEmit, LoaderAllocator* pLoader); protected: - virtual LocalDesc GetNativeType(); - virtual LocalDesc GetManagedType(); + LocalDesc GetNativeType() override; + LocalDesc GetManagedType() override; - virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit); - virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit); + void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override; + void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override; - virtual bool NeedsClearNative(); + bool NeedsClearNative() override; void EmitClearNative(ILCodeStream* pslILEmit); }; @@ -3362,14 +3485,14 @@ public: }; protected: - virtual LocalDesc GetNativeType(); - virtual LocalDesc GetManagedType(); + LocalDesc GetNativeType() override; + LocalDesc GetManagedType() override; - virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit); - virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit); + void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override; + void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override; - virtual bool NeedsClearNative(); - virtual void EmitReInitNative(ILCodeStream* pslILEmit); + bool NeedsClearNative() override; + void EmitReInitNative(ILCodeStream* pslILEmit) override; }; class ILNullableMarshaler : public ILMarshaler @@ -3383,12 +3506,12 @@ public: }; protected: - virtual LocalDesc GetNativeType(); - virtual LocalDesc GetManagedType(); - virtual bool NeedsClearNative(); - virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit); - virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit); - virtual void EmitClearNative(ILCodeStream* pslILEmit); + LocalDesc GetNativeType() override; + LocalDesc GetManagedType() override; + bool NeedsClearNative() override; + void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override; + void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override; + void EmitClearNative(ILCodeStream* pslILEmit) override; private: MethodDesc *GetExactMarshalerMethod(MethodDesc *pGenericMD); @@ -3405,15 +3528,15 @@ public: }; protected: - virtual LocalDesc GetNativeType(); - virtual LocalDesc GetManagedType(); + LocalDesc GetNativeType() override; + LocalDesc GetManagedType() override; - virtual void EmitConvertContentsCLRToNative(ILCodeStream * pslILEmit); - virtual void EmitConvertContentsNativeToCLR(ILCodeStream * pslILEmit); + void EmitConvertContentsCLRToNative(ILCodeStream * pslILEmit) override; + void EmitConvertContentsNativeToCLR(ILCodeStream * pslILEmit) override; - virtual bool NeedsClearNative(); - virtual void EmitClearNative(ILCodeStream * pslILEmit); - virtual void EmitReInitNative(ILCodeStream * pslILEmit); + bool NeedsClearNative() override; + void EmitClearNative(ILCodeStream * pslILEmit) override; + void EmitReInitNative(ILCodeStream * pslILEmit) override; }; class ILHResultExceptionMarshaler : public ILMarshaler @@ -3427,13 +3550,13 @@ public: }; protected: - virtual LocalDesc GetNativeType(); - virtual LocalDesc GetManagedType(); + LocalDesc GetNativeType() override; + LocalDesc GetManagedType() override; - virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit); - virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit); + void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override; + void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override; - virtual bool NeedsClearNative(); + bool NeedsClearNative() override; }; class ILKeyValuePairMarshaler : public ILMarshaler @@ -3447,12 +3570,12 @@ public: }; protected: - virtual LocalDesc GetNativeType(); - virtual LocalDesc GetManagedType(); - virtual bool NeedsClearNative(); - virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit); - virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit); - virtual void EmitClearNative(ILCodeStream* pslILEmit); + LocalDesc GetNativeType() override; + LocalDesc GetManagedType() override; + bool NeedsClearNative() override; + void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override; + void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override; + void EmitClearNative(ILCodeStream* pslILEmit) override; private: MethodDesc *GetExactMarshalerMethod(MethodDesc *pGenericMD); diff --git a/src/vm/metasig.h b/src/vm/metasig.h index 1540280..c468f48 100644 --- a/src/vm/metasig.h +++ b/src/vm/metasig.h @@ -587,7 +587,7 @@ DEFINE_METASIG(SM(RefObject_Object_Object_RetObject, r(j) j j, j)) DEFINE_METASIG_T(SM(RefCleanupWorkListElement_RetVoid, r(C(CLEANUP_WORK_LIST_ELEMENT)), v)) DEFINE_METASIG_T(SM(RefCleanupWorkListElement_SafeHandle_RetIntPtr, r(C(CLEANUP_WORK_LIST_ELEMENT)) C(SAFE_HANDLE), I)) -DEFINE_METASIG_T(SM(RefCleanupWorkListElement_Delegate_RetVoid, r(C(CLEANUP_WORK_LIST_ELEMENT)) C(DELEGATE), v)) +DEFINE_METASIG_T(SM(RefCleanupWorkListElement_Obj_RetVoid, r(C(CLEANUP_WORK_LIST_ELEMENT)) j, v)) #ifdef FEATURE_ICASTABLE DEFINE_METASIG_T(SM(ICastable_RtType_RefException_RetBool, C(ICASTABLE) C(CLASS) r(C(EXCEPTION)), F)) diff --git a/src/vm/mlinfo.cpp b/src/vm/mlinfo.cpp index 4e5ddf9..607463a 100644 --- a/src/vm/mlinfo.cpp +++ b/src/vm/mlinfo.cpp @@ -3269,7 +3269,7 @@ void MarshalInfo::GenerateArgumentIL(NDirectStubLinker* psl, pcsMarshal->EmitNOP("// } argument"); pcsUnmarshal->EmitNOP("// } argument"); - pMarshaler->EmitSetupArgument(pcsDispatch); + pMarshaler->EmitSetupArgumentForDispatch(pcsDispatch); if (m_paramidx == 0) { CorCallingConvention callConv = psl->GetStubTargetCallingConv(); @@ -4689,7 +4689,7 @@ void MarshalInfo::MarshalHiddenLengthArgument(NDirectStubLinker *psl, BOOL manag if (managedToNative) { ILCodeStream* pcsDispatch = psl->GetDispatchCodeStream(); - pHiddenLengthMarshaler->EmitSetupArgument(pcsDispatch); + pHiddenLengthMarshaler->EmitSetupArgumentForDispatch(pcsDispatch); } } diff --git a/src/vm/mscorlib.h b/src/vm/mscorlib.h index 403b27b..201db98 100644 --- a/src/vm/mscorlib.h +++ b/src/vm/mscorlib.h @@ -973,7 +973,7 @@ DEFINE_METHOD(STUBHELPERS, CLEAR_LAST_ERROR, ClearLastError, DEFINE_METHOD(STUBHELPERS, THROW_INTEROP_PARAM_EXCEPTION, ThrowInteropParamException, SM_Int_Int_RetVoid) DEFINE_METHOD(STUBHELPERS, ADD_TO_CLEANUP_LIST_SAFEHANDLE, AddToCleanupList, SM_RefCleanupWorkListElement_SafeHandle_RetIntPtr) -DEFINE_METHOD(STUBHELPERS, ADD_TO_CLEANUP_LIST_DELEGATE, AddToCleanupList, SM_RefCleanupWorkListElement_Delegate_RetVoid) +DEFINE_METHOD(STUBHELPERS, KEEP_ALIVE_VIA_CLEANUP_LIST, KeepAliveViaCleanupList, SM_RefCleanupWorkListElement_Obj_RetVoid) DEFINE_METHOD(STUBHELPERS, DESTROY_CLEANUP_LIST, DestroyCleanupList, SM_RefCleanupWorkListElement_RetVoid) DEFINE_METHOD(STUBHELPERS, GET_HR_EXCEPTION_OBJECT, GetHRExceptionObject, SM_Int_RetException) DEFINE_METHOD(STUBHELPERS, CREATE_CUSTOM_MARSHALER_HELPER, CreateCustomMarshalerHelper, SM_IntPtr_Int_IntPtr_RetIntPtr)