Revert "ILMarshaler Refactor (#21227)" (#25292)
authorJeremy Koritzinsky <jkoritzinsky@gmail.com>
Fri, 21 Jun 2019 00:57:58 +0000 (17:57 -0700)
committerJan Kotas <jkotas@microsoft.com>
Fri, 21 Jun 2019 00:57:58 +0000 (17:57 -0700)
This reverts commit 70febbad4bbe23326c26480b2848cdfe9fc8450c.

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 d84d1b7..0f9ee4e 100644 (file)
@@ -1485,21 +1485,21 @@ namespace System.StubHelpers
         }
     }
 
-    // Keeps an object instance alive across the full Managed->Native call.
+    // Keeps a Delegate 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 KeepAliveCleanupWorkListElement : CleanupWorkListElement
+    internal sealed class DelegateCleanupWorkListElement : CleanupWorkListElement
     {
-        public KeepAliveCleanupWorkListElement(object obj)
+        public DelegateCleanupWorkListElement(Delegate del)
         {
-            m_obj = obj;
+            m_del = del;
         }
 
-        private object m_obj;
+        private Delegate m_del;
 
         protected override void DestroyCore()
         {
-            GC.KeepAlive(m_obj);
+            GC.KeepAlive(m_del);
         }
     }
 
@@ -1562,9 +1562,9 @@ namespace System.StubHelpers
             return element.AddRef();
         }
 
-        internal static void KeepAliveViaCleanupList(ref CleanupWorkListElement pCleanupWorkList, object obj)
+        internal static void AddToCleanupList(ref CleanupWorkListElement pCleanupWorkList, Delegate del)
         {
-            KeepAliveCleanupWorkListElement element = new KeepAliveCleanupWorkListElement(obj);
+            DelegateCleanupWorkListElement element = new DelegateCleanupWorkListElement(del);
             CleanupWorkListElement.AddToCleanupList(ref pCleanupWorkList, element);
         }
 
index c1f512f..8691f2b 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__KEEP_ALIVE_VIA_CLEANUP_LIST);
+        MethodDescCallSite AddToCleanupList(METHOD__STUBHELPERS__ADD_TO_CLEANUP_LIST_DELEGATE);
 
         ARG_SLOT args[] =
         {
index 146ad7c..19db7df 100644 (file)
@@ -78,17 +78,17 @@ void ILReflectionObjectMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* p
 
     if (IsCLRToNative(m_dwMarshalFlags))
     {
-        EmitLoadCleanupWorkList(pslILEmit);
+        // keep the object alive across the call-out to native
         if (tokStruct__m_object != 0)
         {
-            EmitLoadManagedHomeAddr(pslILEmit);
-            pslILEmit->EmitLDFLD(tokStruct__m_object);
+            EmitLoadManagedHomeAddr(m_pcsUnmarshal);
+            m_pcsUnmarshal->EmitLDFLD(tokStruct__m_object);
         }
         else
         {
-            EmitLoadManagedValue(pslILEmit);
+            EmitLoadManagedValue(m_pcsUnmarshal);
         }
-        pslILEmit->EmitCALL(METHOD__STUBHELPERS__KEEP_ALIVE_VIA_CLEANUP_LIST, 2, 0);
+        m_pcsUnmarshal->EmitCALL(METHOD__GC__KEEP_ALIVE, 1, 0);
     }
 }
 
@@ -128,11 +128,18 @@ 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)
@@ -301,6 +308,41 @@ 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)
@@ -321,6 +363,8 @@ void ILWSTRMarshaler::EmitConvertSpaceAndContentsCLRToNative(ILCodeStream* pslIL
 {
     STANDARD_VM_CONTRACT;
 
+    INDEBUG(m_fCoMemoryAllocated = true);
+
     ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
     DWORD dwLengthLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
     
@@ -356,87 +400,73 @@ void ILWSTRMarshaler::EmitConvertSpaceAndContentsCLRToNative(ILCodeStream* pslIL
     pslILEmit->EmitLabel(pNullRefLabel);
 }
 
-void ILWSTRMarshaler::EmitMarshalViaPinning(ILCodeStream* pslILEmit)
+void ILWSTRMarshaler::EmitConvertSpaceAndContentsCLRToNativeTemp(ILCodeStream* pslILEmit)
 {
     STANDARD_VM_CONTRACT;
 
-    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->EmitSTLOC(dwPinnedLocal);
-    pslILEmit->EmitLDLOC(dwPinnedLocal);
-    pslILEmit->EmitLDFLDA(fieldDef);
-    EmitStoreNativeValue(pslILEmit);
-
-    EmitLogNativeArgumentsIfNeeded(pslILEmit, dwPinnedLocal);
-
-    pslILEmit->EmitLabel(pNullRefLabel);
-}
+    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);
 
-void ILWSTRMarshaler::EmitConvertSpaceAndContentsCLRToNativeTemp(ILCodeStream* pslILEmit)
-{
-    STANDARD_VM_CONTRACT;
+        EmitLoadManagedValue(pslILEmit);
+        pslILEmit->EmitBRFALSE(pNullRefLabel);
 
-    ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
-    DWORD dwLengthLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
-    
-    pslILEmit->EmitLoadNullPtr();
-    EmitStoreNativeValue(pslILEmit);
-    
-    EmitLoadManagedValue(pslILEmit);
-    pslILEmit->EmitBRFALSE(pNullRefLabel);
-    
-    EmitLoadManagedValue(pslILEmit);
-    EmitCheckManagedStringLength(pslILEmit);
+        EmitLoadManagedValue(pslILEmit);
+        pslILEmit->EmitSTLOC(dwPinnedLocal);
+        pslILEmit->EmitLDLOC(dwPinnedLocal);
+        pslILEmit->EmitLDFLDA(fieldDef);
+        EmitStoreNativeValue(pslILEmit);
 
-    pslILEmit->EmitSTLOC(dwLengthLocalNum);
+        if (g_pConfig->InteropLogArguments())
+        {
+            m_pslNDirect->EmitLogNativeArgument(pslILEmit, dwPinnedLocal);
+        }
 
-    ILCodeLabel* pAllocRejoin = pslILEmit->NewCodeLabel();
-    ILCodeLabel* pNoOptimize = pslILEmit->NewCodeLabel();
-    m_dwLocalBuffer = pslILEmit->NewLocal(ELEMENT_TYPE_I);
+        pslILEmit->EmitLabel(pNullRefLabel);
 
-    // LocalBuffer = 0
-    pslILEmit->EmitLoadNullPtr();
-    pslILEmit->EmitSTLOC(m_dwLocalBuffer);
+    }
+    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);
 
-    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);
+        // cb
 
-    pslILEmit->EmitLOCALLOC();
-    pslILEmit->EmitDUP();
-    pslILEmit->EmitSTLOC(m_dwLocalBuffer);
-    pslILEmit->EmitBR(pAllocRejoin);
+        pslILEmit->EmitDUP();
+        pslILEmit->EmitSTLOC(dwLengthLocalNum);
 
-    pslILEmit->EmitLabel(pNoOptimize);
+        // cb
 
-    pslILEmit->EmitCALL(METHOD__MARSHAL__ALLOC_CO_TASK_MEM, 1, 1);
-    pslILEmit->EmitLabel(pAllocRejoin);
-    EmitStoreNativeValue(pslILEmit);
+        pslILEmit->EmitLOCALLOC();              // @TODO: add a non-localloc path for large strings
+        EmitStoreNativeValue(pslILEmit);
 
-    EmitLoadManagedValue(pslILEmit);
-    EmitLoadNativeValue(pslILEmit);
+        EmitLoadManagedValue(pslILEmit);
+        EmitLoadNativeValue(pslILEmit);
 
-    // src, dst
+        // 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);
+        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);
+    }
 }
 
 //
@@ -1100,7 +1130,7 @@ void ILValueClassMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEm
     pslILEmit->EmitLDTOKEN(managedVCToken); // pMT
     pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1); // Convert RTH to IntPtr
 
-    EmitLoadCleanupWorkList(pslILEmit);
+    m_pslNDirect->LoadCleanupWorkList(pslILEmit);
     pslILEmit->EmitCALL(METHOD__VALUECLASSMARSHALER__CONVERT_TO_NATIVE, 4, 0);        // void ConvertToNative(IntPtr dst, IntPtr src, IntPtr pMT, ref CleanupWorkListElement pCleanupWorkList)
 }
 
@@ -1368,9 +1398,8 @@ 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
-        EmitLoadCleanupWorkList(pslILEmit);
-        EmitLoadManagedValue(pslILEmit);
-        pslILEmit->EmitCALL(METHOD__STUBHELPERS__KEEP_ALIVE_VIA_CLEANUP_LIST, 2, 0);
+        EmitLoadManagedValue(m_pcsUnmarshal);
+        m_pcsUnmarshal->EmitCALL(METHOD__GC__KEEP_ALIVE, 1, 0);
     }
 }
 
