}
}
- // 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);
}
}
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);
}
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[] =
{
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);
}
}
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)
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)
{
STANDARD_VM_CONTRACT;
+ INDEBUG(m_fCoMemoryAllocated = true);
+
ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
DWORD dwLengthLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
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);
+ }
}
//
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)
}
//
// 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);
}
}
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);
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);
}
EmitLoadManagedValue(pslILEmit);
EmitLoadNativeValue(pslILEmit);
- EmitLoadCleanupWorkList(pslILEmit);
+ m_pslNDirect->LoadCleanupWorkList(pslILEmit);
// static void FmtClassUpdateNativeInternal(object obj, byte* pNative, IntPtr pOptionalCleanupList);
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);
}
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,
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;
}
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;
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;
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()
{
STANDARD_VM_CONTRACT;
// marshaler.ClearNative(nativeHome)
- EmitLoadMngdMarshalerAddr(pslILEmit);
+ pslILEmit->EmitLDLOCA(m_dwMarshalerLocalNum);
EmitLoadNativeValue(pslILEmit);
pslILEmit->EmitCALL(METHOD__ASANY_MARSHALER__CLEAR_NATIVE, 2, 0);
}
}
}
+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);
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
{
}
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();
+ }
}
//
unsigned countParamIdx = mops.countParamIdx;
if (!IsCLRToNative(m_dwMarshalFlags))
{
- int lcidParamIdx = GetLCIDParamIndex();
+ int lcidParamIdx = m_pslNDirect->GetLCIDParamIdx();
if (lcidParamIdx >= 0 && (unsigned)lcidParamIdx <= countParamIdx)
{
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)
{
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)
{
if (IsByref(m_dwMarshalFlags) || IsRetval(m_dwMarshalFlags) || IsOut(m_dwMarshalFlags))
{
- ILCodeLabel *pSkipGetLengthLabel = pslILEmit->NewCodeLabel();
+ ILCodeLabel *pSkipGetLengthLabel = m_pcsMarshal->NewCodeLabel();
// nativeLen = 0
pslILEmit->EmitLDC(0);
}
}
- 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);
+ }
}
}
{
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);
}
}
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;
void InitHome(MarshalHomeType homeType, DWORD dwHomeIndex)
{
LIMITED_METHOD_CONTRACT;
-
m_homeType = homeType;
m_dwHomeIndex = dwHomeIndex;
}
#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:
m_pslNDirect = pslNDirect;
}
-private:
void Init(ILCodeStream* pcsMarshal,
ILCodeStream* pcsUnmarshal,
UINT argidx,
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)
// 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))
{
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());
#endif // FEATURE_COMINTEROP
- void EmitSetupArgumentForDispatch(ILCodeStream* pslILEmit)
+ virtual void EmitSetupArgument(ILCodeStream* pslILEmit)
{
STANDARD_VM_CONTRACT;
}
}
- void EmitMarshalReturnValue(
+ virtual void EmitMarshalReturnValue(
ILCodeStream* pcsMarshal,
ILCodeStream* pcsUnmarshal,
ILCodeStream* pcsDispatch,
LIMITED_METHOD_CONTRACT;
}
- void EmitLoadMngdMarshaler(ILCodeStream* pslILEmit)
+ virtual void EmitLoadMngdMarshaler(ILCodeStream* pslILEmit)
{
CONTRACTL
{
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
}
}
- void EmitMarshalArgumentCLRToNative()
+ virtual void EmitMarshalArgumentCLRToNative()
{
CONTRACTL
{
}
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)
}
}
- 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
}
}
- void EmitMarshalArgumentNativeToCLR()
+ virtual void EmitMarshalArgumentNativeToCLR()
{
CONTRACTL
{
virtual LocalDesc GetNativeType() = 0;
virtual LocalDesc GetManagedType() = 0;
- virtual void EmitSetupArgumentForMarshalling(ILCodeStream* pslILEmit)
- {
- LIMITED_METHOD_CONTRACT;
- }
-
//
// Native-to-CLR
//
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;
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;
EmitStoreNativeValue(pslILEmit);
}
- bool IsManagedPassedByRef()
+ virtual bool IsManagedPassedByRef()
{
LIMITED_METHOD_CONTRACT;
return IsByref(m_dwMarshalFlags);
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,
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,
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;
EmitStoreNativeValue(pslILEmit);
}
- void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override
+ virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
{
STANDARD_VM_CONTRACT;
// 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
{
//
// 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
// 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
{
//
// marshal
//
- EmitMarshalArgumentAddressNativeToCLR();
+ EmitLoadNativeHomeAddr(m_pcsMarshal);
+ EmitStoreManagedHomeAddr(m_pcsMarshal);
//
// no unmarshaling is necessary since we directly passed the pointer to managed
};
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
};
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;
};
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
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
};
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;
};
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;
};
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;
};
#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
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;
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
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
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);
};
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,
public:
- LocalDesc GetManagedType() override
+ LocalDesc GetManagedType()
{
LIMITED_METHOD_CONTRACT;
return LocalDesc();
}
- LocalDesc GetNativeType() override
+ LocalDesc GetNativeType()
{
LIMITED_METHOD_CONTRACT;
return LocalDesc();
};
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
};
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
};
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);
};
};
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);
};
};
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
};
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);
};
};
protected:
- LocalDesc GetNativeType() override
+ virtual LocalDesc GetNativeType()
{
LIMITED_METHOD_CONTRACT;
return LocalDesc(ELEMENT_TYPE_I);
}
- LocalDesc GetManagedType() override
+ virtual LocalDesc GetManagedType()
{
STANDARD_VM_CONTRACT;
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;
pslILEmit->EmitCALL(METHOD__MARSHAL__FREE_CO_TASK_MEM, 1, 0);
}
- void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit) override
+ virtual void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit)
{
STANDARD_VM_CONTRACT;
}
}
- void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override
+ virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
{
STANDARD_VM_CONTRACT;
}
}
- void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override
+ virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
{
STANDARD_VM_CONTRACT;
};
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
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;
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;
};
};
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
}
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
{
}
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
}
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
};
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
};
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
};
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
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
};
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
}
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;
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
};
protected:
- bool IsAnsi() const override
+ virtual bool IsAnsi()
{
return false;
}
};
protected:
- bool IsAnsi() const override
+ virtual bool IsAnsi()
{
return true;
}
}
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;
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;
return false;
}
- void EmitClearCLR(ILCodeStream* pslILEmit) override
+ virtual void EmitClearCLR(ILCodeStream* pslILEmit)
{
WRAPPER_NO_CONTRACT;
EmitCallMngdMarshalerMethod(pslILEmit, GetClearManagedMethod());
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;
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
{
}
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);
};
}
protected:
- void EmitCreateMngdMarshaler(ILCodeStream* pslILEmit) override;
+ virtual void EmitCreateMngdMarshaler(ILCodeStream* pslILEmit);
};
class MngdRefCustomMarshaler
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;
};
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);
};
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);
};
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);
};
};
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
};
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);
};
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
};
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
};
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);
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))
pcsMarshal->EmitNOP("// } argument");
pcsUnmarshal->EmitNOP("// } argument");
- pMarshaler->EmitSetupArgumentForDispatch(pcsDispatch);
+ pMarshaler->EmitSetupArgument(pcsDispatch);
if (m_paramidx == 0)
{
CorCallingConvention callConv = psl->GetStubTargetCallingConv();
if (managedToNative)
{
ILCodeStream* pcsDispatch = psl->GetDispatchCodeStream();
- pHiddenLengthMarshaler->EmitSetupArgumentForDispatch(pcsDispatch);
+ pHiddenLengthMarshaler->EmitSetupArgument(pcsDispatch);
}
}
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)