ILMarshaler Refactor (#21227)
authorJeremy Koritzinsky <jekoritz@microsoft.com>
Wed, 19 Jun 2019 00:26:10 +0000 (17:26 -0700)
committerGitHub <noreply@github.com>
Wed, 19 Jun 2019 00:26:10 +0000 (17:26 -0700)
* 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.

src/System.Private.CoreLib/src/System/StubHelpers.cs
src/vm/fieldmarshaler.cpp
src/vm/ilmarshalers.cpp
src/vm/ilmarshalers.h
src/vm/metasig.h
src/vm/mlinfo.cpp
src/vm/mscorlib.h

index 0f9ee4e..d84d1b7 100644 (file)
@@ -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);
         }
 
index 8691f2b..c1f512f 100644 (file)
@@ -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[] =
         {
index 19db7df..146ad7c 100644 (file)
@@ -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 <dwHandleAddRefedLocalNum> = false
-    ILCodeStream *pcsSetup = m_pslNDirect->GetSetupCodeStream();
-    DWORD dwHandleAddRefedLocalNum = pcsSetup->NewLocal(ELEMENT_TYPE_BOOLEAN);
-    
-    pcsSetup->EmitLDC(0);
-    pcsSetup->EmitSTLOC(dwHandleAddRefedLocalNum);
-
-    // <nativeHandle> = StubHelpers::SafeHandleAddRef(<managedSH>, ref <dwHandleAddRefedLocalNum>)
-    EmitLoadManagedValue(m_pcsMarshal);
-    m_pcsMarshal->EmitLDLOCA(dwHandleAddRefedLocalNum);
-    m_pcsMarshal->EmitCALL(METHOD__STUBHELPERS__SAFE_HANDLE_ADD_REF, 2, 1);
-    EmitStoreNativeValue(m_pcsMarshal);
-
-    // cleanup:
-    // if (<dwHandleAddRefedLocalNum>) StubHelpers.SafeHandleRelease(<managedSH>)
-    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;
 
index 61ff142..e2f81c3 100644 (file)
@@ -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);
index 1540280..c468f48 100644 (file)
@@ -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))
index 4e5ddf9..607463a 100644 (file)
@@ -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);
     }
 }
 
index 403b27b..201db98 100644 (file)
@@ -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)