@@ -1570,17 +1599,16 @@ 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);
@@ -1985,7 +2013,10 @@ void ILHSTRINGMarshaler::EmitConvertCLRToHSTRINGReference(ILCodeStream* pslILEmi
     pslILEmit->EmitLDLOCA(dwHStringHeaderLocal);
     pslILEmit->EmitCALL(METHOD__HSTRINGMARSHALER__CONVERT_TO_NATIVE_REFERENCE, 2, 1);
 
-    EmitLogNativeArgumentsIfNeeded(pslILEmit, dwPinnedStringLocal);
+    if (g_pConfig->InteropLogArguments())
+    {
+        m_pslNDirect->EmitLogNativeArgument(pslILEmit, dwPinnedStringLocal);
+    }
 
     EmitStoreNativeValue(pslILEmit);
 }
@@ -2376,7 +2407,7 @@ void ILLayoutClassPtrMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* psl
     EmitLoadManagedValue(pslILEmit);
     EmitLoadNativeValue(pslILEmit);
 
-    EmitLoadCleanupWorkList(pslILEmit);
+    m_pslNDirect->LoadCleanupWorkList(pslILEmit);
 
     // static void FmtClassUpdateNativeInternal(object obj, byte* pNative, IntPtr pOptionalCleanupList);
 
@@ -2460,41 +2491,43 @@ void ILBlittablePtrMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslIL
     pslILEmit->EmitLabel(pNullRefLabel);
 }
 
-bool ILBlittablePtrMarshaler::CanUsePinnedLayoutClass()
-{
-    return IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags);
-}
-
-void ILBlittablePtrMarshaler::EmitConvertSpaceAndContentsCLRToNativeTemp(ILCodeStream* pslILEmit)
+void ILBlittablePtrMarshaler::EmitMarshalArgumentCLRToNative()
 {
-    STANDARD_VM_CONTRACT;
-
-    if (CanUsePinnedLayoutClass())
+    CONTRACTL
     {
-        ILCodeLabel* pSkipAddLabel = pslILEmit->NewCodeLabel();
-        LocalDesc managedTypePinned = GetManagedType();
-        managedTypePinned.MakePinned();
-        DWORD dwPinnedLocal = pslILEmit->NewLocal(managedTypePinned);
+        STANDARD_VM_CHECK;
+        PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
+    }
+    CONTRACTL_END;
 
-        EmitLoadManagedValue(pslILEmit);
+    EmitSetupSigAndDefaultHomesCLRToNative();
 
-        pslILEmit->EmitSTLOC(dwPinnedLocal);
-        pslILEmit->EmitLDLOC(dwPinnedLocal);
-        pslILEmit->EmitCONV_U();
-        pslILEmit->EmitDUP();
-        pslILEmit->EmitBRFALSE(pSkipAddLabel);
-        pslILEmit->EmitLDC(Object::GetOffsetOfFirstField());
-        pslILEmit->EmitADD();
-        pslILEmit->EmitLabel(pSkipAddLabel);
+    //
+    // marshal
+    //
 
-        EmitLogNativeArgumentsIfNeeded(pslILEmit, dwPinnedLocal);
+    ILCodeLabel* pSkipAddLabel = m_pcsMarshal->NewCodeLabel();
+    LocalDesc managedTypePinned = GetManagedType();
+    managedTypePinned.MakePinned();
+    DWORD dwPinnedLocal = m_pcsMarshal->NewLocal(managedTypePinned);
 
-        EmitStoreNativeValue(pslILEmit);
-    }
-    else
+    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);
+
+    if (g_pConfig->InteropLogArguments())
     {
-        ILLayoutClassPtrMarshalerBase::EmitConvertSpaceAndContentsCLRToNativeTemp(pslILEmit);
+        m_pslNDirect->EmitLogNativeArgument(m_pcsMarshal, dwPinnedLocal);
     }
+
+    EmitStoreNativeValue(m_pcsMarshal);
 }
 
 
@@ -2565,6 +2598,78 @@ 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,
@@ -2588,9 +2693,10 @@ 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;
 
@@ -2735,13 +2841,14 @@ MarshalerOverrideStatus ILSafeHandleMarshaler::ArgumentOverride(NDirectStubLinke
         }
         else
         {
-            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);
+            // 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;
         }
 
         return OVERRIDDEN;
@@ -3299,35 +3406,56 @@ bool ILArgIteratorMarshaler::SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT*
     return true;
 }
 
-void ILArgIteratorMarshaler::EmitConvertSpaceAndContentsCLRToNative(ILCodeStream* pslILEmit)
+void ILArgIteratorMarshaler::EmitMarshalArgumentCLRToNative()
 {
-    STANDARD_VM_CONTRACT;
+    CONTRACTL
+    {
+        STANDARD_VM_CHECK;
+        PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
+    }
+    CONTRACTL_END;
 
-    // Allocate enough memory for va_list
-    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);
+    EmitSetupSigAndDefaultHomesCLRToNative();
+    
+    //
+    // marshal
+    //
 
-    // 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);
+    // 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);
 }
 
-void ILArgIteratorMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
+void ILArgIteratorMarshaler::EmitMarshalArgumentNativeToCLR()
 {
-    EmitLoadNativeValue(pslILEmit);
-    EmitLoadManagedHomeAddr(pslILEmit);
+    CONTRACTL
+    {
+        STANDARD_VM_CHECK;
+        PRECONDITION(!IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
+    }
+    CONTRACTL_END;
+
+    EmitSetupSigAndDefaultHomesNativeToCLR();
+    
+    EmitLoadNativeValue(m_pcsMarshal);
+    EmitLoadManagedHomeAddr(m_pcsMarshal);
 
     // void MarshalToManagedVaList(va_list va, VARARGS *dataout)
-    pslILEmit->EmitCALL(METHOD__STUBHELPERS__MARSHAL_TO_MANAGED_VA_LIST_INTERNAL, 2, 0);
+    m_pcsMarshal->EmitCALL(METHOD__STUBHELPERS__MARSHAL_TO_MANAGED_VA_LIST_INTERNAL, 2, 0);    
 }
 
+
 LocalDesc ILArrayWithOffsetMarshaler::GetNativeType()
 {
     LIMITED_METHOD_CONTRACT;
@@ -3551,53 +3679,74 @@ bool ILAsAnyMarshalerBase::SupportsReturnMarshal(DWORD dwMarshalFlags, UINT* pEr
     return false;
 }
 
-void ILAsAnyMarshalerBase::EmitCreateMngdMarshaler(ILCodeStream* pslILEmit)
+void ILAsAnyMarshalerBase::EmitMarshalArgumentCLRToNative()
 {
     CONTRACTL
     {
-        THROWS;
-        GC_TRIGGERS;
-        MODE_ANY;
-        CONSISTENCY_CHECK(LOCAL_NUM_UNUSED == m_dwMngdMarshalerLocalNum);
+        STANDARD_VM_CHECK;
+        PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
+        CONSISTENCY_CHECK(LOCAL_NUM_UNUSED == m_dwMarshalerLocalNum);
     }
     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_dwMngdMarshalerLocalNum = pslILEmit->NewLocal(marshalerType);
-    DWORD dwTmpLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I);
+    m_dwMarshalerLocalNum = m_pcsMarshal->NewLocal(marshalerType);
+    DWORD dwTmpLocalNum = m_pcsMarshal->NewLocal(ELEMENT_TYPE_I);
 
-    pslILEmit->EmitLDC(sizeof(MngdNativeArrayMarshaler));
-    pslILEmit->EmitLOCALLOC();
-    pslILEmit->EmitSTLOC(dwTmpLocalNum);
+    m_pcsMarshal->EmitLDC(sizeof(MngdNativeArrayMarshaler));
+    m_pcsMarshal->EmitLOCALLOC();
+    m_pcsMarshal->EmitSTLOC(dwTmpLocalNum);
 
     // marshaler = new AsAnyMarshaler(local_buffer)
-    pslILEmit->EmitLDLOCA(m_dwMngdMarshalerLocalNum);
-    pslILEmit->EmitINITOBJ(pslILEmit->GetToken(marshalerType.InternalToken));
+    m_pcsMarshal->EmitLDLOCA(m_dwMarshalerLocalNum);
+    m_pcsMarshal->EmitINITOBJ(m_pcsMarshal->GetToken(marshalerType.InternalToken));
 
-    pslILEmit->EmitLDLOCA(m_dwMngdMarshalerLocalNum);
-    pslILEmit->EmitLDLOC(dwTmpLocalNum);
-    pslILEmit->EmitCALL(METHOD__ASANY_MARSHALER__CTOR, 2, 0);
-}
+    m_pcsMarshal->EmitLDLOCA(m_dwMarshalerLocalNum);
+    m_pcsMarshal->EmitLDLOC(dwTmpLocalNum);
+    m_pcsMarshal->EmitCALL(METHOD__ASANY_MARSHALER__CTOR, 2, 0);
 
-void ILAsAnyMarshalerBase::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
-{
     // nativeValue = marshaler.ConvertToNative(managedValue, flags);
-    EmitLoadMngdMarshalerAddr(pslILEmit);
-    EmitLoadManagedValue(pslILEmit);
-    pslILEmit->EmitLDC(GetAsAnyFlags());
-    pslILEmit->EmitCALL(METHOD__ASANY_MARSHALER__CONVERT_TO_NATIVE, 3, 1);
-    EmitStoreNativeValue(pslILEmit);
-}
+    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);
 
-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);
-}
+    //
+    // 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);
+    }
 
+    //
+    // cleanup
+    //
+    EmitCleanupCLRToNativeTemp();
+}
 
 bool ILAsAnyMarshalerBase::NeedsClearNative()
 {
@@ -3610,7 +3759,7 @@ void ILAsAnyMarshalerBase::EmitClearNativeTemp(ILCodeStream* pslILEmit)
     STANDARD_VM_CONTRACT;
 
     // marshaler.ClearNative(nativeHome)
-    EmitLoadMngdMarshalerAddr(pslILEmit);
+    pslILEmit->EmitLDLOCA(m_dwMarshalerLocalNum);
     EmitLoadNativeValue(pslILEmit);
     pslILEmit->EmitCALL(METHOD__ASANY_MARSHALER__CLEAR_NATIVE, 2, 0);
 }
@@ -3657,9 +3806,24 @@ 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);
         
@@ -3691,12 +3855,8 @@ 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::EmitMarshalViaPinning(ILCodeStream* pslILEmit)
+void ILNativeArrayMarshaler::EmitMarshalArgumentCLRToNative()
 {
     CONTRACTL
     {
@@ -3705,44 +3865,56 @@ void ILNativeArrayMarshaler::EmitMarshalViaPinning(ILCodeStream* pslILEmit)
     }
     CONTRACTL_END;
 
-    //
-    // 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.  
-    //
-
-    LocalDesc managedType = GetManagedType();
-    managedType.MakePinned();
-
-    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);
+    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.  
+        //
 
-    EmitLogNativeArgumentsIfNeeded(pslILEmit, dwPinnedLocal);
+        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);
+        }
 
-    pslILEmit->EmitLabel(pNullRefLabel);
+        m_pcsMarshal->EmitLabel(pNullRefLabel);
+    }
+    else
+    {
+        ILMngdMarshaler::EmitMarshalArgumentCLRToNative();
+    }
 }
 
 //
@@ -3857,7 +4029,7 @@ void ILNativeArrayMarshaler::EmitLoadElementCount(ILCodeStream* pslILEmit)
         unsigned countParamIdx = mops.countParamIdx;
         if (!IsCLRToNative(m_dwMarshalFlags))
         {
-            int lcidParamIdx = GetLCIDParamIndex();
+            int lcidParamIdx = m_pslNDirect->GetLCIDParamIdx();
     
             if (lcidParamIdx >= 0 && (unsigned)lcidParamIdx <= countParamIdx)
             {
@@ -4043,24 +4215,42 @@ void ILNativeArrayMarshaler::EmitClearNativeContents(ILCodeStream* pslILEmit)
     pslILEmit->EmitCALL(pslILEmit->GetToken(GetClearNativeContentsMethod()), 3, 0);
 }
 
-void ILNativeArrayMarshaler::EmitSetupArgumentForMarshalling(ILCodeStream* pslILEmit)
+void ILNativeArrayMarshaler::EmitNewSavedSizeArgLocal()
 {
+    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(pslILEmit);
+        EmitNewSavedSizeArgLocal();
     }
+    
+    ILMngdMarshaler::EmitMarshalArgumentNativeToCLRByref();
 }
 
-void ILNativeArrayMarshaler::EmitNewSavedSizeArgLocal(ILCodeStream* pslILEmit)
+void ILNativeArrayMarshaler::EmitMarshalArgumentCLRToNativeByref()
 {
     STANDARD_VM_CONTRACT;
 
-    _ASSERTE(m_dwSavedSizeArg == LOCAL_NUM_UNUSED);
-    m_dwSavedSizeArg = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
-    pslILEmit->EmitLDC(0);
-    pslILEmit->EmitSTLOC(m_dwSavedSizeArg);
+    if (IsByref(m_dwMarshalFlags))
+    {
+        EmitNewSavedSizeArgLocal();
+    }
+    
+    ILMngdMarshaler::EmitMarshalArgumentCLRToNativeByref();
 }
 
+
 #ifndef CROSSGEN_COMPILE
 
 FCIMPL3(void, MngdNativeArrayMarshaler::CreateMarshaler, MngdNativeArrayMarshaler* pThis, MethodTable* pMT, UINT32 dwFlags)
@@ -4538,75 +4728,98 @@ void ILHiddenLengthArrayMarshaler::EmitCreateMngdMarshaler(ILCodeStream* pslILEm
 {
     STANDARD_VM_CONTRACT;
 
-    m_dwMngdMarshalerLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I);
-    
-    pslILEmit->EmitLDC(sizeof(MngdHiddenLengthArrayMarshaler));
-    pslILEmit->EmitLOCALLOC();
-    pslILEmit->EmitSTLOC(m_dwMngdMarshalerLocalNum);
+    if (!CanUsePinnedArray())
+    {
+        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::EmitMarshalViaPinning(ILCodeStream* pslILEmit)
+void ILHiddenLengthArrayMarshaler::EmitMarshalArgumentCLRToNative()
 {
-    LocalDesc managedType = GetManagedType();
-    managedType.MakePinned();
-    DWORD dwPinnedLocal = pslILEmit->NewLocal(managedType);
+    STANDARD_VM_CONTRACT;
 
-    ILCodeLabel* pMarshalDoneLabel = pslILEmit->NewCodeLabel();
+    // 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();
 
-    // native = NULL
-    pslILEmit->EmitLoadNullPtr();
-    EmitStoreNativeValue(pslILEmit);
+        LocalDesc managedType = GetManagedType();
+        managedType.MakePinned();
+        DWORD dwPinnedLocal = m_pcsMarshal->NewLocal(managedType);
 
-    // if (managed == null) goto MarshalDone
-    EmitLoadManagedValue(pslILEmit);
-    pslILEmit->EmitBRFALSE(pMarshalDoneLabel);
+        ILCodeLabel* pMarshalDoneLabel = m_pcsMarshal->NewCodeLabel();
 
-    // pinnedLocal = managed;
-    EmitLoadManagedValue(pslILEmit);
-    pslILEmit->EmitSTLOC(dwPinnedLocal);
+        // native = NULL
+        m_pcsMarshal->EmitLoadNullPtr();
+        EmitStoreNativeValue(m_pcsMarshal);
 
-    // native = pinnedLocal + dataOffset
+        // if (managed == null) goto MarshalDone
+        EmitLoadManagedValue(m_pcsMarshal);
+        m_pcsMarshal->EmitBRFALSE(pMarshalDoneLabel);
 
-    // 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);
+        // pinnedLocal = managed;
+        EmitLoadManagedValue(m_pcsMarshal);
+        m_pcsMarshal->EmitSTLOC(dwPinnedLocal);
 
-    EmitLogNativeArgumentsIfNeeded(pslILEmit, dwPinnedLocal);
+        // native = pinnedLocal + dataOffset
+
+        // 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);
+
+        if (g_pConfig->InteropLogArguments())
+        {
+            m_pslNDirect->EmitLogNativeArgument(m_pcsMarshal, dwPinnedLocal);
+        }
+
+        // MarshalDone:
+        m_pcsMarshal->EmitLabel(pMarshalDoneLabel);
+    }
+    else
+    {
+        ILMngdMarshaler::EmitMarshalArgumentCLRToNative();
+    }
 
-    // MarshalDone:
-    pslILEmit->EmitLabel(pMarshalDoneLabel);
 }
 
 void ILHiddenLengthArrayMarshaler::EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit)
 {
     STANDARD_VM_CONTRACT;
 
-    EmitLoadMngdMarshaler(pslILEmit);
-    EmitLoadManagedHomeAddr(pslILEmit);
-    EmitLoadNativeHomeAddr(pslILEmit);
-    EmitLoadNativeArrayLength(pslILEmit);
-    
-    // MngdHiddenLengthArrayMarshaler::ConvertSpaceToManaged
-    pslILEmit->EmitCALL(pslILEmit->GetToken(GetConvertSpaceToManagedMethod()), 4, 0);
+    if (!CanUsePinnedArray())
+    {
+        EmitLoadMngdMarshaler(pslILEmit);
+        EmitLoadManagedHomeAddr(pslILEmit);
+        EmitLoadNativeHomeAddr(pslILEmit);
+        EmitLoadNativeArrayLength(pslILEmit);
+        
+        // MngdHiddenLengthArrayMarshaler::ConvertSpaceToManaged
+        pslILEmit->EmitCALL(pslILEmit->GetToken(GetConvertSpaceToManagedMethod()), 4, 0);
+    }
 }
 
 void ILHiddenLengthArrayMarshaler::EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit)
@@ -4618,7 +4831,7 @@ void ILHiddenLengthArrayMarshaler::EmitConvertSpaceCLRToNative(ILCodeStream* psl
     {
         if (IsByref(m_dwMarshalFlags) || IsRetval(m_dwMarshalFlags) || IsOut(m_dwMarshalFlags))
         {
-            ILCodeLabel *pSkipGetLengthLabel = pslILEmit->NewCodeLabel();
+            ILCodeLabel *pSkipGetLengthLabel = m_pcsMarshal->NewCodeLabel();
 
             // nativeLen = 0
             pslILEmit->EmitLDC(0);
@@ -4645,76 +4858,82 @@ void ILHiddenLengthArrayMarshaler::EmitConvertSpaceCLRToNative(ILCodeStream* psl
         }
     }
 
-    ILMngdMarshaler::EmitConvertSpaceCLRToNative(pslILEmit);
+    if (!CanUsePinnedArray())
+    {
+        ILMngdMarshaler::EmitConvertSpaceCLRToNative(pslILEmit);
+    }
 }
 
 void ILHiddenLengthArrayMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
 {
     STANDARD_VM_CONTRACT;
 
-    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 (!CanUsePinnedArray())
     {
-        // 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();
-
-        switch (m_pargs->na.m_redirectedTypeIndex)
+        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))
         {
-            case WinMDAdapter::RedirectedTypeIndex_System_Uri:
-                ILUriMarshaler::EmitConvertCLRUriToWinRTUri(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetLoaderAllocator());
-                break;
+            // 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();
 
-            case WinMDAdapter::RedirectedTypeIndex_System_Collections_Specialized_NotifyCollectionChangedEventArgs:
-                ILNCCEventArgsMarshaler::EmitConvertCLREventArgsToWinRTEventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetLoaderAllocator());
-                break;
+            // 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();
 
-            case WinMDAdapter::RedirectedTypeIndex_System_ComponentModel_PropertyChangedEventArgs:
-                ILPCEventArgsMarshaler::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;
 
-            default: UNREACHABLE();
-        }
+                case WinMDAdapter::RedirectedTypeIndex_System_Collections_Specialized_NotifyCollectionChangedEventArgs:
+                    ILNCCEventArgsMarshaler::EmitConvertCLREventArgsToWinRTEventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetLoaderAllocator());
+                    break;
 
-        pslILEmit->EmitSTIND_I();
+                case WinMDAdapter::RedirectedTypeIndex_System_ComponentModel_PropertyChangedEventArgs:
+                    ILPCEventArgsMarshaler::EmitConvertCLREventArgsToWinRTEventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetLoaderAllocator());
+                    break;
 
-        // ... 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);
+                default: UNREACHABLE();
+            }
 
-        // ... i < pManaged.Length; ...
-        pslILEmit->EmitLabel(pConditionLabel);
-        pslILEmit->EmitLDLOC(dwLoopCounterLocalNum);
-        EmitLoadNativeArrayLength(pslILEmit);
-        pslILEmit->EmitBLT(pLoopBodyLabel);
-    }            
-    else
-    {
-        ILMngdMarshaler::EmitConvertContentsCLRToNative(pslILEmit);
+            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);
+        }
     }
 }
 
@@ -4722,69 +4941,72 @@ void ILHiddenLengthArrayMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream*
 {
     STANDARD_VM_CONTRACT;
 
-    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 (!CanUsePinnedArray())
     {
-        // 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();
+        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();
 
-        // 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();
+                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);
         }
-        
-        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);
     }
 }
 
@@ -4794,37 +5016,43 @@ void ILHiddenLengthArrayMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
 
     EmitClearNativeContents(pslILEmit);
 
-    EmitLoadNativeValue(pslILEmit);
-    pslILEmit->EmitCALL(pslILEmit->GetToken(GetClearNativeMethod()), 1, 0);
+    if (!CanUsePinnedArray())
+    {
+        EmitLoadNativeValue(pslILEmit);
+        pslILEmit->EmitCALL(pslILEmit->GetToken(GetClearNativeMethod()), 1, 0);
+    }
 }
 
 void ILHiddenLengthArrayMarshaler::EmitClearNativeContents(ILCodeStream* pslILEmit)
 {
     STANDARD_VM_CONTRACT;
 
-    MethodDesc *pMD = GetClearNativeContentsMethod();
-    if (pMD != NULL)
+    if (!CanUsePinnedArray())
     {
-        MetaSig sig(pMD);
-        UINT numArgs = sig.NumFixedArgs();
-
-        if (numArgs == 3)
+        MethodDesc *pMD = GetClearNativeContentsMethod();
+        if (pMD != NULL)
         {
-            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::CanMarshalViaPinning()
+bool ILHiddenLengthArrayMarshaler::CanUsePinnedArray()
 {
     STANDARD_VM_CONTRACT;
 
index e2f81c3..61ff142 100644 (file)
@@ -42,7 +42,6 @@ public:
     void InitHome(MarshalHomeType homeType, DWORD dwHomeIndex)
     {
         LIMITED_METHOD_CONTRACT;
-
         m_homeType = homeType;
         m_dwHomeIndex = dwHomeIndex;
     }
@@ -215,16 +214,17 @@ 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;
-    NDirectStubLinker*  m_pslNDirect;
+
+    DWORD               m_dwMngdMarshalerLocalNum;
 
 public:
 
@@ -245,7 +245,6 @@ public:
         m_pslNDirect = pslNDirect;
     }
 
-private:
     void Init(ILCodeStream* pcsMarshal, 
             ILCodeStream* pcsUnmarshal,
             UINT argidx,
@@ -353,14 +352,6 @@ 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)
@@ -407,15 +398,7 @@ 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).
-        // 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());
+        EmitCreateMngdMarshaler(m_pslNDirect->GetSetupCodeStream());
 
         if (IsCLRToNative(dwMarshalFlags))
         {
@@ -460,13 +443,7 @@ public:
         CONTRACTL_END;
 
         Init(pcsMarshal, pcsUnmarshal, hiddenArgIndex, dwMarshalFlags, pargs);
-
-        if (!CanMarshalViaPinning())
-        {
-            EmitCreateMngdMarshaler(m_pslNDirect->GetSetupCodeStream());
-        }
-
-        EmitSetupArgumentForMarshalling(m_pslNDirect->GetSetupCodeStream());
+        EmitCreateMngdMarshaler(m_pslNDirect->GetSetupCodeStream());
 
         // Create a local to be the home of the length parameter
         DWORD dwManagedLocalHome = m_pcsMarshal->NewLocal(GetManagedType());
@@ -559,7 +536,7 @@ public:
 
 #endif // FEATURE_COMINTEROP
 
-    void EmitSetupArgumentForDispatch(ILCodeStream* pslILEmit)
+    virtual void EmitSetupArgument(ILCodeStream* pslILEmit)
     {
         STANDARD_VM_CONTRACT;
 
@@ -587,7 +564,7 @@ public:
         }
     }
 
-    void EmitMarshalReturnValue(
+    virtual void EmitMarshalReturnValue(
                 ILCodeStream* pcsMarshal, 
                 ILCodeStream* pcsUnmarshal,
                 ILCodeStream* pcsDispatch,
@@ -834,7 +811,7 @@ protected:
         LIMITED_METHOD_CONTRACT;
     }
 
-    void EmitLoadMngdMarshaler(ILCodeStream* pslILEmit)
+    virtual void EmitLoadMngdMarshaler(ILCodeStream* pslILEmit)
     {
         CONTRACTL
         {
@@ -848,30 +825,6 @@ 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
@@ -931,7 +884,7 @@ protected:
         }
     }
 
-    void EmitMarshalArgumentCLRToNative()
+    virtual void EmitMarshalArgumentCLRToNative()
     {
         CONTRACTL
         {
@@ -953,39 +906,31 @@ protected:
         }
         CONTRACTL_END;
 
-        if (CanMarshalViaPinning())
+        //
+        // marshal
+        //
+        if (IsIn(m_dwMarshalFlags))
         {
-            // If we can marshal via pinning, all we need to do to marshal is pin.
-            EmitMarshalViaPinning(m_pcsMarshal);
+            EmitConvertSpaceAndContentsCLRToNativeTemp(m_pcsMarshal);
         }
         else
         {
-            //
-            // marshal
-            //
-            if (IsIn(m_dwMarshalFlags) || AlwaysConvertByValContentsCLRToNative())
-            {
-                EmitConvertSpaceAndContentsCLRToNativeTemp(m_pcsMarshal);
-            }
-            else
-            {
-                EmitConvertSpaceCLRToNativeTemp(m_pcsMarshal);
-            }
+            EmitConvertSpaceCLRToNativeTemp(m_pcsMarshal);
+        }
 
-            //
-            // unmarshal
-            //
-            if (IsOut(m_dwMarshalFlags))
+        //
+        // unmarshal
+        //
+        if (IsOut(m_dwMarshalFlags))
+        {
+            if (IsIn(m_dwMarshalFlags))
             {
-                if (IsIn(m_dwMarshalFlags))
-                {
-                    EmitClearCLRContents(m_pcsUnmarshal);
-                }
-                EmitConvertContentsNativeToCLR(m_pcsUnmarshal);
+                EmitClearCLRContents(m_pcsUnmarshal);
             }
-            
-            EmitCleanupCLRToNativeTemp();
+            EmitConvertContentsNativeToCLR(m_pcsUnmarshal);
         }
+
+        EmitCleanupCLRToNativeTemp();
    }
 
     void EmitSetupSigAndDefaultHomesCLRToNativeByref(bool fBlittable = false)
@@ -1136,18 +1081,6 @@ 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
@@ -1234,7 +1167,7 @@ protected:
         }
     }
 
-    void EmitMarshalArgumentNativeToCLR()
+    virtual void EmitMarshalArgumentNativeToCLR()
     {
         CONTRACTL
         {
@@ -1392,11 +1325,6 @@ protected:
     virtual LocalDesc GetNativeType() = 0;
     virtual LocalDesc GetManagedType() = 0;
 
-    virtual void EmitSetupArgumentForMarshalling(ILCodeStream* pslILEmit)
-    {
-        LIMITED_METHOD_CONTRACT;
-    }
-    
     //
     // Native-to-CLR
     //
@@ -1443,10 +1371,7 @@ 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;
@@ -1494,17 +1419,6 @@ 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;
@@ -1521,7 +1435,7 @@ protected:
         EmitStoreNativeValue(pslILEmit);
     }
 
-    bool IsManagedPassedByRef()
+    virtual bool IsManagedPassedByRef()
     {
         LIMITED_METHOD_CONTRACT;
         return IsByref(m_dwMarshalFlags);
@@ -1535,16 +1449,7 @@ 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,
@@ -1559,8 +1464,6 @@ 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,
@@ -1575,13 +1478,13 @@ public:
         
 class ILCopyMarshalerBase : public ILMarshaler
 {
-    LocalDesc GetManagedType() override
+    virtual LocalDesc GetManagedType()
     {
         WRAPPER_NO_CONTRACT;
         return GetNativeType();
     }
 
-    void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override
+    virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
     {
         STANDARD_VM_CONTRACT;
 
@@ -1589,7 +1492,7 @@ class ILCopyMarshalerBase : public ILMarshaler
         EmitStoreNativeValue(pslILEmit);
     }
 
-    void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override
+    virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
     {
         STANDARD_VM_CONTRACT;
 
@@ -1610,7 +1513,7 @@ class ILCopyMarshalerBase : public ILMarshaler
     // This method was changed to pin instead of copy in Dev10 in order
     // to match the original ML behavior.
     //
-    void EmitMarshalArgumentCLRToNativeByref() override 
+    virtual void EmitMarshalArgumentCLRToNativeByref()
     {
         CONTRACTL
         {
@@ -1624,8 +1527,9 @@ class ILCopyMarshalerBase : public ILMarshaler
         //
         // marshal
         //
-        EmitMarshalArgumentAddressCLRToNative();
-
+        EmitLoadManagedHomeAddr(m_pcsMarshal);
+        EmitStoreNativeHomeAddr(m_pcsMarshal);
+        
         //
         // no unmarshaling is necessary since we directly passed the pinned byref to native,
         // the argument is therefore automatically in/out
@@ -1643,7 +1547,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.
     //
-    void EmitMarshalArgumentNativeToCLRByref() override
+    virtual void EmitMarshalArgumentNativeToCLRByref()
     {
         CONTRACTL
         {
@@ -1657,7 +1561,8 @@ class ILCopyMarshalerBase : public ILMarshaler
         //
         // marshal
         //
-        EmitMarshalArgumentAddressNativeToCLR();
+        EmitLoadNativeHomeAddr(m_pcsMarshal);
+        EmitStoreManagedHomeAddr(m_pcsMarshal);
         
         //
         // no unmarshaling is necessary since we directly passed the pointer to managed
@@ -1891,10 +1796,10 @@ public:
     };
 
 protected:
-    LocalDesc GetNativeType() override;
-    LocalDesc GetManagedType() override;
-    void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override;
-    void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override;
+    virtual LocalDesc GetNativeType();
+    virtual LocalDesc GetManagedType();
+    virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
+    virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
 };
 
 class ILReflectionObjectMarshaler : public ILMarshaler
@@ -1908,11 +1813,11 @@ public:
     };
 
 protected:
-    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 LocalDesc GetManagedType();
+    virtual LocalDesc GetNativeType();
+    virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
+    virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
+    virtual BinderFieldID GetStructureFieldID() {LIMITED_METHOD_CONTRACT; return (BinderFieldID)0;}
     virtual BinderFieldID GetObjectFieldID() = 0;
     virtual BinderClassID GetManagedTypeBinderID() = 0;
 };
@@ -1920,25 +1825,25 @@ protected:
 class ILRuntimeTypeHandleMarshaler : public ILReflectionObjectMarshaler
 {
 protected:
-    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; }
+    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; }
 };
 
 class ILRuntimeMethodHandleMarshaler : public ILReflectionObjectMarshaler
 {
 protected:
-    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; }
+    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; }
 };
 
 class ILRuntimeFieldHandleMarshaler : public ILReflectionObjectMarshaler
 {
 protected:
-    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; }
+    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; }
 };
 
 class ILBoolMarshaler : public ILMarshaler
@@ -1950,10 +1855,10 @@ public:
     virtual int GetNativeFalseValue() = 0;
 
 protected:
-    LocalDesc GetNativeType() override;
-    LocalDesc GetManagedType() override;
-    void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override;
-    void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override;
+    virtual LocalDesc GetNativeType();
+    virtual LocalDesc GetManagedType();
+    virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
+    virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
 };
 
 class ILWinBoolMarshaler : public ILBoolMarshaler
@@ -1967,19 +1872,19 @@ public:
     };
         
 protected:    
-    CorElementType GetNativeBoolElementType() override
+    virtual CorElementType GetNativeBoolElementType()
     {
         LIMITED_METHOD_CONTRACT;
         return ELEMENT_TYPE_I4;
     }
 
-    int GetNativeTrueValue() override
+    virtual int GetNativeTrueValue()
     {
         LIMITED_METHOD_CONTRACT;
         return 1;
     }
         
-    int GetNativeFalseValue() override
+    virtual int GetNativeFalseValue()
     {
         LIMITED_METHOD_CONTRACT;
         return 0;
@@ -1997,19 +1902,19 @@ public:
     };
 
 protected:
-    CorElementType GetNativeBoolElementType() override
+    virtual CorElementType GetNativeBoolElementType()
     {
         LIMITED_METHOD_CONTRACT;
         return ELEMENT_TYPE_I1;
     }
 
-    int GetNativeTrueValue() override
+    virtual int GetNativeTrueValue()
     {
         LIMITED_METHOD_CONTRACT;
         return 1;
     }
                 
-    int GetNativeFalseValue() override
+    virtual int GetNativeFalseValue()
     {
         LIMITED_METHOD_CONTRACT;
         return 0;
@@ -2028,19 +1933,19 @@ public:
     };
 
 protected:    
-    CorElementType GetNativeBoolElementType() override
+    virtual CorElementType GetNativeBoolElementType()
     {
         LIMITED_METHOD_CONTRACT;
         return ELEMENT_TYPE_I2;
     }
 
-    int GetNativeTrueValue() override
+    virtual int GetNativeTrueValue()
     {
         LIMITED_METHOD_CONTRACT;
         return VARIANT_TRUE;
     }
 
-    int GetNativeFalseValue() override
+    virtual int GetNativeFalseValue()
     {
         LIMITED_METHOD_CONTRACT;
         return VARIANT_FALSE;
@@ -2048,6 +1953,59 @@ 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
@@ -2060,9 +2018,9 @@ public:
         LIMITED_METHOD_CONTRACT;
     }
 
-    LocalDesc GetNativeType() override;
-    bool NeedsClearNative() override;
-    void EmitClearNative(ILCodeStream* pslILEmit) override;
+    virtual LocalDesc GetNativeType();
+    virtual bool NeedsClearNative();
+    virtual void EmitClearNative(ILCodeStream* pslILEmit);
 
 protected:
     const BinderMethodID m_idClearNative;
@@ -2091,11 +2049,11 @@ public:
                LIMITED_METHOD_CONTRACT;
        }
 
-       LocalDesc GetManagedType() override;
-       void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit) override;
-       void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override;
-       void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit) override;
-       void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override;
+       virtual LocalDesc GetManagedType();
+       virtual void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit);
+       virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
+       virtual void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit);
+       virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
 };
 
 class ILWSTRBufferMarshaler : public ILOptimizedAllocMarshaler
@@ -2120,11 +2078,11 @@ public:
         LIMITED_METHOD_CONTRACT;
     }
 
-    LocalDesc GetManagedType() override;
-    void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit) override;
-    void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override;
-    void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit) override;
-    void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override;
+    virtual LocalDesc GetManagedType();
+    virtual void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit);
+    virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
+    virtual void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit);
+    virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
 };
 
 class ILCSTRBufferMarshaler : public ILOptimizedAllocMarshaler
@@ -2149,11 +2107,11 @@ public:
         LIMITED_METHOD_CONTRACT;
     }
 
-    LocalDesc GetManagedType() override;
-    void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit) override;
-    void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override;
-    void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit) override;
-    void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override;
+    virtual LocalDesc GetManagedType();
+    virtual void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit);
+    virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
+    virtual void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit);
+    virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
 };
 
         
@@ -2213,17 +2171,13 @@ public:
         c_CLRSize               = sizeof(SAFEHANDLE),
     };
 
-    LocalDesc GetManagedType() override
-    {
-        LIMITED_METHOD_CONTRACT;
-        return LocalDesc();
-    }
-    
-    LocalDesc GetNativeType() override
-    {
-        LIMITED_METHOD_CONTRACT;
-        return LocalDesc();
-    }
+    virtual LocalDesc GetManagedType();
+    virtual LocalDesc GetNativeType();
+
+    virtual bool NeedsClearNative();
+    virtual void EmitClearNative(ILCodeStream* pslILEmit);
+
+    virtual void EmitMarshalArgumentCLRToNative();
 
     static MarshalerOverrideStatus ArgumentOverride(NDirectStubLinker* psl,
                                                     BOOL               byref,
@@ -2255,13 +2209,13 @@ public:
         
 public:
 
-    LocalDesc GetManagedType() override
+    LocalDesc GetManagedType()
     {
         LIMITED_METHOD_CONTRACT;
         return LocalDesc();
     }
     
-    LocalDesc GetNativeType() override
+    LocalDesc GetNativeType()
     {
         LIMITED_METHOD_CONTRACT;
         return LocalDesc();
@@ -2296,13 +2250,13 @@ public:
     };
 
 protected:
-    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;
+    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);
 };
         
 #ifdef FEATURE_COMINTEROP
@@ -2317,13 +2271,13 @@ public:
     };
 
 protected:
-    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;
+    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);
 };
 #endif // FEATURE_COMINTEROP
 
@@ -2338,11 +2292,11 @@ public:
     };
                 
 protected:
-    LocalDesc GetNativeType() override;
-    LocalDesc GetManagedType() override;
-    void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override;
-    void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override;
-    void EmitReInitNative(ILCodeStream* pslILEmit) override;
+    virtual LocalDesc GetNativeType();
+    virtual LocalDesc GetManagedType();
+    virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
+    virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
+    virtual void EmitReInitNative(ILCodeStream* pslILEmit);
 };
                 
 
@@ -2357,11 +2311,11 @@ public:
     };
 
 protected:    
-    LocalDesc GetNativeType() override;
-    LocalDesc GetManagedType() override;
-    void EmitReInitNative(ILCodeStream* pslILEmit) override;
-    void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override;
-    void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override;
+    virtual LocalDesc GetNativeType();
+    virtual LocalDesc GetManagedType();
+    virtual void EmitReInitNative(ILCodeStream* pslILEmit);
+    virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
+    virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
 };
 
 
@@ -2377,12 +2331,12 @@ public:
     };
 
 protected:    
-    LocalDesc GetNativeType() override;
-    LocalDesc GetManagedType() override;
-    void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override;
-    void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override;
-    bool NeedsClearNative() override;
-    void EmitClearNative(ILCodeStream* pslILEmit) override;
+    virtual LocalDesc GetNativeType();
+    virtual LocalDesc GetManagedType();
+    virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
+    virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
+    virtual bool NeedsClearNative();
+    virtual void EmitClearNative(ILCodeStream* pslILEmit);
 };
 #endif // FEATURE_COMINTEROP
 
@@ -2398,10 +2352,10 @@ public:
     };
 
 protected:
-    LocalDesc GetNativeType() override;
-    LocalDesc GetManagedType() override;
-    void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override;
-    void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override;
+    virtual LocalDesc GetNativeType();
+    virtual LocalDesc GetManagedType();
+    virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
+    virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
 };
 
 
@@ -2417,7 +2371,7 @@ public:
     };
 
 protected:
-    LocalDesc GetNativeType() override
+    virtual LocalDesc GetNativeType()
     {
         LIMITED_METHOD_CONTRACT;
 
@@ -2427,7 +2381,7 @@ protected:
         return LocalDesc(ELEMENT_TYPE_I);
     }
 
-    LocalDesc GetManagedType() override
+    virtual LocalDesc GetManagedType()
     {
         STANDARD_VM_CONTRACT;
 
@@ -2437,13 +2391,13 @@ protected:
         return LocalDesc(MscorlibBinder::GetClass(CLASS__ID));
     }
 
-    bool NeedsClearNative() override
+    virtual bool NeedsClearNative()
     {
         LIMITED_METHOD_CONTRACT;
         return (IsByref(m_dwMarshalFlags) && IsOut(m_dwMarshalFlags));
     }
 
-    void EmitClearNative(ILCodeStream* pslILEmit) override
+    virtual void EmitClearNative(ILCodeStream* pslILEmit)
     {
         STANDARD_VM_CONTRACT;
 
@@ -2452,7 +2406,7 @@ protected:
         pslILEmit->EmitCALL(METHOD__MARSHAL__FREE_CO_TASK_MEM, 1, 0);
     }
 
-    void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit) override
+    virtual void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit)
     {
         STANDARD_VM_CONTRACT;
 
@@ -2466,7 +2420,7 @@ protected:
         }
     }
 
-    void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override
+    virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
     {
         STANDARD_VM_CONTRACT;
 
@@ -2483,7 +2437,7 @@ protected:
         }
     }
 
-    void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override
+    virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
     {
         STANDARD_VM_CONTRACT;
 
@@ -2526,10 +2480,10 @@ public:
     };
 
 protected:
-    LocalDesc GetNativeType() override;
-    LocalDesc GetManagedType() override;
-    void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override;
-    void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override;
+    virtual LocalDesc GetNativeType();
+    virtual LocalDesc GetManagedType();
+    virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
+    virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
 };
 
 class ILVBByValStrWMarshaler : public ILMarshaler
@@ -2556,18 +2510,17 @@ public:
         LIMITED_METHOD_CONTRACT;
     }
 
-    bool SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID) override;
-    bool SupportsReturnMarshal(DWORD dwMarshalFlags, UINT* pErrorResID) override;
+    virtual bool SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID);
+    virtual bool SupportsReturnMarshal(DWORD dwMarshalFlags, UINT* pErrorResID);
 
 protected:
-    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;
+    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();
         
     DWORD m_dwCCHLocal;
     DWORD m_dwLocalBuffer;
@@ -2589,17 +2542,17 @@ public:
         LIMITED_METHOD_CONTRACT;
     }
 
-    bool SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID) override;
-    bool SupportsReturnMarshal(DWORD dwMarshalFlags, UINT* pErrorResID) override;
+    virtual bool SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID);
+    virtual bool SupportsReturnMarshal(DWORD dwMarshalFlags, UINT* pErrorResID);
 
 protected:
-    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;
+    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();
 
     DWORD m_dwCCHLocal;
 };
@@ -2615,17 +2568,17 @@ public:
     };
 
 protected:
-    LocalDesc GetNativeType() override;
-    LocalDesc GetManagedType() override;
+    virtual LocalDesc GetNativeType();
+    virtual LocalDesc GetManagedType();
 
-    void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override;
+    virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
     void EmitConvertCLRToHSTRINGReference(ILCodeStream* pslILEmit);
     void EmitConvertCLRToHSTRING(ILCodeStream* pslILEmit);
 
-    void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override;
+    virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
 
-    bool NeedsClearNative() override;
-    void EmitClearNative(ILCodeStream* pslILEmit) override;
+    virtual bool NeedsClearNative();
+    virtual void EmitClearNative(ILCodeStream* pslILEmit);
 };
 #endif // FEATURE_COMINTEROP
 
@@ -2653,67 +2606,12 @@ public:
        }
 
 protected:
-       LocalDesc GetManagedType() override;
-       void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override;
-       void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override;
+       virtual LocalDesc GetManagedType();
+       virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
+       virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
 };
 
-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
 {
@@ -2738,9 +2636,9 @@ public:
     }
 
 protected:    
-    LocalDesc GetManagedType() override;
-    void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override;
-    void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override;
+    virtual LocalDesc GetManagedType();
+    virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
+    virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
 };
 
 class ILBSTRMarshaler : public ILOptimizedAllocMarshaler
@@ -2766,9 +2664,9 @@ public:
     }
 
 protected:    
-    LocalDesc GetManagedType() override;
-    void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override;
-    void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override;
+    virtual LocalDesc GetManagedType();
+    virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
+    virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
 };
 
 class ILAnsiBSTRMarshaler : public ILMarshaler
@@ -2782,12 +2680,12 @@ public:
     };
 
 protected:    
-    LocalDesc GetNativeType() override;
-    LocalDesc GetManagedType() override;
-    void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override;
-    void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override;
-    bool NeedsClearNative() override;
-    void EmitClearNative(ILCodeStream* pslILEmit) override;
+    virtual LocalDesc GetNativeType();
+    virtual LocalDesc GetManagedType();
+    virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
+    virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
+    virtual bool NeedsClearNative();
+    virtual void EmitClearNative(ILCodeStream* pslILEmit);
 };
 
 class ILLayoutClassPtrMarshalerBase : public ILMarshaler
@@ -2800,15 +2698,15 @@ public:
     };
 
 protected:    
-    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;
+    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);
 };
 
 class ILLayoutClassPtrMarshaler : public ILLayoutClassPtrMarshalerBase
@@ -2820,9 +2718,9 @@ public:
     };
         
 protected:    
-    void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override;
-    void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override;
-    void EmitClearNativeContents(ILCodeStream * pslILEmit) override;
+    virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
+    virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
+    virtual void EmitClearNativeContents(ILCodeStream * pslILEmit);
 };
 
 class ILBlittablePtrMarshaler : public ILLayoutClassPtrMarshalerBase
@@ -2833,12 +2731,10 @@ public:
         c_fInOnly               = FALSE,
     };
             
-protected:
-    void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override;
-    void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override;
-    void EmitConvertSpaceAndContentsCLRToNativeTemp(ILCodeStream* pslILEmit) override;
-private:
-    bool CanUsePinnedLayoutClass();
+protected:    
+    virtual void EmitMarshalArgumentCLRToNative();
+    virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
+    virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
 };
 
 class ILBlittableValueClassWithCopyCtorMarshaler : public ILMarshaler
@@ -2887,14 +2783,11 @@ public:
     };
 
 protected:
-    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;
+    virtual LocalDesc GetNativeType();
+    virtual LocalDesc GetManagedType();
+    virtual bool SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID);
+    virtual void EmitMarshalArgumentCLRToNative();
+    virtual void EmitMarshalArgumentNativeToCLR();
 };
         
 class ILArrayWithOffsetMarshaler : public ILMarshaler
@@ -2916,15 +2809,15 @@ public:
     }
 
 protected:
-    LocalDesc GetNativeType() override;
-    LocalDesc GetManagedType() override;
-    bool SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID) override;
+    virtual LocalDesc GetNativeType();
+    virtual LocalDesc GetManagedType();
+    virtual bool SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID);
 
-    void EmitConvertSpaceAndContentsCLRToNativeTemp(ILCodeStream* pslILEmit) override;
-    void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override;
-    void EmitClearNativeTemp(ILCodeStream* pslILEmit) override;
+    virtual void EmitConvertSpaceAndContentsCLRToNativeTemp(ILCodeStream* pslILEmit);
+    virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
+    virtual void EmitClearNativeTemp(ILCodeStream* pslILEmit);
 
-private:
+        
     DWORD m_dwCountLocalNum;
     DWORD m_dwOffsetLocalNum;
     DWORD m_dwPinnedLocalNum;
@@ -2939,46 +2832,26 @@ public:
         c_CLRSize               = sizeof(OBJECTREF),
     };
 
-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
+    ILAsAnyMarshalerBase() :
+        m_dwMarshalerLocalNum(-1)
     {
         LIMITED_METHOD_CONTRACT;
-        return true;
     }
 
-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.
+protected:
     static const BYTE ML_IN  = 0x10;
     static const BYTE ML_OUT = 0x20;
 
-    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;
+    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);
 
-        dwFlags |= inout << 24;
-        dwFlags |= fIsAnsi << 16;
-        dwFlags |= fThrow << 8;
-        dwFlags |= fBestFit << 0;
-        return dwFlags;
-    }
+    DWORD m_dwMarshalerLocalNum;
 };
 
 class ILAsAnyWMarshaler : public ILAsAnyMarshalerBase
@@ -2990,7 +2863,7 @@ public:
     };
 
 protected:
-    bool IsAnsi() const override
+    virtual bool IsAnsi() 
     {
         return false;
     }
@@ -3005,7 +2878,7 @@ public:
     };
 
 protected:
-    bool IsAnsi() const override
+    virtual bool IsAnsi() 
     {
         return true;
     }
@@ -3040,38 +2913,38 @@ public:
     }
     
 protected:    
-    LocalDesc GetNativeType() override;
-    LocalDesc GetManagedType() override;
+    virtual LocalDesc GetNativeType();
+    virtual LocalDesc GetManagedType();
 
-    void EmitCreateMngdMarshaler(ILCodeStream* pslILEmit) override = 0;
+    virtual void EmitCreateMngdMarshaler(ILCodeStream* pslILEmit) = 0;
 
     virtual void EmitCallMngdMarshalerMethod(ILCodeStream* pslILEmit, MethodDesc *pMD);
 
-    void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit) override
+    virtual void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit)
     {
         WRAPPER_NO_CONTRACT;
         EmitCallMngdMarshalerMethod(pslILEmit, GetConvertSpaceToManagedMethod());
     }
     
-    void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override
+    virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
     {
         WRAPPER_NO_CONTRACT;
         EmitCallMngdMarshalerMethod(pslILEmit, GetConvertContentsToManagedMethod());
     }
     
-    void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit) override
+    virtual void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit)
     {
         WRAPPER_NO_CONTRACT;
         EmitCallMngdMarshalerMethod(pslILEmit, GetConvertSpaceToNativeMethod());
     }
     
-    void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override
+    virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
     {
         WRAPPER_NO_CONTRACT;
         EmitCallMngdMarshalerMethod(pslILEmit, GetConvertContentsToNativeMethod());
     }
 
-    bool NeedsClearNative() override
+    virtual bool NeedsClearNative()
     {
         LIMITED_METHOD_CONTRACT;
 
@@ -3083,19 +2956,20 @@ protected:
         return false;
     }
     
-    void EmitClearNative(ILCodeStream* pslILEmit) override
+    virtual void EmitClearNative(ILCodeStream* pslILEmit)
     {
         WRAPPER_NO_CONTRACT;
         EmitCallMngdMarshalerMethod(pslILEmit, GetClearNativeMethod());
     }
     
-    void EmitClearNativeContents(ILCodeStream* pslILEmit) override
+    virtual void EmitClearNativeContents(ILCodeStream* pslILEmit)
     {
         WRAPPER_NO_CONTRACT;
         EmitCallMngdMarshalerMethod(pslILEmit, GetClearNativeContentsMethod());
     }
 
-    bool NeedsClearCLR() override
+    
+    virtual bool NeedsClearCLR()
     {
         LIMITED_METHOD_CONTRACT;
 
@@ -3107,7 +2981,7 @@ protected:
         return false;
     }
 
-    void EmitClearCLR(ILCodeStream* pslILEmit) override
+    virtual void EmitClearCLR(ILCodeStream* pslILEmit)
     {
         WRAPPER_NO_CONTRACT;
         EmitCallMngdMarshalerMethod(pslILEmit, GetClearManagedMethod());
@@ -3153,26 +3027,27 @@ public:
         m_dwSavedSizeArg = LOCAL_NUM_UNUSED;
     }
 
-    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;
+    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();
     
 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);    
 
-    void EmitCreateMngdMarshaler(ILCodeStream* pslILEmit) override;
+    virtual void EmitCreateMngdMarshaler(ILCodeStream* pslILEmit);
 
     void EmitLoadNativeSize(ILCodeStream* pslILEmit);
-    void EmitNewSavedSizeArgLocal(ILCodeStream* pslILEmit);
+    void EmitNewSavedSizeArgLocal();
     
 private :
     DWORD m_dwSavedSizeArg;                 
@@ -3231,11 +3106,11 @@ public:
     
 protected:
 
-    void EmitCreateMngdMarshaler(ILCodeStream* pslILEmit) override;
-    void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override;
-    void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override;
+    virtual void EmitCreateMngdMarshaler(ILCodeStream* pslILEmit);
+    virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
+    virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
 
-    void EmitReInitNative(ILCodeStream* pslILEmit) override
+    virtual void EmitReInitNative(ILCodeStream* pslILEmit)
     {
         CONTRACTL
         {
@@ -3316,25 +3191,25 @@ public:
     }
 
 protected:
-    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;
+    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);
 
 private:
+    bool CanUsePinnedArray();
     void EmitLoadNativeArrayLength(ILCodeStream *pslILEmit);
 
-    MethodDesc *GetConvertContentsToManagedMethod() override;
-    MethodDesc *GetConvertContentsToNativeMethod() override;
-    MethodDesc *GetClearNativeContentsMethod() override;
+    virtual MethodDesc *GetConvertContentsToManagedMethod();
+    virtual MethodDesc *GetConvertContentsToNativeMethod();
+    virtual MethodDesc *GetClearNativeContentsMethod();
 
     MethodDesc *GetExactMarshalerMethod(MethodDesc *pGenericMD);
 };
@@ -3385,7 +3260,7 @@ public:
     }
         
 protected:
-    void EmitCreateMngdMarshaler(ILCodeStream* pslILEmit) override;
+    virtual void EmitCreateMngdMarshaler(ILCodeStream* pslILEmit);
 };
 
 class MngdRefCustomMarshaler
@@ -3397,6 +3272,8 @@ 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;
 };
 
@@ -3416,13 +3293,13 @@ public:
     static void EmitConvertWinRTUriToCLRUri(ILCodeStream* pslILEmit, LoaderAllocator* pLoader);
 
 protected:
-    LocalDesc GetNativeType() override;
-    LocalDesc GetManagedType() override;
+    virtual LocalDesc GetNativeType();
+    virtual LocalDesc GetManagedType();
 
-    void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override;    
-    void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override;
+    virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);    
+    virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
 
-    bool NeedsClearNative() override;
+    virtual bool NeedsClearNative();
     void EmitClearNative(ILCodeStream* pslILEmit);
 };
 
@@ -3440,13 +3317,13 @@ public:
     static void EmitConvertWinRTEventArgsToCLREventArgs(ILCodeStream* pslILEmit, LoaderAllocator* pLoader);
 
 protected:
-    LocalDesc GetNativeType() override;
-    LocalDesc GetManagedType() override;
+    virtual LocalDesc GetNativeType();
+    virtual LocalDesc GetManagedType();
 
-    void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override;    
-    void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override;
+    virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);    
+    virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
 
-    bool NeedsClearNative() override;
+    virtual bool NeedsClearNative();
     void EmitClearNative(ILCodeStream* pslILEmit);
 };
 
@@ -3464,13 +3341,13 @@ public:
     static void EmitConvertWinRTEventArgsToCLREventArgs(ILCodeStream* pslILEmit, LoaderAllocator* pLoader);
 
 protected:
-    LocalDesc GetNativeType() override;
-    LocalDesc GetManagedType() override;
+    virtual LocalDesc GetNativeType();
+    virtual LocalDesc GetManagedType();
 
-    void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override;    
-    void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override;
+    virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);    
+    virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
 
-    bool NeedsClearNative() override;
+    virtual bool NeedsClearNative();
     void EmitClearNative(ILCodeStream* pslILEmit);
 };
 
@@ -3485,14 +3362,14 @@ public:
     };
 
 protected:
-    LocalDesc GetNativeType() override;
-    LocalDesc GetManagedType() override;
+    virtual LocalDesc GetNativeType();
+    virtual LocalDesc GetManagedType();
 
-    void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override;    
-    void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override;
+    virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);    
+    virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
 
-    bool NeedsClearNative() override;
-    void EmitReInitNative(ILCodeStream* pslILEmit) override;
+    virtual bool NeedsClearNative();
+    virtual void EmitReInitNative(ILCodeStream* pslILEmit);
 };
 
 class ILNullableMarshaler : public ILMarshaler
@@ -3506,12 +3383,12 @@ public:
     };
                 
 protected:
-    LocalDesc GetNativeType() override;
-    LocalDesc GetManagedType() override;
-    bool NeedsClearNative() override;
-    void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override;
-    void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override;    
-    void EmitClearNative(ILCodeStream* pslILEmit) override;    
+    virtual LocalDesc GetNativeType();
+    virtual LocalDesc GetManagedType();
+    virtual bool NeedsClearNative();
+    virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
+    virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);    
+    virtual void EmitClearNative(ILCodeStream* pslILEmit);    
 
 private:
     MethodDesc *GetExactMarshalerMethod(MethodDesc *pGenericMD);
@@ -3528,15 +3405,15 @@ public:
     };
 
 protected:
-    LocalDesc GetNativeType() override;
-    LocalDesc GetManagedType() override;
+    virtual LocalDesc GetNativeType();
+    virtual LocalDesc GetManagedType();
 
-    void EmitConvertContentsCLRToNative(ILCodeStream * pslILEmit) override;
-    void EmitConvertContentsNativeToCLR(ILCodeStream * pslILEmit) override;
+    virtual void EmitConvertContentsCLRToNative(ILCodeStream * pslILEmit);
+    virtual void EmitConvertContentsNativeToCLR(ILCodeStream * pslILEmit);
 
-    bool NeedsClearNative() override;
-    void EmitClearNative(ILCodeStream * pslILEmit) override;
-    void EmitReInitNative(ILCodeStream * pslILEmit) override;
+    virtual bool NeedsClearNative();
+    virtual void EmitClearNative(ILCodeStream * pslILEmit);
+    virtual void EmitReInitNative(ILCodeStream * pslILEmit);
 };
 
 class ILHResultExceptionMarshaler : public ILMarshaler
@@ -3550,13 +3427,13 @@ public:
     };
 
 protected:
-    LocalDesc GetNativeType() override;
-    LocalDesc GetManagedType() override;
+    virtual LocalDesc GetNativeType();
+    virtual LocalDesc GetManagedType();
 
-    void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override;    
-    void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override;
+    virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);    
+    virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
 
-    bool NeedsClearNative() override;
+    virtual bool NeedsClearNative();
 };
 
 class ILKeyValuePairMarshaler : public ILMarshaler
@@ -3570,12 +3447,12 @@ public:
     };
                 
 protected:
-    LocalDesc GetNativeType() override;
-    LocalDesc GetManagedType() override;
-    bool NeedsClearNative() override;
-    void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override;
-    void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override;
-    void EmitClearNative(ILCodeStream* pslILEmit) override;
+    virtual LocalDesc GetNativeType();
+    virtual LocalDesc GetManagedType();
+    virtual bool NeedsClearNative();
+    virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
+    virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
+    virtual void EmitClearNative(ILCodeStream* pslILEmit);
 
 private:
     MethodDesc *GetExactMarshalerMethod(MethodDesc *pGenericMD);
index c468f48..1540280 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_Obj_RetVoid, r(C(CLEANUP_WORK_LIST_ELEMENT)) j, v))
+DEFINE_METASIG_T(SM(RefCleanupWorkListElement_Delegate_RetVoid, r(C(CLEANUP_WORK_LIST_ELEMENT)) C(DELEGATE), v))
 
 #ifdef FEATURE_ICASTABLE
 DEFINE_METASIG_T(SM(ICastable_RtType_RefException_RetBool, C(ICASTABLE) C(CLASS) r(C(EXCEPTION)), F))
index 607463a..4e5ddf9 100644 (file)
@@ -3269,7 +3269,7 @@ void MarshalInfo::GenerateArgumentIL(NDirectStubLinker* psl,
     pcsMarshal->EmitNOP("// } argument");
     pcsUnmarshal->EmitNOP("// } argument");
 
-    pMarshaler->EmitSetupArgumentForDispatch(pcsDispatch);
+    pMarshaler->EmitSetupArgument(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->EmitSetupArgumentForDispatch(pcsDispatch);
+        pHiddenLengthMarshaler->EmitSetupArgument(pcsDispatch);
     }
 }
 
index 201db98..403b27b 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,          KEEP_ALIVE_VIA_CLEANUP_LIST,    KeepAliveViaCleanupList,       SM_RefCleanupWorkListElement_Obj_RetVoid)
+DEFINE_METHOD(STUBHELPERS,          ADD_TO_CLEANUP_LIST_DELEGATE,    AddToCleanupList,             SM_RefCleanupWorkListElement_Delegate_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)