<data name="Interop_Marshal_Unmappable_Char" xml:space="preserve">
<value>Cannot marshal: Encountered unmappable character.</value>
</data>
+ <data name="Interop_Marshal_SafeHandle_InvalidOperation" xml:space="preserve">
+ <value>Structures containing SafeHandle fields are not allowed in this operation.</value>
+ </data>
+ <data name="Interop_Marshal_CannotCreateSafeHandleField" xml:space="preserve">
+ <value>SafeHandle fields cannot be created from an unmanaged handle.</value>
+ </data>
+ <data name="Interop_Marshal_CannotCreateCriticalHandleField" xml:space="preserve">
+ <value>CriticalHandle fields cannot be created from an unmanaged handle.</value>
+ </data>
<data name="InvalidCast_CannotCastNullToValueType" xml:space="preserve">
<value>Null object cannot be converted to a value type.</value>
</data>
{
Interop.Ole32.CoTaskMemFree(pNative);
}
+
+ internal static unsafe void ConvertFixedToNative(int flags, string strManaged, IntPtr pNativeBuffer, int length)
+ {
+ int numChars = strManaged.Length;
+ if (numChars >= length)
+ {
+ numChars = length - 1;
+ }
+
+ byte* buffer = (byte*)pNativeBuffer;
+
+ // Flags defined in ILFixedCSTRMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit).
+ bool throwOnUnmappableChar = 0 != (flags >> 8);
+ bool bestFit = 0 != (flags & 0xFF);
+ uint defaultCharUsed = 0;
+
+ int cbWritten;
+
+ fixed (char* pwzChar = strManaged)
+ {
+#if PLATFORM_WINDOWS
+ cbWritten = Interop.Kernel32.WideCharToMultiByte(
+ Interop.Kernel32.CP_ACP,
+ bestFit ? 0 : Interop.Kernel32.WC_NO_BEST_FIT_CHARS,
+ pwzChar,
+ numChars,
+ buffer,
+ length,
+ IntPtr.Zero,
+ throwOnUnmappableChar ? new IntPtr(&defaultCharUsed) : IntPtr.Zero);
+#else
+ cbWritten = Encoding.UTF8.GetBytes(pwzChar, numChars, buffer, length);
+#endif
+ }
+
+ if (defaultCharUsed != 0)
+ {
+ throw new ArgumentException(SR.Interop_Marshal_Unmappable_Char);
+ }
+
+ if (cbWritten == (int)length)
+ {
+ cbWritten--;
+ }
+
+ buffer[cbWritten] = 0;
+ }
+
+ internal static unsafe string ConvertFixedToManaged(IntPtr cstr, int length)
+ {
+ int allocSize = length + 2;
+ if (allocSize < length)
+ {
+ throw new OutOfMemoryException();
+ }
+ Span<sbyte> originalBuffer = new Span<sbyte>((byte*)cstr, length);
+
+ Span<sbyte> tempBuf = stackalloc sbyte[allocSize];
+
+ originalBuffer.CopyTo(tempBuf);
+ tempBuf[length - 1] = 0;
+ tempBuf[length] = 0;
+ tempBuf[length + 1] = 0;
+
+ fixed (sbyte* buffer = tempBuf)
+ {
+ return new string(buffer, 0, string.strlen((byte*)buffer));
+ }
+ }
} // class CSTRMarshaler
internal static class UTF8Marshaler
}
} // class AnsiBSTRMarshaler
- internal static class WSTRBufferMarshaler
+ internal static class FixedWSTRMarshaler
{
- internal static IntPtr ConvertToNative(string strManaged)
+ internal static unsafe void ConvertToNative(string? strManaged, IntPtr nativeHome, int length)
{
- Debug.Fail("NYI");
- return IntPtr.Zero;
- }
+ ReadOnlySpan<char> managed = strManaged;
+ Span<char> native = new Span<char>((char*)nativeHome, length);
- internal static string? ConvertToManaged(IntPtr bstr)
- {
- Debug.Fail("NYI");
- return null;
- }
+ int numChars = Math.Min(managed.Length, length - 1);
- internal static void ClearNative(IntPtr pNative)
- {
- Debug.Fail("NYI");
+ managed.Slice(0, numChars).CopyTo(native);
+ native[numChars] = '\0';
}
} // class WSTRBufferMarshaler
#endif // FEATURE_COMINTEROP
- internal static class ValueClassMarshaler
+ internal sealed class HandleMarshaler
{
- [MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern void ConvertToNative(IntPtr dst, IntPtr src, IntPtr pMT, ref CleanupWorkListElement pCleanupWorkList);
+ internal static unsafe IntPtr ConvertSafeHandleToNative(SafeHandle? handle, bool hasCleanupWorkList, ref CleanupWorkListElement? cleanupWorkList)
+ {
+ if (!hasCleanupWorkList)
+ {
+ throw new InvalidOperationException(SR.Interop_Marshal_SafeHandle_InvalidOperation);
+ }
- [MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern void ConvertToManaged(IntPtr dst, IntPtr src, IntPtr pMT);
+ if (handle is null)
+ {
+ throw new ArgumentNullException(nameof(handle));
+ }
- [MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern void ClearNative(IntPtr dst, IntPtr pMT);
- } // class ValueClassMarshaler
+ return StubHelpers.AddToCleanupList(ref cleanupWorkList, handle);
+ }
+
+ internal static unsafe void ThrowSafeHandleFieldChanged()
+ {
+ throw new NotSupportedException(SR.Interop_Marshal_CannotCreateSafeHandleField);
+ }
+
+ internal static unsafe void ThrowCriticalHandleFieldChanged()
+ {
+ throw new NotSupportedException(SR.Interop_Marshal_CannotCreateCriticalHandleField);
+ }
+ }
internal static class DateMarshaler
{
- [MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern double ConvertToNative(DateTime managedDate);
+ internal static double ConvertToNative(DateTime managedDate)
+ {
+ return managedDate.ToOADate();
+ }
- // The return type is really DateTime but we use long to avoid the pain associated with returning structures.
- [MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern long ConvertToManaged(double nativeDate);
+ internal static long ConvertToManaged(double nativeDate)
+ {
+ return DateTime.DoubleDateToTicks(nativeDate);
+ }
} // class DateMarshaler
#if FEATURE_COMINTEROP
#pragma warning disable CA1823 // not used by managed code
private IntPtr m_pElementMT;
private IntPtr m_Array;
+ private IntPtr m_pManagedNativeArrayMarshaler;
private int m_NativeDataValid;
private int m_BestFitMap;
private int m_ThrowOnUnmappableChar;
}
[MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern void CreateMarshaler(IntPtr pMarshalState, IntPtr pMT, int dwFlags);
+ internal static extern void CreateMarshaler(IntPtr pMarshalState, IntPtr pMT, int dwFlags, IntPtr pManagedMarshaler);
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern void ConvertSpaceToNative(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
internal static extern void ConvertContentsToManaged(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern void ClearNative(IntPtr pMarshalState, IntPtr pNativeHome, int cElements);
+ internal static extern void ClearNative(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome, int cElements);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern void ClearNativeContents(IntPtr pMarshalState, IntPtr pNativeHome, int cElements);
+ internal static extern void ClearNativeContents(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome, int cElements);
} // class MngdNativeArrayMarshaler
+ internal static class MngdFixedArrayMarshaler
+ {
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ internal static extern void CreateMarshaler(IntPtr pMarshalState, IntPtr pMT, int dwFlags, int cElements, IntPtr pManagedMarshaler);
+
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ internal static extern void ConvertSpaceToNative(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
+
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ internal static extern void ConvertContentsToNative(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
+
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ internal static extern void ConvertSpaceToManaged(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
+
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ internal static extern void ConvertContentsToManaged(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
+
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ internal static extern void ClearNativeContents(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
+ } // class MngdFixedArrayMarshaler
+
#if FEATURE_COMINTEROP
internal static class MngdSafeArrayMarshaler
{
[MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern void CreateMarshaler(IntPtr pMarshalState, IntPtr pMT, int iRank, int dwFlags);
+ internal static extern void CreateMarshaler(IntPtr pMarshalState, IntPtr pMT, int iRank, int dwFlags, IntPtr pManagedMarshaler);
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern void ConvertSpaceToNative(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
internal static class MngdHiddenLengthArrayMarshaler
{
[MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern void CreateMarshaler(IntPtr pMarshalState, IntPtr pMT, IntPtr cbElementSize, ushort vt);
+ internal static extern void CreateMarshaler(IntPtr pMarshalState, IntPtr pMT, IntPtr cbElementSize, ushort vt, IntPtr pManagedMarshaler);
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern void ConvertSpaceToNative(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
MngdNativeArrayMarshaler.CreateMarshaler(
pvArrayMarshaler,
IntPtr.Zero, // not needed as we marshal primitive VTs only
- dwArrayMarshalerFlags);
+ dwArrayMarshalerFlags,
+ IntPtr.Zero); // not needed as we marshal primitive VTs only
IntPtr pNativeHome;
IntPtr pNativeHomeAddr = new IntPtr(&pNativeHome);
#endif
} // struct NativeVariant
+ // This NativeDecimal type is very similar to the System.Decimal type, except it requires an 8-byte alignment
+ // like the native DECIMAL type instead of the 4-byte requirement of the System.Decimal type.
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct NativeDecimal
+ {
+ private ushort reserved;
+ private ushort signScale;
+ private uint hi32;
+ private ulong lo64;
+ }
+
internal abstract class CleanupWorkListElement
{
private CleanupWorkListElement? m_Next;
}
}
- public static void AddToCleanupList(ref CleanupWorkListElement list, CleanupWorkListElement newElement)
+ public static void AddToCleanupList(ref CleanupWorkListElement? list, CleanupWorkListElement newElement)
{
if (list == null)
{
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern void ThrowInteropParamException(int resID, int paramIdx);
- internal static IntPtr AddToCleanupList(ref CleanupWorkListElement pCleanupWorkList, SafeHandle handle)
+ internal static IntPtr AddToCleanupList(ref CleanupWorkListElement? pCleanupWorkList, SafeHandle handle)
{
SafeHandleCleanupWorkListElement element = new SafeHandleCleanupWorkListElement(handle);
CleanupWorkListElement.AddToCleanupList(ref pCleanupWorkList, element);
return element.AddRef();
}
- internal static void KeepAliveViaCleanupList(ref CleanupWorkListElement pCleanupWorkList, object obj)
+ internal static void KeepAliveViaCleanupList(ref CleanupWorkListElement? pCleanupWorkList, object obj)
{
KeepAliveCleanupWorkListElement element = new KeepAliveCleanupWorkListElement(obj);
CleanupWorkListElement.AddToCleanupList(ref pCleanupWorkList, element);
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern unsafe void FmtClassUpdateCLRInternal(object obj, byte* pNative);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern unsafe void LayoutDestroyNativeInternal(byte* pNative, IntPtr pMT);
+ internal static extern unsafe void LayoutDestroyNativeInternal(object obj, byte* pNative);
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern object AllocateInternal(IntPtr typeHandle);
#include <comcallablewrapper.h>
#include <gcdump.h>
+#include <fieldmarshaler.h>
#if !defined(FEATURE_CORESYSTEM)
#include <algorithm>
VERBOSE_TYPES );
DisplayWriteFieldInt( m_numCTMFields, eecli->m_numCTMFields,
EEClassLayoutInfo, VERBOSE_TYPES );
- PTR_FieldMarshaler fmArray = eecli->GetFieldMarshalers();
- DisplayWriteFieldAddress( m_pFieldMarshalers,
+ PTR_NativeFieldDescriptor fmArray = eecli->GetNativeFieldDescriptors();
+ DisplayWriteFieldAddress( m_pNativeFieldDescriptors,
DPtrToPreferredAddr(fmArray),
eecli->m_numCTMFields
- * MAXFIELDMARSHALERSIZE,
+ * sizeof(NativeFieldDescriptor),
EEClassLayoutInfo, VERBOSE_TYPES );
/* REVISIT_TODO Wed 03/22/2006
- * Dump the various types of FieldMarshalers.
+ * Dump the various types of NativeFieldDescriptors.
*/
#if 0
- DisplayStartArrayWithOffset( m_pFieldMarshalers, NULL,
+ DisplayStartArrayWithOffset( m_pNativeFieldDescriptors, NULL,
EEClassLayoutInfo, VERBOSE_TYPES );
for( unsigned i = 0; i < eecli->m_numCTMFields; ++i )
{
/* REVISIT_TODO Wed 03/22/2006
* Try to display the type of the field marshaler in the future.
*/
- PTR_FieldMarshaler current = fmArray + i;
- DisplayStartStructure( "FieldMarshaler",
+ PTR_NativeFieldDescriptor current = fmArray + i;
+ DisplayStartStructure( "NativeFieldDescriptor",
DPtrToPreferredAddr(current),
sizeof(*current), VERBOSE_TYPES );
WriteFieldFieldDesc( m_pFD, PTR_FieldDesc(TO_TADDR(current->m_pFD)),
- FieldMarshaler, VERBOSE_TYPES );
- DisplayWriteFieldInt( m_dwExternalOffset,
- current->m_dwExternalOffset, FieldMarshaler,
+ NativeFieldDescriptor, VERBOSE_TYPES );
+ DisplayWriteFieldInt( m_offset,
+ current->m_offset, NativeFieldDescriptor,
VERBOSE_TYPES );
DisplayEndStructure( VERBOSE_TYPES ); //FieldMarshaler
}
- DisplayEndArray( "Number of FieldMarshalers", VERBOSE_TYPES ); //m_pFieldMarshalers
+ DisplayEndArray( "Number of NativeFieldDescriptors", VERBOSE_TYPES ); //m_pNativeFieldDescriptors
#endif
DisplayEndStructure( EECLASSES ); //LayoutInfo
IDS_CLASSLOAD_WRONGCPU "Could not load file or assembly '%1'. This assembly was compiled for a different processor."
IDS_CANNOT_MARSHAL "Type '%1' cannot be marshaled as an unmanaged structure; no meaningful size or offset can be computed."
+
+ IDS_CANNOT_MARSHAL_RECURSIVE_DEF "Type '%1' cannot be marshaled as an unmanaged structure; its native layout contains a recursive definition so no meaningful size can be computed."
IDS_INVALID_REDIM "Illegal attempt to replace or redimension a fixed or locked SafeArray."
#define IDS_EE_ADUNLOAD_CANT_UNWIND_THREAD 0x1769
#define IDS_CANNOT_MARSHAL 0x1770
+#define IDS_CANNOT_MARSHAL_RECURSIVE_DEF 0x1771
#define IDS_EE_HASH_VAL_FAILED 0x1772
<map value="0x8" message="$(string.RuntimePublisher.ILStubGenerated.DelegateMapMessage)"/>
<map value="0x10" message="$(string.RuntimePublisher.ILStubGenerated.VarArgMapMessage)"/>
<map value="0x20" message="$(string.RuntimePublisher.ILStubGenerated.UnmanagedCalleeMapMessage)"/>
+ <map value="0x40" message="$(string.RuntimePublisher.ILStubGenerated.StructStubMapMessage)"/>
</bitMap>
<bitMap name="StartupFlagsMap">
<map value="0x000001" message="$(string.RuntimePublisher.Startup.CONCURRENT_GCMapMessage)"/>
<string id="RuntimePublisher.ILStubGenerated.DelegateMapMessage" value="Delegate" />
<string id="RuntimePublisher.ILStubGenerated.VarArgMapMessage" value="VarArg" />
<string id="RuntimePublisher.ILStubGenerated.UnmanagedCalleeMapMessage" value="UnmanagedCallee" />
+ <string id="RuntimePublisher.ILStubGenerated.StructStubMapMessage" value="StructMarshal" />
<string id="RuntimePublisher.Contention.ManagedMapMessage" value="Managed" />
<string id="RuntimePublisher.Contention.NativeMapMessage" value="Native" />
<string id="RuntimePublisher.TailCallType.OptimizedMapMessage" value="OptimizedTailCall" />
#define X86RegFromAMD64Reg(extended_reg) \
((X86Reg)(((int)extended_reg) & X86_REGISTER_MASK))
-
-//=======================================================================
-// IMPORTANT: This value is used to figure out how much to allocate
-// for a fixed array of FieldMarshaler's. That means it must be at least
-// as large as the largest FieldMarshaler subclass. This requirement
-// is guarded by an assert.
-//=======================================================================
-#define MAXFIELDMARSHALERSIZE 40
-
-
// Why is the return value ARG_SLOT? On 64-bit systems, that is 64-bits
// and much bigger than necessary for R4, requiring explicit downcasts.
inline
// Offset of pc register
#define PC_REG_RELATIVE_OFFSET 4
-//=======================================================================
-// IMPORTANT: This value is used to figure out how much to allocate
-// for a fixed array of FieldMarshaler's. That means it must be at least
-// as large as the largest FieldMarshaler subclass. This requirement
-// is guarded by an assert.
-//=======================================================================
-#ifdef BIT64
-#define MAXFIELDMARSHALERSIZE 40
-#else
-#define MAXFIELDMARSHALERSIZE 24
-#endif
-
//**********************************************************************
// Parameter size
//**********************************************************************
// this is the offset by which it should be decremented to arrive at the callsite.
#define STACKWALK_CONTROLPC_ADJUST_OFFSET 4
-//=======================================================================
-// IMPORTANT: This value is used to figure out how much to allocate
-// for a fixed array of FieldMarshaler's. That means it must be at least
-// as large as the largest FieldMarshaler subclass. This requirement
-// is guarded by an assert.
-//=======================================================================
-#define MAXFIELDMARSHALERSIZE 40
-
inline
ARG_SLOT FPSpillToR8(void* pSpillSlot)
{
#include "jitinterface.h"
#include "eeconfig.h"
#include "log.h"
-#include "fieldmarshaler.h"
#include "cgensys.h"
#include "array.h"
#include "typestring.h"
{
if (pClass->HasLayout() && pClass->GetLayoutInfo()->GetNumCTMFields() > 0)
{
- image->PlaceStructureForAddress((void *)pClass->GetLayoutInfo()->GetFieldMarshalers(), CORCOMPILE_SECTION_HOT);
+ image->PlaceStructureForAddress((void *)pClass->GetLayoutInfo()->GetNativeFieldDescriptors(), CORCOMPILE_SECTION_HOT);
}
}
}
CorElementType hfaType = ELEMENT_TYPE_END;
#ifndef DACCESS_COMPILE
- const FieldMarshaler *pFieldMarshaler = GetFieldMarshalers();
- while (numReferenceFields--)
+ const NativeFieldDescriptor* pNativeFieldDescriptorsBegin = GetNativeFieldDescriptors();
+ const NativeFieldDescriptor* pNativeFieldDescriptorsEnd = pNativeFieldDescriptorsBegin + numReferenceFields;
+ for(const NativeFieldDescriptor* pCurrNFD = pNativeFieldDescriptorsBegin; pCurrNFD < pNativeFieldDescriptorsEnd; ++pCurrNFD)
{
CorElementType fieldType = ELEMENT_TYPE_END;
- NativeFieldFlags category = pFieldMarshaler->GetNativeFieldFlags();
+ NativeFieldFlags category = pCurrNFD->GetNativeFieldFlags();
if (category & NATIVE_FIELD_SUBCATEGORY_FLOAT)
{
}
// An HFA can only have aligned float and double fields.
- if (pFieldMarshaler->GetExternalOffset() % pFieldMarshaler->AlignmentRequirement() != 0)
+ if (pCurrNFD->GetExternalOffset() % pCurrNFD->AlignmentRequirement() != 0)
{
fieldType = ELEMENT_TYPE_END;
}
}
else if (category & NATIVE_FIELD_SUBCATEGORY_NESTED)
{
- fieldType = ((FieldMarshaler_NestedType*)pFieldMarshaler)->GetNestedNativeMethodTable()->GetNativeHFAType();
+ fieldType = pCurrNFD->GetNestedNativeMethodTable()->GetNativeHFAType();
}
else
{
{
return ELEMENT_TYPE_END;
}
-
- ((BYTE*&)pFieldMarshaler) += MAXFIELDMARSHALERSIZE;
}
if (hfaType == ELEMENT_TYPE_END)
if (pInfo->m_numCTMFields > 0)
{
- ZapStoredStructure * pNode = image->StoreStructure(pInfo->GetFieldMarshalers(),
- pInfo->m_numCTMFields * MAXFIELDMARSHALERSIZE,
+ ZapStoredStructure * pNode = image->StoreStructure(pInfo->GetNativeFieldDescriptors(),
+ pInfo->m_numCTMFields * sizeof(NativeFieldDescriptor),
DataImage::ITEM_FIELD_MARSHALERS);
for (UINT iField = 0; iField < pInfo->m_numCTMFields; iField++)
{
- FieldMarshaler *pFM = (FieldMarshaler*)((BYTE *)pInfo->GetFieldMarshalers() + iField * MAXFIELDMARSHALERSIZE);
+ NativeFieldDescriptor *pFM = &pInfo->GetNativeFieldDescriptors()[iField];
pFM->Save(image);
if (iField > 0)
- image->BindPointer(pFM, pNode, iField * MAXFIELDMARSHALERSIZE);
+ image->BindPointer(pFM, pNode, iField * sizeof(NativeFieldDescriptor));
}
}
}
if (HasLayout())
{
- image->FixupRelativePointerField(this, offsetof(LayoutEEClass, m_LayoutInfo.m_pFieldMarshalers));
+ image->FixupRelativePointerField(this, offsetof(LayoutEEClass, m_LayoutInfo.m_pNativeFieldDescriptors));
EEClassLayoutInfo *pInfo = &((LayoutEEClass*)this)->m_LayoutInfo;
- FieldMarshaler *pFM = pInfo->GetFieldMarshalers();
- FieldMarshaler *pFMEnd = (FieldMarshaler*) ((BYTE *)pFM + pInfo->m_numCTMFields*MAXFIELDMARSHALERSIZE);
- while (pFM < pFMEnd)
+ NativeFieldDescriptor* pFMBegin = pInfo->GetNativeFieldDescriptors();
+ NativeFieldDescriptor* pFMEnd = pFMBegin + pInfo->m_numCTMFields;
+ for (NativeFieldDescriptor* pCurr = pFMBegin; pCurr < pFMEnd; ++pCurr)
{
- pFM->Fixup(image);
- ((BYTE*&)pFM) += MAXFIELDMARSHALERSIZE;
+ pCurr->Fixup(image);
}
}
else if (IsDelegate())
_ASSERTE(!(fHasNonTrivialParent && !(pParentMT->HasLayout())));
pEEClassLayoutInfoOut->m_numCTMFields = fHasNonTrivialParent ? pParentMT->GetLayoutInfo()->m_numCTMFields : 0;
- pEEClassLayoutInfoOut->SetFieldMarshalers(NULL);
+ pEEClassLayoutInfoOut->SetNativeFieldDescriptors(NULL);
pEEClassLayoutInfoOut->SetIsBlittable(TRUE);
if (fHasNonTrivialParent)
pEEClassLayoutInfoOut->SetIsBlittable(pParentMT->IsBlittable());
// Now compute the native size of each field
for (LayoutRawFieldInfo* pfwalk = pInfoArrayOut; pfwalk->m_MD != mdFieldDefNil; pfwalk++)
{
- pfwalk->m_nativePlacement.m_size = ((FieldMarshaler*) & (pfwalk->m_FieldMarshaler))->NativeSize();
- pfwalk->m_nativePlacement.m_alignment = ((FieldMarshaler*) & (pfwalk->m_FieldMarshaler))->AlignmentRequirement();
+ pfwalk->m_nativePlacement.m_size = pfwalk->m_nfd.NativeSize();
+ pfwalk->m_nativePlacement.m_alignment = pfwalk->m_nfd.AlignmentRequirement();
#ifdef _DEBUG
// @perf: If the type is blittable, the managed and native layouts have to be identical
// If this type has
if (pEEClassLayoutInfoOut->m_numCTMFields)
{
- pEEClassLayoutInfoOut->SetFieldMarshalers((FieldMarshaler*)(pamTracker->Track(pAllocator->GetLowFrequencyHeap()->AllocMem(S_SIZE_T(MAXFIELDMARSHALERSIZE) * S_SIZE_T(pEEClassLayoutInfoOut->m_numCTMFields)))));
+ pEEClassLayoutInfoOut->SetNativeFieldDescriptors((NativeFieldDescriptor*)(pamTracker->Track(pAllocator->GetLowFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(NativeFieldDescriptor)) * S_SIZE_T(pEEClassLayoutInfoOut->m_numCTMFields)))));
// Bring in the parent's fieldmarshalers
if (fHasNonTrivialParent)
UINT numChildCTMFields = pEEClassLayoutInfoOut->m_numCTMFields - pParentLayoutInfo->m_numCTMFields;
- BYTE *pParentCTMFieldSrcArray = (BYTE*)pParentLayoutInfo->GetFieldMarshalers();
- BYTE *pParentCTMFieldDestArray = ((BYTE*)pEEClassLayoutInfoOut->GetFieldMarshalers()) + MAXFIELDMARSHALERSIZE*numChildCTMFields;
+ NativeFieldDescriptor *pParentCTMFieldSrcArray = pParentLayoutInfo->GetNativeFieldDescriptors();
+ NativeFieldDescriptor *pParentCTMFieldDestArray = pEEClassLayoutInfoOut->GetNativeFieldDescriptors() + numChildCTMFields;
for (UINT parentCTMFieldIndex = 0; parentCTMFieldIndex < pParentLayoutInfo->m_numCTMFields; parentCTMFieldIndex++)
{
- FieldMarshaler *pParentCTMFieldSrc = (FieldMarshaler *)(pParentCTMFieldSrcArray + MAXFIELDMARSHALERSIZE*parentCTMFieldIndex);
- FieldMarshaler *pParentCTMFieldDest = (FieldMarshaler *)(pParentCTMFieldDestArray + MAXFIELDMARSHALERSIZE*parentCTMFieldIndex);
-
- pParentCTMFieldSrc->CopyTo(pParentCTMFieldDest, MAXFIELDMARSHALERSIZE);
+ pParentCTMFieldDestArray[parentCTMFieldIndex] = pParentCTMFieldSrcArray[parentCTMFieldIndex];
}
}
LOG((LF_INTEROP, LL_INFO100000, "%s", fieldname));
LOG((LF_INTEROP, LL_INFO100000, "\n"));
- if (((FieldMarshaler*)&pfwalk->m_FieldMarshaler)->IsIllegalMarshaler())
+ if (pfwalk->m_nfd.IsUnmarshalable())
illegalMarshaler = TRUE;
}
// If we are dealing with a non trivial parent, determine if it has any illegal marshallers.
if (fHasNonTrivialParent)
{
- FieldMarshaler *pParentFM = pParentMT->GetLayoutInfo()->GetFieldMarshalers();
+ NativeFieldDescriptor *pParentNFD = pParentMT->GetLayoutInfo()->GetNativeFieldDescriptors();
for (UINT i = 0; i < pParentMT->GetLayoutInfo()->m_numCTMFields; i++)
{
- if (pParentFM->IsIllegalMarshaler())
- illegalMarshaler = TRUE;
- ((BYTE*&)pParentFM) += MAXFIELDMARSHALERSIZE;
+ if (pParentNFD->IsUnmarshalable())
+ illegalMarshaler = TRUE;
}
}
#pragma warning(pop)
#endif // _PREFAST_
+namespace
+{
+ //=======================================================================
+ // This function returns TRUE if the provided corElemType disqualifies
+ // the structure from being a managed-sequential structure.
+ // The fsig parameter is used when the corElemType doesn't contain enough information
+ // to successfully determine if this field disqualifies the type from being
+ // managed-sequential.
+ // This function also fills in the pManagedPlacementInfo structure for this field.
+ //=======================================================================
+ BOOL IsDisqualifiedFromManagedSequential(CorElementType corElemType, MetaSig &fsig, RawFieldPlacementInfo * pManagedPlacementInfo)
+ {
+ // This type may qualify for ManagedSequential. Collect managed size and alignment info.
+ if (CorTypeInfo::IsPrimitiveType(corElemType))
+ {
+ // Safe cast - no primitive type is larger than 4gb!
+ pManagedPlacementInfo->m_size = ((UINT32)CorTypeInfo::Size(corElemType));
+ #if defined(_TARGET_X86_) && defined(UNIX_X86_ABI)
+ switch (corElemType)
+ {
+ // The System V ABI for i386 defines different packing for these types.
+ case ELEMENT_TYPE_I8:
+ case ELEMENT_TYPE_U8:
+ case ELEMENT_TYPE_R8:
+ {
+ pManagedPlacementInfo->m_alignment = 4;
+ break;
+ }
+
+ default:
+ {
+ pManagedPlacementInfo->m_alignment = pManagedPlacementInfo->m_size;
+ break;
+ }
+ }
+ #else // _TARGET_X86_ && UNIX_X86_ABI
+ pManagedPlacementInfo->m_alignment = pManagedPlacementInfo->m_size;
+ #endif
+
+ return FALSE;
+ }
+ else if (corElemType == ELEMENT_TYPE_PTR)
+ {
+ pManagedPlacementInfo->m_size = TARGET_POINTER_SIZE;
+ pManagedPlacementInfo->m_alignment = TARGET_POINTER_SIZE;
+
+ return FALSE;
+ }
+ else if (corElemType == ELEMENT_TYPE_VALUETYPE)
+ {
+ TypeHandle pNestedType = fsig.GetLastTypeHandleThrowing(ClassLoader::LoadTypes,
+ CLASS_LOAD_APPROXPARENTS,
+ TRUE);
+ if (!pNestedType.GetMethodTable()->IsManagedSequential())
+ {
+ return TRUE;
+ }
+
+ pManagedPlacementInfo->m_size = (pNestedType.GetMethodTable()->GetNumInstanceFieldBytes());
+
+ _ASSERTE(pNestedType.GetMethodTable()->HasLayout()); // If it is ManagedSequential(), it also has Layout but doesn't hurt to check before we do a cast!
+ pManagedPlacementInfo->m_alignment = pNestedType.GetMethodTable()->GetLayoutInfo()->m_ManagedLargestAlignmentRequirementOfAllMembers;
+
+ return FALSE;
+ }
+ // No other type permitted for ManagedSequential.
+ return TRUE;
+ }
+}
+
//=====================================================================
// ParseNativeFieldTypes:
// Figure out the native field type of each field based on both the CLR
}
#endif
+
+ MetaSig fsig(pCOMSignature, cbCOMSignature, pModule, pTypeContext, MetaSig::sigField);
+ CorElementType corElemType = fsig.NextArgNormalized();
+ if (!(*fDisqualifyFromManagedSequential))
+ {
+ *fDisqualifyFromManagedSequential = IsDisqualifiedFromManagedSequential(corElemType, fsig, &pFieldInfoArrayOut->m_managedPlacement);
+ }
+
ParseNativeType(pModule,
- pCOMSignature,
- cbCOMSignature,
+ fsig.GetArgProps(),
+ fd,
nativeTypeFlags,
- pFieldInfoArrayOut,
- pNativeType,
- cbNativeType,
- cl,
- pTypeContext,
- fDisqualifyFromManagedSequential
+ &pFieldInfoArrayOut->m_nfd,
+ pTypeContext
#ifdef _DEBUG
,
szNamespace,
#endif
);
- if (!IsFieldBlittable((FieldMarshaler*)(&pFieldInfoArrayOut->m_FieldMarshaler)))
+ if (!pFieldInfoArrayOut->m_nfd.IsBlittable())
pEEClassLayoutInfoOut->SetIsBlittable(FALSE);
(*cInstanceFields)++;
class EEClass;
class EnCFieldDesc;
class FieldDesc;
-class FieldMarshaler;
+class NativeFieldDescriptor;
struct LayoutRawFieldInfo;
class MetaSig;
class MethodDesc;
enum class ParseNativeTypeFlags : int;
typedef DPTR(DictionaryLayout) PTR_DictionaryLayout;
-typedef DPTR(FieldMarshaler) PTR_FieldMarshaler;
+typedef DPTR(NativeFieldDescriptor) PTR_NativeFieldDescriptor;
//---------------------------------------------------------------------------------
// # of fields that are of the calltime-marshal variety.
UINT m_numCTMFields;
- // An array of FieldMarshaler data blocks, used to drive call-time
+ // An array of NativeFieldDescriptor data blocks, used to drive call-time
// marshaling of NStruct reference parameters. The number of elements
// equals m_numCTMFields.
- RelativePointer<PTR_FieldMarshaler> m_pFieldMarshalers;
+ RelativePointer<PTR_NativeFieldDescriptor> m_pNativeFieldDescriptors;
public:
return m_numCTMFields;
}
- PTR_FieldMarshaler GetFieldMarshalers() const
+ PTR_NativeFieldDescriptor GetNativeFieldDescriptors() const
{
LIMITED_METHOD_CONTRACT;
- return ReadPointerMaybeNull(this, &EEClassLayoutInfo::m_pFieldMarshalers);
+ return ReadPointerMaybeNull(this, &EEClassLayoutInfo::m_pNativeFieldDescriptors);
}
#ifndef DACCESS_COMPILE
- void SetFieldMarshalers(FieldMarshaler *pFieldMarshallers)
+ void SetNativeFieldDescriptors(NativeFieldDescriptor *pNativeFieldDescriptors)
{
LIMITED_METHOD_CONTRACT;
- m_pFieldMarshalers.SetValueMaybeNull(pFieldMarshallers);
+ m_pNativeFieldDescriptors.SetValueMaybeNull(pNativeFieldDescriptors);
}
#endif // DACCESS_COMPILE
#include "jitinterface.h"
#include "eeconfig.h"
#include "log.h"
-#include "fieldmarshaler.h"
#include "cgensys.h"
#include "gcheaputilities.h"
#include "dbginterface.h"
#include "eeconfig.h"
#include "contractimpl.h"
#include "prettyprintsig.h"
+#include "compile.h"
#include "comcallablewrapper.h"
#include "clrtocomcall.h"
class LayoutEEClass;
class EnCFieldDesc;
class FieldDesc;
-class FieldMarshaler;
struct LayoutRawFieldInfo;
class MetaSig;
class MethodDesc;
MarshalInfo Info(msig.GetModule(), msig.GetArgProps(), msig.GetSigTypeContext(), params[iParam],
MarshalInfo::MARSHAL_SCENARIO_COMINTEROP, (CorNativeLinkType)0, (CorNativeLinkFlags)0,
- TRUE, iParam, numArgs, BestFit, ThrowOnUnmappableChar, FALSE, TRUE, pMD, TRUE
+ TRUE, iParam, numArgs, BestFit, ThrowOnUnmappableChar, FALSE, TRUE, pMD, TRUE, FALSE
#ifdef _DEBUG
, pMD->m_pszDebugMethodName, pMD->m_pszDebugClassName, iParam
#endif
MarshalInfo info(fsig.GetModule(), fsig.GetArgProps(), fsig.GetSigTypeContext(), pFD->GetMemberDef(), MarshalInfo::MARSHAL_SCENARIO_COMINTEROP,
(CorNativeLinkType)0, (CorNativeLinkFlags)0,
- FALSE, 0, fsig.NumFixedArgs(), BestFit, ThrowOnUnmappableChar, FALSE, TRUE, NULL, FALSE
+ FALSE, 0, fsig.NumFixedArgs(), BestFit, ThrowOnUnmappableChar, FALSE, TRUE, NULL, FALSE, FALSE
#ifdef _DEBUG
, szDebugName, szDebugClassName, 0
#endif
MarshalInfo info(msig.GetModule(), msig.GetArgProps(), msig.GetSigTypeContext(), params[iArg],
WinRTType ? MarshalInfo::MARSHAL_SCENARIO_WINRT : MarshalInfo::MARSHAL_SCENARIO_COMINTEROP,
(CorNativeLinkType)0, (CorNativeLinkFlags)0,
- TRUE, iArg, numArgs, BestFit, ThrowOnUnmappableChar, FALSE, TRUE, pMD, FALSE
+ TRUE, iArg, numArgs, BestFit, ThrowOnUnmappableChar, FALSE, TRUE, pMD, FALSE, FALSE
#ifdef _DEBUG
, szDebugName, szDebugClassName, iArg
#endif
MarshalInfo info(msig.GetModule(), msig.GetReturnProps(), msig.GetSigTypeContext(), params[0],
WinRTType ? MarshalInfo::MARSHAL_SCENARIO_WINRT : MarshalInfo::MARSHAL_SCENARIO_COMINTEROP,
(CorNativeLinkType)0, (CorNativeLinkFlags)0,
- FALSE, 0, numArgs, BestFit, ThrowOnUnmappableChar, FALSE, TRUE, pMD, FALSE
+ FALSE, 0, numArgs, BestFit, ThrowOnUnmappableChar, FALSE, TRUE, pMD, FALSE, FALSE
#ifdef _DEBUG
,szDebugName, szDebugClassName, 0
#endif
#include "dispparammarshaler.h"
#include "reflectioninvocation.h"
#include "dbginterface.h"
+#include "dllimport.h"
#define EXCEPTION_INNER_PROP "InnerException"
}
else if (MscorlibBinder::IsClass(pMemberInfoMT, CLASS__FIELD))
{
- MethodDescCallSite getFieldHandle(METHOD__RTFIELD__GET_FIELDHANDLE, &MemberInfoObj);
- ARG_SLOT arg = ObjToArgSlot(MemberInfoObj);
- FieldDesc* pFld = (FieldDesc*) getFieldHandle.Call_RetLPVOID(&arg);
- if (pFld)
- SetUpFieldMarshalerInfo(pFld);
+ // We don't support non-default marshalling behavior for field getter/setter stubs invoked via IDispatch.
}
else if (MscorlibBinder::IsClass(pMemberInfoMT, CLASS__PROPERTY))
{
MarshalInfo Info(msig.GetModule(), msig.GetArgProps(), msig.GetSigTypeContext(), paramDef, MarshalInfo::MARSHAL_SCENARIO_COMINTEROP,
(CorNativeLinkType)0, (CorNativeLinkFlags)0,
- TRUE, iParam, numArgs, BestFit, ThrowOnUnmappableChar, FALSE, TRUE, pMD, TRUE
+ TRUE, iParam, numArgs, BestFit, ThrowOnUnmappableChar, FALSE, TRUE, pMD, TRUE, FALSE
#ifdef _DEBUG
, pMD->m_pszDebugMethodName, pMD->m_pszDebugClassName, iParam
#endif
{
MarshalInfo Info(msig.GetModule(), msig.GetReturnProps(), msig.GetSigTypeContext(), returnParamDef, MarshalInfo::MARSHAL_SCENARIO_COMINTEROP,
(CorNativeLinkType)0, (CorNativeLinkFlags)0,
- FALSE, 0, numArgs, BestFit, ThrowOnUnmappableChar, FALSE, TRUE, pMD, TRUE
+ FALSE, 0, numArgs, BestFit, ThrowOnUnmappableChar, FALSE, TRUE, pMD, TRUE, FALSE
#ifdef _DEBUG
, pMD->m_pszDebugMethodName, pMD->m_pszDebugClassName, 0
#endif
}
}
-void DispatchMemberInfo::SetUpFieldMarshalerInfo(FieldDesc *pField)
-{
- // @TODO(DM): Implement this.
- LIMITED_METHOD_CONTRACT;
-}
-
void DispatchMemberInfo::SetUpDispParamMarshalerForMarshalInfo(int iParam, MarshalInfo *pInfo)
{
CONTRACTL
VARTYPE ElementVt = V_VT(pRefVar) & ~(VT_BYREF | VT_ARRAY);
MethodTable *pElementMT = (*(BASEARRAYREF *)pSrcObj)->GetArrayElementTypeHandle().GetMethodTable();
+ PCODE pStructMarshalStubAddress = NULL;
+ GCPROTECT_BEGIN(*pSrcObj);
+ if (ElementVt == VT_RECORD && pElementMT->IsBlittable())
+ {
+ GCX_PREEMP();
+ pStructMarshalStubAddress = NDirect::GetEntryPointForStructMarshalStub(pElementMT);
+ }
+ GCPROTECT_END();
+
// Convert the contents of the managed array into the original SAFEARRAY.
- OleVariant::MarshalSafeArrayForArrayRef((BASEARRAYREF *)pSrcObj, *V_ARRAYREF(pRefVar), ElementVt, pElementMT);
+ OleVariant::MarshalSafeArrayForArrayRef((BASEARRAYREF *)pSrcObj, *V_ARRAYREF(pRefVar), ElementVt, pElementMT, pStructMarshalStubAddress);
}
else
{
void DetermineCultureAwareness();
void SetUpParamMarshalerInfo();
void SetUpMethodMarshalerInfo(MethodDesc *pMeth, BOOL bReturnValueOnly);
- void SetUpFieldMarshalerInfo(FieldDesc *pField);
void SetUpDispParamMarshalerForMarshalInfo(int iParam, MarshalInfo *pInfo);
void SetUpDispParamAttributes(int iParam, MarshalInfo* Info);
public:
GC_TRIGGERS;
MODE_COOPERATIVE;
PRECONDITION(CheckPointer(pSrcVar));
+ PRECONDITION(CheckPointer(pDestObj) && *pDestObj == NULL);
}
CONTRACTL_END;
// Retrieve the SAFEARRAY pointer.
SAFEARRAY *pSafeArray = V_VT(pSrcVar) & VT_BYREF ? *V_ARRAYREF(pSrcVar) : V_ARRAY(pSrcVar);
- if (pSafeArray)
+ if (!pSafeArray)
{
- // Retrieve the variant type if it is not specified for the parameter.
- if (vt == VT_EMPTY)
- vt = V_VT(pSrcVar) & ~VT_ARRAY | VT_BYREF;
+ return;
+ }
- if (!pElemMT && vt == VT_RECORD)
- pElemMT = OleVariant::GetElementTypeForRecordSafeArray(pSafeArray).GetMethodTable();
+ // Retrieve the variant type if it is not specified for the parameter.
+ if (vt == VT_EMPTY)
+ vt = V_VT(pSrcVar) & ~VT_ARRAY | VT_BYREF;
- // Create an array from the SAFEARRAY.
- *(BASEARRAYREF*)pDestObj = OleVariant::CreateArrayRefForSafeArray(pSafeArray, vt, pElemMT);
+ if (!pElemMT && vt == VT_RECORD)
+ pElemMT = OleVariant::GetElementTypeForRecordSafeArray(pSafeArray).GetMethodTable();
- // Convert the contents of the SAFEARRAY.
- OleVariant::MarshalArrayRefForSafeArray(pSafeArray, (BASEARRAYREF*)pDestObj, vt, pElemMT);
- }
- else
+ PCODE pStructMarshalStubAddress = NULL;
+ if (vt == VT_RECORD && !pElemMT->IsBlittable())
{
- *pDestObj = NULL;
+ GCX_PREEMP();
+ pStructMarshalStubAddress = NDirect::GetEntryPointForStructMarshalStub(pElemMT);
}
+
+ // Create an array from the SAFEARRAY.
+ *(BASEARRAYREF*)pDestObj = OleVariant::CreateArrayRefForSafeArray(pSafeArray, vt, pElemMT);
+
+ // Convert the contents of the SAFEARRAY.
+ OleVariant::MarshalArrayRefForSafeArray(pSafeArray, (BASEARRAYREF*)pDestObj, vt, pStructMarshalStubAddress, pElemMT);
}
void DispParamArrayMarshaler::MarshalManagedToNative(OBJECTREF *pSrcObj, VARIANT *pDestVar)
TypeHandle tempHandle = OleVariant::GetArrayElementTypeWrapperAware((BASEARRAYREF*)pSrcObj);
pElemMT = tempHandle.GetMethodTable();
}
-
+
+ PCODE pStructMarshalStubAddress = NULL;
+ GCPROTECT_BEGIN(*pSrcObj);
+ if (vt == VT_RECORD && !pElemMT->IsBlittable())
+ {
+ GCX_PREEMP();
+ pStructMarshalStubAddress = NDirect::GetEntryPointForStructMarshalStub(pElemMT);
+ }
+ GCPROTECT_END();
+
// Allocate the safe array based on the source object and the destination VT.
pSafeArray = OleVariant::CreateSafeArrayForArrayRef((BASEARRAYREF*)pSrcObj, vt, pElemMT);
_ASSERTE(pSafeArray);
// Marshal the contents of the SAFEARRAY.
- OleVariant::MarshalSafeArrayForArrayRef((BASEARRAYREF*)pSrcObj, pSafeArray, vt, pElemMT);
+ OleVariant::MarshalSafeArrayForArrayRef((BASEARRAYREF*)pSrcObj, pSafeArray, vt, pElemMT, pStructMarshalStubAddress);
}
// Store the resulting SAFEARRAY in the destination VARIANT.
// Allocate an instance of the boxed value class and copy the contents
// of the record into it.
BoxedValueClass = m_pRecordMT->Allocate();
- FmtClassUpdateCLR(&BoxedValueClass, (BYTE*)pvRecord);
+
+ MethodDesc* pStructMarshalStub;
+ {
+ GCX_PREEMP();
+
+ pStructMarshalStub = NDirect::CreateStructMarshalILStub(m_pRecordMT);
+ }
+
+ MarshalStructViaILStub(pStructMarshalStub, BoxedValueClass->GetData(), pvRecord, StructMarshalStubs::MarshalOperation::Unmarshal);
}
*pDestObj = BoxedValueClass;
#include "customattribute.h"
#include "ilstubcache.h"
#include "typeparse.h"
+#include "typestring.h"
#include "sigbuilder.h"
#include "sigformat.h"
#include "strongnameholders.h"
#include "ecall.h"
+#include "fieldmarshaler.h"
#include <formattype.h>
#include "../md/compiler/custattr.h"
GC_NOTRIGGER;
SUPPORTS_DAC;
}
- CONTRACTL_END
+ CONTRACTL_END;
m_pMD = pMD;
+ m_pMT = nullptr;
if (pSigInfo != NULL)
{
m_sig = pSigInfo->GetSignature();
INDEBUG(InitDebugNames());
}
-StubSigDesc::StubSigDesc(MethodDesc *pMD, Signature sig, Module *pModule)
+StubSigDesc::StubSigDesc(MethodDesc* pMD, Signature sig, Module* pModule)
{
CONTRACTL
{
PRECONDITION(!sig.IsEmpty());
PRECONDITION(pModule != NULL);
}
- CONTRACTL_END
+ CONTRACTL_END;
- m_pMD = pMD;
- m_sig = sig;
- m_pModule = pModule;
+ m_pMD = pMD;
+ m_pMT = nullptr;
+ m_sig = sig;
+ m_pModule = pModule;
if (pMD != NULL)
{
INDEBUG(InitDebugNames());
}
+StubSigDesc::StubSigDesc(MethodTable* pMT, Signature sig, Module* pModule)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ SUPPORTS_DAC;
+ PRECONDITION(!sig.IsEmpty());
+ PRECONDITION(pModule != NULL);
+ }
+ CONTRACTL_END;
+
+ m_pMD = nullptr;
+ m_pMT = pMT;
+ m_sig = sig;
+ m_pModule = pModule;
+
+ m_tkMethodDef = mdMethodDefNil;
+
+ if (pMT != NULL)
+ {
+ SigTypeContext::InitTypeContext(pMT, &m_typeContext);
+ m_pLoaderModule = pMT->GetLoaderModule(); // Used for ILStubCache selection and MethodTable creation.
+ }
+ else
+ {
+ m_pLoaderModule = m_pModule;
+ }
+
+ INDEBUG(InitDebugNames());
+}
+
+StubSigDesc::StubSigDesc(std::nullptr_t, Signature sig, Module* pModule)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ SUPPORTS_DAC;
+ PRECONDITION(!sig.IsEmpty());
+ PRECONDITION(pModule != NULL);
+ }
+ CONTRACTL_END;
+
+ m_pMD = nullptr;
+ m_pMT = nullptr;
+ m_sig = sig;
+ m_pModule = pModule;
+ m_tkMethodDef = mdMethodDefNil;
+ m_pLoaderModule = m_pModule;
+
+ INDEBUG(InitDebugNames());
+}
+
#ifndef DACCESS_COMPILE
class StubState
virtual void MarshalReturn(MarshalInfo* pInfo, int argOffset) = 0;
virtual void MarshalArgument(MarshalInfo* pInfo, int argOffset, UINT nativeStackOffset) = 0;
virtual void MarshalLCID(int argIdx) = 0;
+ virtual void MarshalField(MarshalInfo* pInfo, UINT32 managedOffset, UINT32 nativeOffset, FieldDesc* pFieldDesc) = 0;
#ifdef FEATURE_COMINTEROP
virtual void MarshalHiddenLengthArgument(MarshalInfo *pInfo, BOOL isForReturnArray) = 0;
pInfo->GenerateArgumentIL(&m_slIL, argOffset, nativeStackOffset, SF_IsForwardStub(m_dwStubFlags));
}
+ void MarshalField(MarshalInfo* pInfo, UINT32 managedOffset, UINT32 nativeOffset, FieldDesc* pFieldDesc)
+ {
+ CONTRACTL
+ {
+ STANDARD_VM_CHECK;
+ PRECONDITION(CheckPointer(pInfo));
+ }
+ CONTRACTL_END;
+
+ pInfo->GenerateFieldIL(&m_slIL, managedOffset, nativeOffset, pFieldDesc);
+ }
+
#ifdef FEATURE_COMINTEROP
// Marshal the hidden length parameter for the managed parameter in pInfo
virtual void MarshalHiddenLengthArgument(MarshalInfo *pInfo, BOOL isForReturnArray)
m_slIL.DoNDirect(m_slIL.GetDispatchCodeStream(), m_dwStubFlags, pStubMD);
}
-#ifdef FEATURE_COMINTEROP
- void EmitExceptionHandler(LocalDesc* pNativeReturnType, LocalDesc* pManagedReturnType,
- ILCodeLabel** ppTryEndAndCatchBeginLabel, ILCodeLabel ** ppCatchEndAndReturnLabel)
+ virtual void EmitExceptionHandler(LocalDesc* pNativeReturnType, LocalDesc* pManagedReturnType,
+ ILCodeLabel** ppTryBeginLabel, ILCodeLabel** ppTryEndAndCatchBeginLabel, ILCodeLabel** ppCatchEndAndReturnLabel)
{
+#ifdef FEATURE_COMINTEROP
STANDARD_VM_CONTRACT;
ILCodeStream* pcsExceptionHandler = m_slIL.NewCodeStream(ILStubLinker::kExceptionHandler);
- *ppTryEndAndCatchBeginLabel = pcsExceptionHandler->NewCodeLabel();
- *ppCatchEndAndReturnLabel = pcsExceptionHandler->NewCodeLabel();
+ *ppTryEndAndCatchBeginLabel = pcsExceptionHandler->NewCodeLabel(); // try ends at the same place the catch begins
+ *ppCatchEndAndReturnLabel = pcsExceptionHandler->NewCodeLabel(); // catch ends at the same place we resume afterwards
pcsExceptionHandler->EmitLEAVE(*ppCatchEndAndReturnLabel);
pcsExceptionHandler->EmitLabel(*ppTryEndAndCatchBeginLabel);
pcsExceptionHandler->EmitLDLOC(retvalLocalNum);
}
pcsExceptionHandler->EmitRET();
- }
#endif // FEATURE_COMINTEROP
+ }
void FinishEmit(MethodDesc* pStubMD)
{
&& !SF_IsFieldGetterStub(m_dwStubFlags)
&& !SF_IsFieldSetterStub(m_dwStubFlags);
+ bool hasTryCatchExceptionHandler = hasTryCatchForHRESULT || SF_IsStructMarshalStub(m_dwStubFlags);
+
#ifdef FEATURE_COMINTEROP
if (hasTryCatchForHRESULT)
{
DWORD dwMethodDescLocalNum = (DWORD)-1;
// Notify the profiler of call out of the runtime
- if (!SF_IsReverseCOMStub(m_dwStubFlags) && (CORProfilerTrackTransitions() || (!IsReadyToRunCompilation() && SF_IsNGENedStubForProfiling(m_dwStubFlags))))
+ if (!SF_IsReverseCOMStub(m_dwStubFlags) && !SF_IsStructMarshalStub(m_dwStubFlags) && (CORProfilerTrackTransitions() || (!IsReadyToRunCompilation() && SF_IsNGENedStubForProfiling(m_dwStubFlags))))
{
dwMethodDescLocalNum = m_slIL.EmitProfilerBeginTransitionCallback(pcsDispatch, m_dwStubFlags);
_ASSERTE(dwMethodDescLocalNum != (DWORD)-1);
{
// Field access stubs are not shared and do not use the secret parameter.
}
+ else if (SF_IsStructMarshalStub(m_dwStubFlags))
+ {
+ // Struct marshal stubs don't actually call anything so they do not need the secrect parameter.
+ }
#ifndef BIT64
else if (SF_IsForwardDelegateStub(m_dwStubFlags) ||
(SF_IsForwardCOMStub(m_dwStubFlags) && SF_IsWinRTDelegateStub(m_dwStubFlags)))
SwapStubSignatures(pStubMD);
}
- ILCodeLabel* pTryEndAndCatchBeginLabel = NULL; // try ends at the same place the catch begins
- ILCodeLabel* pCatchEndAndReturnLabel = NULL; // catch ends at the same place we resume afterwards
-#ifdef FEATURE_COMINTEROP
- if (hasTryCatchForHRESULT)
+ ILCodeLabel* pTryBeginLabel = nullptr;
+ ILCodeLabel* pTryEndAndCatchBeginLabel = nullptr;
+ ILCodeLabel* pCatchEndLabel = nullptr;
+ if (hasTryCatchExceptionHandler)
{
- EmitExceptionHandler(&nativeReturnType, &managedReturnType, &pTryEndAndCatchBeginLabel, &pCatchEndAndReturnLabel);
+ EmitExceptionHandler(&nativeReturnType, &managedReturnType, &pTryBeginLabel, &pTryEndAndCatchBeginLabel, &pCatchEndLabel);
}
-#endif // FEATURE_COMINTEROP
UINT maxStack;
size_t cbCode;
pbLocalSig = (BYTE *)pILHeader->LocalVarSig;
_ASSERTE(cbSig == pILHeader->cbLocalVarSig);
- ILStubEHClause cleanupTryFinally = { 0 };
- ILStubEHClause convertToHRTryCatch = { 0 };
+ ILStubEHClause cleanupTryFinally{};
m_slIL.GetCleanupFinallyOffsets(&cleanupTryFinally);
-#ifdef FEATURE_COMINTEROP
- if (hasTryCatchForHRESULT)
+ ILStubEHClause tryCatchClause{};
+ if (hasTryCatchExceptionHandler)
{
- convertToHRTryCatch.kind = ILStubEHClause::kTypedCatch;
- convertToHRTryCatch.dwTryBeginOffset = 0;
- convertToHRTryCatch.dwHandlerBeginOffset = ((DWORD)pTryEndAndCatchBeginLabel->GetCodeOffset());
- convertToHRTryCatch.cbTryLength = convertToHRTryCatch.dwHandlerBeginOffset - convertToHRTryCatch.dwTryBeginOffset;
- convertToHRTryCatch.cbHandlerLength = ((DWORD)pCatchEndAndReturnLabel->GetCodeOffset()) - convertToHRTryCatch.dwHandlerBeginOffset;
- convertToHRTryCatch.dwTypeToken = pcsDispatch->GetToken(g_pObjectClass);
+ tryCatchClause.kind = ILStubEHClause::kTypedCatch;
+ tryCatchClause.dwTryBeginOffset = pTryBeginLabel != nullptr ? (DWORD)pTryBeginLabel->GetCodeOffset() : 0;
+ tryCatchClause.dwHandlerBeginOffset = ((DWORD)pTryEndAndCatchBeginLabel->GetCodeOffset());
+ tryCatchClause.cbTryLength = tryCatchClause.dwHandlerBeginOffset - tryCatchClause.dwTryBeginOffset;
+ tryCatchClause.cbHandlerLength = ((DWORD)pCatchEndLabel->GetCodeOffset()) - tryCatchClause.dwHandlerBeginOffset;
+ tryCatchClause.dwTypeToken = pcsMarshal->GetToken(g_pObjectClass);
}
-#endif // FEATURE_COMINTEROP
int nEHClauses = 0;
- if (convertToHRTryCatch.cbHandlerLength != 0)
+ if (tryCatchClause.cbHandlerLength != 0)
nEHClauses++;
if (cleanupTryFinally.cbHandlerLength != 0)
if (nEHClauses > 0)
{
COR_ILMETHOD_SECT_EH* pEHSect = pResolver->AllocEHSect(nEHClauses);
- PopulateEHSect(pEHSect, nEHClauses, &cleanupTryFinally, &convertToHRTryCatch);
+ PopulateEHSect(pEHSect, nEHClauses, &cleanupTryFinally, &tryCatchClause);
}
m_slIL.GenerateCode(pbBuffer, cbCode);
cleanupTryFinally.dwTryBeginOffset, cleanupTryFinally.dwTryBeginOffset + cleanupTryFinally.cbTryLength,
cleanupTryFinally.dwHandlerBeginOffset, cleanupTryFinally.dwHandlerBeginOffset + cleanupTryFinally.cbHandlerLength));
}
- if (convertToHRTryCatch.cbHandlerLength != 0)
+ if (tryCatchClause.cbHandlerLength != 0)
{
LOG((LF_STUBS, LL_INFO1000, "try_begin: 0x%04x try_end: 0x%04x catch_begin: 0x%04x catch_end: 0x%04x type_token: 0x%08x\n",
- convertToHRTryCatch.dwTryBeginOffset, convertToHRTryCatch.dwTryBeginOffset + convertToHRTryCatch.cbTryLength,
- convertToHRTryCatch.dwHandlerBeginOffset, convertToHRTryCatch.dwHandlerBeginOffset + convertToHRTryCatch.cbHandlerLength,
- convertToHRTryCatch.dwTypeToken));
+ tryCatchClause.dwTryBeginOffset, tryCatchClause.dwTryBeginOffset + tryCatchClause.cbTryLength,
+ tryCatchClause.dwHandlerBeginOffset, tryCatchClause.dwHandlerBeginOffset + tryCatchClause.cbHandlerLength,
+ tryCatchClause.dwTypeToken));
}
LogILStubFlags(LF_STUBS, LL_INFO1000, m_dwStubFlags);
pbLocalSig,
cbSig,
jitFlags,
- &convertToHRTryCatch,
+ &tryCatchClause,
&cleanupTryFinally,
maxStack,
(DWORD)cbCode
dwFlags |= ETW_IL_STUB_FLAGS_VARARG;
if (m_dwStubFlags & NDIRECTSTUB_FL_UNMANAGED_CALLI)
dwFlags |= ETW_IL_STUB_FLAGS_UNMANAGED_CALLI;
+ if (m_dwStubFlags & NDIRECTSTUB_FL_STRUCT_MARSHAL)
+ dwFlags |= ETW_IL_STUB_FLAGS_STRUCT_MARSHAL;
DWORD dwToken = 0;
if (pTargetMD)
LogOneFlag(dwStubFlags, NDIRECTSTUB_FL_DELEGATE, " NDIRECTSTUB_FL_DELEGATE\n", facility, level);
LogOneFlag(dwStubFlags, NDIRECTSTUB_FL_DOHRESULTSWAPPING, " NDIRECTSTUB_FL_DOHRESULTSWAPPING\n", facility, level);
LogOneFlag(dwStubFlags, NDIRECTSTUB_FL_REVERSE_INTEROP, " NDIRECTSTUB_FL_REVERSE_INTEROP\n", facility, level);
+ LogOneFlag(dwStubFlags, NDIRECTSTUB_FL_STRUCT_MARSHAL, " NDIRECTSTUB_FL_STRUCT_MARSHAL\n", facility, level);
#ifdef FEATURE_COMINTEROP
LogOneFlag(dwStubFlags, NDIRECTSTUB_FL_COM, " NDIRECTSTUB_FL_COM\n", facility, level);
#endif // FEATURE_COMINTEROP
NDIRECTSTUB_FL_NGENEDSTUBFORPROFILING |
NDIRECTSTUB_FL_GENERATEDEBUGGABLEIL |
NDIRECTSTUB_FL_UNMANAGED_CALLI |
+ NDIRECTSTUB_FL_STRUCT_MARSHAL |
NDIRECTSTUB_FL_TRIGGERCCTOR |
#ifdef FEATURE_COMINTEROP
NDIRECTSTUB_FL_COM |
DWORD m_dwStubFlags;
};
+class StructMarshal_ILStubState : public ILStubState
+{
+public:
+
+ StructMarshal_ILStubState(MethodTable* pMT, const Signature& signature, SigTypeContext* pTypeContext, DWORD dwStubFlags)
+ : ILStubState(
+ pMT->GetModule(),
+ signature,
+ pTypeContext,
+ FALSE,
+ FALSE,
+ dwStubFlags,
+ -1 /* We have no LCID parameter */,
+ nullptr),
+ m_nativeSize(pMT->GetNativeSize())
+ {
+ LIMITED_METHOD_CONTRACT;
+
+ }
+
+ void BeginEmit(DWORD dwStubFlags)
+ {
+ STANDARD_VM_CONTRACT;
+
+ ILStubState::BeginEmit(dwStubFlags);
+
+ ILCodeStream* pcsSetup = m_slIL.GetSetupCodeStream();
+ ILCodeStream* pcsMarshal = m_slIL.GetMarshalCodeStream();
+ ILCodeStream* pcsUnmarshal = m_slIL.GetUnmarshalCodeStream();
+ ILCodeStream* pcsCleanup = m_slIL.GetCleanupCodeStream();
+
+ pMarshalStartLabel = pcsSetup->NewCodeLabel();
+ pCatchTrampolineStartLabel = pcsSetup->NewCodeLabel();
+ pCatchTrampolineEndLabel = pcsSetup->NewCodeLabel();
+ pUnmarshalStartLabel = pcsSetup->NewCodeLabel();
+ pCleanupStartLabel = pcsSetup->NewCodeLabel();
+ pReturnLabel = pcsSetup->NewCodeLabel();
+
+ dwExceptionDispatchInfoLocal = pcsSetup->NewLocal(MscorlibBinder::GetClass(CLASS__EXCEPTION_DISPATCH_INFO));
+ pcsSetup->EmitLDNULL();
+ pcsSetup->EmitSTLOC(dwExceptionDispatchInfoLocal);
+
+ pcsMarshal->EmitLabel(pMarshalStartLabel);
+ pcsUnmarshal->EmitLabel(pUnmarshalStartLabel);
+ pcsCleanup->EmitLabel(pCleanupStartLabel);
+
+ // Initialize the native structure's memory so we can do a partial cleanup
+ // if marshalling fails.
+ pcsMarshal->EmitLDARG(StructMarshalStubs::NATIVE_STRUCT_ARGIDX);
+ pcsMarshal->EmitLDC(0);
+ pcsMarshal->EmitLDC(m_nativeSize);
+ pcsMarshal->EmitINITBLK();
+ }
+
+ void FinishEmit(MethodDesc* pStubMD)
+ {
+ STANDARD_VM_CONTRACT;
+
+ ILCodeStream* pcsSetup = m_slIL.GetSetupCodeStream();
+ ILCodeStream* pcsMarshal = m_slIL.GetMarshalCodeStream();
+ ILCodeStream* pcsUnmarshal = m_slIL.GetUnmarshalCodeStream();
+ ILCodeStream* pcsDispatch = m_slIL.GetDispatchCodeStream();
+ ILCodeStream* pcsCleanup = m_slIL.GetCleanupCodeStream();
+
+ pcsSetup->EmitNOP("// marshal operation jump table {");
+ pcsSetup->EmitLDARG(StructMarshalStubs::OPERATION_ARGIDX);
+ pcsSetup->EmitLDC(StructMarshalStubs::MarshalOperation::Marshal);
+ pcsSetup->EmitBEQ(pMarshalStartLabel);
+ pcsSetup->EmitLDARG(StructMarshalStubs::OPERATION_ARGIDX);
+ pcsSetup->EmitLDC(StructMarshalStubs::MarshalOperation::Unmarshal);
+ pcsSetup->EmitBEQ(pUnmarshalStartLabel);
+ pcsSetup->EmitLDARG(StructMarshalStubs::OPERATION_ARGIDX);
+ pcsSetup->EmitLDC(StructMarshalStubs::MarshalOperation::Cleanup);
+ pcsSetup->EmitBEQ(pCleanupStartLabel);
+ pcsSetup->EmitNOP("// } marshal operation jump table");
+
+ // Clear native memory after release so we don't leave anything dangling.
+ pcsCleanup->EmitLDARG(StructMarshalStubs::NATIVE_STRUCT_ARGIDX);
+ pcsCleanup->EmitLDC(0);
+ pcsCleanup->EmitLDC(m_nativeSize);
+ pcsCleanup->EmitINITBLK();
+
+ pcsMarshal->EmitLEAVE(pReturnLabel);
+ pcsMarshal->EmitLabel(pCatchTrampolineStartLabel);
+ // WARNING: The ILStubLinker has no knowledge that the exception object is on the stack
+ // (because it is
+ // unaware that we've just entered a catch block), so we lie about the number of arguments
+ // (say the method takes one less) to rebalance the stack.
+ pcsMarshal->EmitCALL(METHOD__EXCEPTION_DISPATCH_INFO__CAPTURE, 0, 1);
+ pcsMarshal->EmitSTLOC(dwExceptionDispatchInfoLocal);
+ pcsMarshal->EmitLEAVE(pCleanupStartLabel);
+ pcsMarshal->EmitLabel(pCatchTrampolineEndLabel);
+
+ pcsDispatch->EmitLabel(pReturnLabel);
+ pcsDispatch->EmitRET();
+
+ pcsUnmarshal->EmitRET();
+
+ pcsCleanup->EmitLDLOC(dwExceptionDispatchInfoLocal);
+ pcsCleanup->EmitBRFALSE(pReturnLabel);
+ pcsCleanup->EmitLDLOC(dwExceptionDispatchInfoLocal);
+ pcsCleanup->EmitCALL(METHOD__EXCEPTION_DISPATCH_INFO__THROW, 0, 0);
+ pcsCleanup->EmitRET();
+
+ ILStubState::FinishEmit(pStubMD);
+ }
+
+ virtual void EmitExceptionHandler(LocalDesc* pNativeReturnType, LocalDesc* pManagedReturnType,
+ ILCodeLabel** ppTryBeginLabel, ILCodeLabel** ppTryEndCatchBeginLabel, ILCodeLabel** ppCatchEndLabel)
+ {
+ *ppTryBeginLabel = pMarshalStartLabel;
+ *ppTryEndCatchBeginLabel = pCatchTrampolineStartLabel;
+ *ppCatchEndLabel = pCatchTrampolineEndLabel;
+ }
+
+private:
+ ILCodeLabel* pMarshalStartLabel = nullptr;
+ ILCodeLabel* pCatchTrampolineStartLabel = nullptr;
+ ILCodeLabel* pCatchTrampolineEndLabel = nullptr;
+ ILCodeLabel* pUnmarshalStartLabel = nullptr;
+ ILCodeLabel* pCleanupStartLabel = nullptr;
+ ILCodeLabel* pReturnLabel = nullptr;
+ DWORD dwExceptionDispatchInfoLocal;
+
+ UINT32 m_nativeSize;
+};
class PInvoke_ILStubState : public ILStubState
{
{
STANDARD_VM_CONTRACT;
- NeedsCleanupList();
- pcsEmit->EmitLDLOCA(GetCleanupWorkListLocalNum());
+ if (SF_IsStructMarshalStub(m_dwStubFlags))
+ {
+ pcsEmit->EmitLDARG(StructMarshalStubs::CLEANUP_WORK_LIST_ARGIDX);
+ }
+ else
+ {
+ NeedsCleanupList();
+ pcsEmit->EmitLDLOCA(GetCleanupWorkListLocalNum());
+ }
}
//
// Create a local for the return value and store the return value in it.
//
- if (IsCleanupNeeded() || hasTryCatchForHRESULT)
+ if ((IsCleanupNeeded() || hasTryCatchForHRESULT) && !SF_IsStructMarshalStub(dwStubFlags))
{
// Save the return value if necessary, since the IL stack will be emptied when we leave a try block.
LocalDesc locDescRetVal;
//
// Emit end-of-try and end-of-finally code for the try/finally
//
- if (IsCleanupNeeded())
+ if (IsCleanupNeeded() && !SF_IsStructMarshalStub(dwStubFlags))
{
m_pCleanupFinallyEndLabel = NewCodeLabel();
m_pCleanupTryEndLabel = NewCodeLabel();
}
// Reload the return value
- if ((m_dwRetValLocalNum != (DWORD)-1) && !hasTryCatchForHRESULT)
+ if ((m_dwRetValLocalNum != (DWORD)-1) && !hasTryCatchForHRESULT && !SF_IsStructMarshalStub(dwStubFlags))
{
pcs->EmitLDLOC(m_dwRetValLocalNum);
}
void NDirectStubLinker::DoNDirect(ILCodeStream *pcsEmit, DWORD dwStubFlags, MethodDesc * pStubMD)
{
STANDARD_VM_CONTRACT;
+
+ if (SF_IsStructMarshalStub(dwStubFlags))
+ {
+ // Struct marshal stubs do not call anything, so this is a no-op
+ return;
+ }
+
if (SF_IsForwardStub(dwStubFlags)) // managed-to-native
{
LIMITED_METHOD_CONTRACT;
}
+ void MarshalField(MarshalInfo* pInfo, UINT32 managedOffset, UINT32 nativeOffset, FieldDesc* pFieldDesc)
+ {
+ LIMITED_METHOD_CONTRACT;
+ UNREACHABLE();
+ }
+
#ifdef FEATURE_COMINTEROP
void MarshalHiddenLengthArgument(MarshalInfo *, BOOL)
{
TRUE,
isInstanceMethod,
pMD,
- TRUE
+ TRUE,
+ FALSE
DEBUG_ARG(pDebugName)
DEBUG_ARG(pDebugClassName)
DEBUG_ARG(0)
CONSISTENCY_CHECK_MSGF(false, ("BreakOnInteropStubSetup: '%s' ", pSigDesc->m_pDebugName));
#endif // _DEBUG
- Stub* pstub = NULL;
-
if (SF_IsCOMStub(dwStubFlags))
{
_ASSERTE(0 == nlType);
TRUE,
isInstanceMethod ? TRUE : FALSE,
pMD,
- TRUE
+ TRUE,
+ FALSE
DEBUG_ARG(pSigDesc->m_pDebugName)
DEBUG_ARG(pSigDesc->m_pDebugClassName)
DEBUG_ARG(i + 1));
pss->FinishEmit(pMD);
}
+static CorNativeLinkType GetLinkTypeOfMethodTable(MethodTable* pMT)
+{
+ CorNativeLinkType nltType;
+
+ IMDInternalImport* pInternalImport = pMT->GetModule()->GetMDImport();
+
+ DWORD clFlags;
+ if (FAILED(pInternalImport->GetTypeDefProps(pMT->GetTypeDefRid(), &clFlags, NULL)))
+ {
+ UNREACHABLE_MSG("Structs that are generating interop marshalling stubs have already been verified to have valid metadata");
+ }
+
+ if (IsTdAnsiClass(clFlags))
+ {
+ nltType = nltAnsi;
+ }
+ else if (IsTdUnicodeClass(clFlags))
+ {
+ nltType = nltUnicode;
+ }
+ else if (IsTdAutoClass(clFlags))
+ {
+#ifdef PLATFORM_WINDOWS
+ nltType = nltUnicode;
+#else
+ nltType = nltAnsi; // We don't have a utf8 charset in metadata yet, but ANSI == UTF-8 off-Windows
+#endif
+ }
+ else
+ {
+ UNREACHABLE_MSG("Structs that are generating interop marshalling stubs have already been verified to have valid metadata");
+ }
+
+ return nltType;
+}
+
+static void CreateStructStub(ILStubState* pss,
+ StubSigDesc* pSigDesc,
+ MethodTable* pMT,
+ DWORD dwStubFlags,
+ MethodDesc* pMD)
+{
+ CONTRACTL
+ {
+ STANDARD_VM_CHECK;
+ PRECONDITION(CheckPointer(pss));
+ PRECONDITION(CheckPointer(pSigDesc));
+ PRECONDITION(CheckPointer(pMD, NULL_OK));
+ PRECONDITION(!pMD || pMD->IsILStub());
+ PRECONDITION(SF_IsStructMarshalStub(dwStubFlags));
+ }
+ CONTRACTL_END;
+
+ SF_ConsistencyCheck(dwStubFlags);
+
+#ifdef _DEBUG
+ if (g_pConfig->ShouldBreakOnInteropStubSetup(pSigDesc->m_pDebugName))
+ CONSISTENCY_CHECK_MSGF(false, ("BreakOnInteropStubSetup: '%s' ", pSigDesc->m_pDebugName));
+#endif // _DEBUG
+
+ Module* pModule = pSigDesc->m_pModule;
+
+
+ pss->SetLastError(false);
+
+ pss->BeginEmit(dwStubFlags);
+
+ // Marshal the fields
+ MarshalInfo::MarshalScenario ms = MarshalInfo::MARSHAL_SCENARIO_FIELD;
+#ifdef FEATURE_COMINTEROP
+ if (pMT->IsProjectedFromWinRT())
+ {
+ ms = MarshalInfo::MARSHAL_SCENARIO_WINRT_FIELD;
+ }
+#endif // FEATURE_COMINTEROP
+
+ int numFields = pMT->GetNumInstanceFields();
+ // Build up marshaling information for each of the method's parameters
+ SIZE_T cbFieldMarshalInfo;
+ if (!ClrSafeInt<SIZE_T>::multiply(sizeof(MarshalInfo), numFields, cbFieldMarshalInfo))
+ {
+ COMPlusThrowHR(COR_E_OVERFLOW);
+ }
+
+ CorNativeLinkType nlType = GetLinkTypeOfMethodTable(pMT);
+ NativeFieldDescriptor* pFieldDescriptors = pMT->GetLayoutInfo()->GetNativeFieldDescriptors();
+
+ for (int i = 0; i < numFields; ++i)
+ {
+ NativeFieldDescriptor& nativeFieldDescriptor = pFieldDescriptors[i];
+
+ nativeFieldDescriptor.Restore();
+
+ FieldDesc* pFD = nativeFieldDescriptor.GetFieldDesc();
+ SigPointer fieldSig = pFD->GetSigPointer();
+ // The first byte in a field signature is always 0x6 per ECMA 335. Skip over this byte to get to the rest of the signature for the MarshalInfo constructor.
+ (void)fieldSig.GetByte(nullptr);
+ SigTypeContext context(pFD, TypeHandle(pMT));
+
+ MarshalInfo mlInfo(pFD->GetModule(),
+ fieldSig,
+ &context,
+ nativeFieldDescriptor.GetFieldDesc()->GetMemberDef(),
+ ms,
+ nlType,
+ nlfNone,
+ TRUE,
+ i + 1,
+ numFields,
+ SF_IsBestFit(dwStubFlags),
+ SF_IsThrowOnUnmappableChar(dwStubFlags),
+ TRUE,
+ FALSE,
+ pMD,
+ TRUE,
+ FALSE
+ DEBUG_ARG(pSigDesc->m_pDebugName)
+ DEBUG_ARG(pSigDesc->m_pDebugClassName)
+ DEBUG_ARG(-1 /* field */));
+
+ pss->MarshalField(&mlInfo, pFD->GetOffset(), nativeFieldDescriptor.GetExternalOffset(), pFD);
+ }
+
+ if (pMD->IsDynamicMethod())
+ {
+ DynamicMethodDesc* pDMD = pMD->AsDynamicMethodDesc();
+#ifdef FEATURE_COMINTEROP
+ pDMD->SetStubNeedsCOMStarted(ms == MarshalInfo::MARSHAL_SCENARIO_WINRT_FIELD);
+#endif
+ pDMD->SetNativeStackArgSize(4 * sizeof(SLOT)); // The native stack arg size is constant since the signature for struct stubs is constant.
+ }
+
+ // FinishEmit needs to know the native stack arg size so we call it after the number
+ // has been set in the stub MD (code:DynamicMethodDesc.SetNativeStackArgSize)
+ pss->FinishEmit(pMD);
+}
+
class NDirectStubHashBlob : public ILStubHashBlobBase
{
public:
Module* m_pModule;
+ MethodTable* m_pMT;
WORD m_unmgdCallConv;
BYTE m_nlType; // C_ASSERTS are in NDirect::CreateHashBlob
pBlob->m_pModule = pParams->m_pModule;
}
+ pBlob->m_pMT = pParams->m_pMT;
pBlob->m_cbSizeOfBlob = cbSizeOfBlob.Value();
pBlob->m_unmgdCallConv = static_cast<WORD>(pParams->m_unmgdCallConv);
pBlob->m_nlType = static_cast<BYTE>(pParams->m_nlType);
DWORD dwStubFlags, // NDirectStubFlags
int nParamTokens,
mdParamDef* pParamTokenArray,
- int iLCIDArg
+ int iLCIDArg,
+ bool* pGeneratedNewStub = nullptr
)
{
CONTRACT(MethodDesc*)
Module* pModule = pSigDesc->m_pModule;
Module* pLoaderModule = pSigDesc->m_pLoaderModule;
MethodDesc* pTargetMD = pSigDesc->m_pMD;
+ MethodTable* pTargetMT = pSigDesc->m_pMT;
//
// pTargetMD may be null in the case of calli pinvoke
// and vararg pinvoke.
dwStubFlags,
nParamTokens,
pParamTokenArray,
- iLCIDArg
+ iLCIDArg,
+ pSigDesc->m_pMT
);
// The following two ILStubCreatorHelperHolder are to recover the status when an
// We can release the holder for the first phase now
pCreateOrGetStubHolder.SuppressRelease();
+ // We have the entry lock we need to use, so we can release the global lock.
+ pILStubLock.Release();
+
{
// The holder will free the allocated MethodDesc and restore the ILStubCache
// if exception happen. The reason to get the holder again is to
if (!pEntryLock.DeadlockAwareAcquire())
{
- // the IL generation is not recursive!
+ // the IL generation is not recursive.
+ // However, we can encounter a recursive situation when attempting to
+ // marshal a struct containing a layout class containing another struct.
+ // Throw an exception here instead of asserting.
+ if (SF_IsStructMarshalStub(dwStubFlags))
+ {
+ _ASSERTE(pSigDesc->m_pMT != nullptr);
+ StackSString strTypeName;
+ TypeString::AppendType(strTypeName, TypeHandle(pSigDesc->m_pMT));
+ COMPlusThrow(kTypeLoadException, IDS_CANNOT_MARSHAL_RECURSIVE_DEF, strTypeName.GetUnicode());
+ }
UNREACHABLE_MSG("unexpected deadlock in IL stub generation!");
}
if (SF_IsSharedStub(params.m_dwStubFlags))
{
+ // We need to re-acquire the lock in case we need to get a new pStubMD
+ // in the case that the owner of the shared stub was destroyed.
+ pILStubLock.Acquire();
+
// Assure that pStubMD we have now has not been destroyed by other threads
pGenILHolder->GetStubMethodDesc();
pEntry.Assign(ListLockEntry::Find(pILStubLock, pStubMD, "il stub gen lock"));
pEntryLock.Assign(pEntry, FALSE);
+ // We have the entry lock we need to use, so we can release the global lock.
+ pILStubLock.Release();
+
if (!pEntryLock.DeadlockAwareAcquire())
{
- // the IL generation is not recursive!
+ // the IL generation is not recursive.
+ // However, we can encounter a recursive situation when attempting to
+ // marshal a struct containing a layout class containing another struct.
+ // Throw an exception here instead of asserting.
+ if (SF_IsStructMarshalStub(dwStubFlags))
+ {
+ _ASSERTE(pSigDesc->m_pMT != nullptr);
+ StackSString strTypeName;
+ TypeString::AppendType(strTypeName, TypeHandle(pSigDesc->m_pMT));
+ COMPlusThrow(kTypeLoadException, IDS_CANNOT_MARSHAL_RECURSIVE_DEF, strTypeName.GetUnicode());
+ }
UNREACHABLE_MSG("unexpected deadlock in IL stub generation!");
}
+ pILStubLock.Acquire();
+
pGenILHolder->GetStubMethodDesc();
}
}
// We have the entry lock now, we can release the global lock
pILStubLock.Release();
+ _ASSERTE(pEntryLock.GetValue()->HasLock());
+
if (pEntry->m_hrResultCode != S_FALSE)
{
// We came in to generate the IL but someone
pResolver->SetStubMethodDesc(pStubMD);
pResolver->SetStubTargetMethodDesc(pTargetMD);
- CreateNDirectStubWorker(pss,
- pSigDesc,
- nlType,
- nlFlags,
- unmgdCallConv,
- dwStubFlags,
- pStubMD,
- pParamTokenArray,
- iLCIDArg);
+ if (SF_IsStructMarshalStub(dwStubFlags))
+ {
+ CreateStructStub(pss, pSigDesc, pTargetMT, dwStubFlags, pStubMD);
+ }
+ else
+ {
+ CreateNDirectStubWorker(pss,
+ pSigDesc,
+ nlType,
+ nlFlags,
+ unmgdCallConv,
+ dwStubFlags,
+ pStubMD,
+ pParamTokenArray,
+ iLCIDArg);
+ }
+
pResolver->SetTokenLookupMap(pss->GetTokenLookupMap());
sgh.SuppressRelease();
}
+ if (pGeneratedNewStub)
+ {
+ *pGeneratedNewStub = true;
+ }
+
pEntry->m_hrResultCode = S_OK;
break;
}
pParamTokenArray,
iLCIDArg);
-
-
RETURN pStubMD;
}
sigBuilder.AppendBlob((const PVOID)(szMetaSig + 1), cbMetaSigSize - 1);
szMetaSig = (PCCOR_SIGNATURE)sigBuilder.GetSignature(&cbMetaSigSize);
- StubSigDesc sigDesc(NULL, Signature(szMetaSig, cbMetaSigSize), pModule);
+ StubSigDesc sigDesc(nullptr, Signature(szMetaSig, cbMetaSigSize), pModule);
#ifdef _DEBUG
sigDesc.m_pDebugName = pFD->GetDebugName();
}
#endif // FEATURE_COMINTEROP
+MethodDesc* NDirect::CreateStructMarshalILStub(MethodTable* pMT)
+{
+ CONTRACT(MethodDesc*)
+ {
+ STANDARD_VM_CHECK;
+
+ PRECONDITION(CheckPointer(pMT));
+ POSTCONDITION(CheckPointer(RETVAL));
+ }
+ CONTRACT_END;
+
+ if (IsReadyToRunCompilation())
+ {
+ // We don't support emitting struct marshalling IL stubs into R2R images.
+ ThrowHR(E_FAIL);
+ }
+
+ DWORD dwStubFlags = NDIRECTSTUB_FL_STRUCT_MARSHAL;
+
+ BOOL bestFit, throwOnUnmappableChar;
+
+ ReadBestFitCustomAttribute(pMT->GetModule(), pMT->GetCl(), &bestFit, &throwOnUnmappableChar);
+
+ if (bestFit == TRUE)
+ {
+ dwStubFlags |= NDIRECTSTUB_FL_BESTFIT;
+ }
+ if (throwOnUnmappableChar == TRUE)
+ {
+ dwStubFlags |= NDIRECTSTUB_FL_THROWONUNMAPPABLECHAR;
+ }
+
+ // ValueClass signature:
+ // void (ref Struct managedData, native Struct* nativeData, int marshalAction, ref CleanupWorkListElement cwl)
+ // LayoutClass signature:
+ // void (ref byte managedData, byte* nativeData, int marshalAction, ref CleanupWorkListElement cwl)
+ constexpr int numParamTokens = 1;
+ mdParamDef pParamTokenArray[numParamTokens];
+ pParamTokenArray[0] = (mdParamDef)pMT->GetCl();
+
+ FunctionSigBuilder sigBuilder;
+
+ sigBuilder.SetCallingConv(IMAGE_CEE_CS_CALLCONV_DEFAULT);
+ LocalDesc returnType(ELEMENT_TYPE_VOID);
+ sigBuilder.SetReturnType(&returnType);
+
+
+ if (pMT->IsValueType())
+ {
+ LocalDesc managedParameter(pMT);
+ managedParameter.MakeByRef();
+ sigBuilder.NewArg(&managedParameter);
+
+ LocalDesc nativeValueType(TypeHandle{ pMT }.MakeNativeValueType());
+ nativeValueType.MakePointer();
+ sigBuilder.NewArg(&nativeValueType);
+ }
+ else
+ {
+ LocalDesc byteRef(ELEMENT_TYPE_I1);
+ byteRef.MakeByRef();
+ sigBuilder.NewArg(&byteRef);
+ LocalDesc bytePtr(ELEMENT_TYPE_I1);
+ bytePtr.MakePointer();
+ sigBuilder.NewArg(&bytePtr);
+ }
+
+ LocalDesc i4(ELEMENT_TYPE_I4);
+ sigBuilder.NewArg(&i4);
+
+ LocalDesc cleanupWorkList(MscorlibBinder::GetClass(CLASS__CLEANUP_WORK_LIST_ELEMENT));
+ cleanupWorkList.MakeByRef();
+ sigBuilder.NewArg(&cleanupWorkList);
+
+ DWORD cbMetaSigSize = sigBuilder.GetSigSize();
+ AllocMemHolder<BYTE> szMetaSig(pMT->GetLoaderAllocator()->GetHighFrequencyHeap()->AllocMem(S_SIZE_T(cbMetaSigSize)));
+ sigBuilder.GetSig(szMetaSig, cbMetaSigSize);
+
+ StubSigDesc sigDesc(pMT, Signature(szMetaSig, cbMetaSigSize), pMT->GetModule());
+
+#ifdef _DEBUG
+ sigDesc.m_pDebugName = "Struct Marshalling Stub";
+ sigDesc.m_pDebugClassName = pMT->GetDebugClassName();
+#endif // _DEBUG
+
+ Signature signature(szMetaSig, cbMetaSigSize);
+
+ NewHolder<ILStubState> pStubState = new StructMarshal_ILStubState(pMT, signature, &sigDesc.m_typeContext, dwStubFlags);
+
+ bool generatedNewStub = false;
+
+ MethodDesc* pStubMD;
+ pStubMD = CreateInteropILStub(
+ pStubState,
+ &sigDesc,
+ (CorNativeLinkType)0,
+ (CorNativeLinkFlags)0,
+ (CorPinvokeMap)0,
+ dwStubFlags,
+ numParamTokens,
+ pParamTokenArray,
+ -1,
+ &generatedNewStub);
+
+ if (generatedNewStub) // If we generated a new stub, we need to keep the signature we created allocated.
+ {
+ szMetaSig.SuppressRelease();
+ }
+
+ RETURN pStubMD;
+}
+
+PCODE NDirect::GetEntryPointForStructMarshalStub(MethodTable* pMT)
+{
+ LIMITED_METHOD_CONTRACT;
+
+ MethodDesc* pMD = CreateStructMarshalILStub(pMT);
+
+ _ASSERTE(pMD != nullptr);
+
+ return pMD->GetMultiCallableAddrOfCode();
+}
+
MethodDesc* NDirect::CreateCLRToNativeILStub(PInvokeStaticSigInfo* pSigInfo,
DWORD dwStubFlags,
MethodDesc* pMD)
}
}
+void MarshalStructViaILStub(MethodDesc* pStubMD, void* pManagedData, void* pNativeData, StructMarshalStubs::MarshalOperation operation, void** ppCleanupWorkList /* = nullptr */)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_COOPERATIVE;
+ PRECONDITION(CheckPointer(pStubMD));
+ }
+ CONTRACTL_END;
+
+ ARG_SLOT args[] =
+ {
+ PtrToArgSlot(pManagedData),
+ PtrToArgSlot(pNativeData),
+ (ARG_SLOT)operation,
+ PtrToArgSlot(ppCleanupWorkList)
+ };
+
+ MethodDescCallSite callSite(pStubMD);
+
+ callSite.Call(args);
+}
+
+void MarshalStructViaILStubCode(PCODE pStubCode, void* pManagedData, void* pNativeData, StructMarshalStubs::MarshalOperation operation, void** ppCleanupWorkList /* = nullptr */)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_COOPERATIVE;
+ PRECONDITION(pStubCode != NULL);
+ }
+ CONTRACTL_END;
+
+ PREPARE_NONVIRTUAL_CALLSITE_USING_CODE(pStubCode);
+ DECLARE_ARGHOLDER_ARRAY(args, 4);
+ args[ARGNUM_0] = PTR_TO_ARGHOLDER(pManagedData);
+ args[ARGNUM_1] = PTR_TO_ARGHOLDER(pNativeData);
+ args[ARGNUM_2] = DWORD_TO_ARGHOLDER(operation);
+ args[ARGNUM_3] = PTR_TO_ARGHOLDER(ppCleanupWorkList);
+
+ CALL_MANAGED_METHOD_NORET(args);
+}
+
+
//==========================================================================
// This function is reached only via NDirectImportThunk. It's purpose
// is to ensure that the target DLL is fully loaded and ready to run.
struct StubSigDesc
{
public:
- StubSigDesc(MethodDesc *pMD, PInvokeStaticSigInfo* pSigInfo = NULL);
- StubSigDesc(MethodDesc *pMD, Signature sig, Module *m_pModule);
+ StubSigDesc(MethodDesc * pMD, PInvokeStaticSigInfo* pSigInfo = NULL);
+ StubSigDesc(MethodDesc* pMD, Signature sig, Module* m_pModule);
+ StubSigDesc(MethodTable* pMT, Signature sig, Module* m_pModule);
+ StubSigDesc(std::nullptr_t, Signature sig, Module* m_pModule);
MethodDesc *m_pMD;
+ MethodTable *m_pMT;
Signature m_sig;
Module *m_pModule;
Module *m_pLoaderModule;
FieldDesc* pFD);
#endif // FEATURE_COMINTEROP
+ static MethodDesc* CreateStructMarshalILStub(MethodTable* pMT);
+ static PCODE GetEntryPointForStructMarshalStub(MethodTable* pMT);
+
static MethodDesc* CreateCLRToNativeILStub(PInvokeStaticSigInfo* pSigInfo,
DWORD dwStubFlags,
MethodDesc* pMD);
#endif // FEATURE_COMINTEROP
NDIRECTSTUB_FL_NGENEDSTUBFORPROFILING = 0x00000100,
NDIRECTSTUB_FL_GENERATEDEBUGGABLEIL = 0x00000200,
- // unused = 0x00000400,
+ NDIRECTSTUB_FL_STRUCT_MARSHAL = 0x00000400,
NDIRECTSTUB_FL_UNMANAGED_CALLI = 0x00000800,
NDIRECTSTUB_FL_TRIGGERCCTOR = 0x00001000,
#ifdef FEATURE_COMINTEROP
inline bool SF_IsCALLIStub (DWORD dwStubFlags) { LIMITED_METHOD_CONTRACT; return (dwStubFlags < NDIRECTSTUB_FL_INVALID && 0 != (dwStubFlags & NDIRECTSTUB_FL_UNMANAGED_CALLI)); }
inline bool SF_IsStubWithCctorTrigger (DWORD dwStubFlags) { LIMITED_METHOD_CONTRACT; return (dwStubFlags < NDIRECTSTUB_FL_INVALID && 0 != (dwStubFlags & NDIRECTSTUB_FL_TRIGGERCCTOR)); }
inline bool SF_IsForNumParamBytes (DWORD dwStubFlags) { LIMITED_METHOD_CONTRACT; return (dwStubFlags < NDIRECTSTUB_FL_INVALID && 0 != (dwStubFlags & NDIRECTSTUB_FL_FOR_NUMPARAMBYTES)); }
+inline bool SF_IsStructMarshalStub (DWORD dwStubFlags) { LIMITED_METHOD_CONTRACT; return (dwStubFlags < NDIRECTSTUB_FL_INVALID && 0 != (dwStubFlags & NDIRECTSTUB_FL_STRUCT_MARSHAL)); }
#ifdef FEATURE_ARRAYSTUB_AS_IL
inline bool SF_IsArrayOpStub (DWORD dwStubFlags) { LIMITED_METHOD_CONTRACT; return ((dwStubFlags == ILSTUB_ARRAYOP_GET) ||
// Delegate stubs are not COM
CONSISTENCY_CHECK(!(SF_IsDelegateStub(dwStubFlags) && SF_IsCOMStub(dwStubFlags)));
+
+ // Struct marshal stubs are not COM or HRESULT swapping stubs
+ CONSISTENCY_CHECK(!(SF_IsStructMarshalStub(dwStubFlags) && SF_IsCOMStub(dwStubFlags)));
+ CONSISTENCY_CHECK(!(SF_IsStructMarshalStub(dwStubFlags) && SF_IsHRESULTSwapping(dwStubFlags)));
+ CONSISTENCY_CHECK(!(SF_IsStructMarshalStub(dwStubFlags) && SF_IsReverseCOMStub(dwStubFlags)));
}
enum ETW_IL_STUB_FLAGS
ETW_IL_STUB_FLAGS_NGENED_STUB = 0x00000004,
ETW_IL_STUB_FLAGS_DELEGATE = 0x00000008,
ETW_IL_STUB_FLAGS_VARARG = 0x00000010,
- ETW_IL_STUB_FLAGS_UNMANAGED_CALLI = 0x00000020
+ ETW_IL_STUB_FLAGS_UNMANAGED_CALLI = 0x00000020,
+ ETW_IL_STUB_FLAGS_STRUCT_MARSHAL = 0x00000040
};
//---------------------------------------------------------
DWORD dwStubFlags, // NDirectStubFlags
int nParamTokens,
mdParamDef* pParamTokenArray,
- int iLCIDArg
+ int iLCIDArg,
+ MethodTable* pMT
) :
m_sig(sig),
m_pTypeContext(pTypeContext),
m_nlFlags(nlFlags),
m_dwStubFlags(dwStubFlags),
m_iLCIDArg(iLCIDArg),
- m_nParamTokens(nParamTokens)
+ m_nParamTokens(nParamTokens),
+ m_pMT(pMT)
{
LIMITED_METHOD_CONTRACT;
}
DWORD m_dwStubFlags;
int m_iLCIDArg;
int m_nParamTokens;
+ MethodTable* m_pMT;
};
PCODE GetILStubForCalli(VASigCookie *pVASigCookie, MethodDesc *pMD);
HRESULT FindPredefinedILStubMethod(MethodDesc *pTargetMD, DWORD dwStubFlags, MethodDesc **ppRetStubMD);
#endif // FEATURE_COMINTEROP
+void MarshalStructViaILStub(MethodDesc* pStubMD, void* pManagedData, void* pNativeData, StructMarshalStubs::MarshalOperation operation, void** ppCleanupWorkList = nullptr);
+void MarshalStructViaILStubCode(PCODE pStubCode, void* pManagedData, void* pNativeData, StructMarshalStubs::MarshalOperation operation, void** ppCleanupWorkList = nullptr);
+
//
// Limit length of string field in IL stub ETW events so that the whole
// IL stub ETW events won't exceed 64KB
#endif
FCFuncEnd()
-FCFuncStart(gDateMarshalerFuncs)
- FCFuncElement("ConvertToNative", StubHelpers::DateMarshaler__ConvertToNative)
- FCFuncElement("ConvertToManaged", StubHelpers::DateMarshaler__ConvertToManaged)
-FCFuncEnd()
-
-FCFuncStart(gValueClassMarshalerFuncs)
- FCFuncElement("ConvertToNative", StubHelpers::ValueClassMarshaler__ConvertToNative)
- FCFuncElement("ConvertToManaged", StubHelpers::ValueClassMarshaler__ConvertToManaged)
- FCFuncElement("ClearNative", StubHelpers::ValueClassMarshaler__ClearNative)
+FCFuncStart(gMngdFixedArrayMarshalerFuncs)
+ FCFuncElement("CreateMarshaler", MngdFixedArrayMarshaler::CreateMarshaler)
+ FCFuncElement("ConvertSpaceToNative", MngdFixedArrayMarshaler::ConvertSpaceToNative)
+ FCFuncElement("ConvertContentsToNative", MngdFixedArrayMarshaler::ConvertContentsToNative)
+ FCFuncElement("ConvertSpaceToManaged", MngdFixedArrayMarshaler::ConvertSpaceToManaged)
+ FCFuncElement("ConvertContentsToManaged", MngdFixedArrayMarshaler::ConvertContentsToManaged)
+ FCFuncElement("ClearNativeContents", MngdFixedArrayMarshaler::ClearNativeContents)
FCFuncEnd()
FCFuncStart(gMngdNativeArrayMarshalerFuncs)
FCClassElement("CriticalHandle", "System.Runtime.InteropServices", gCriticalHandleFuncs)
FCClassElement("CustomAttribute", "System.Reflection", gCOMCustomAttributeFuncs)
FCClassElement("CustomAttributeEncodedArgument", "System.Reflection", gCustomAttributeEncodedArgument)
-FCClassElement("DateMarshaler", "System.StubHelpers", gDateMarshalerFuncs)
FCClassElement("DateTime", "System", gDateTimeFuncs)
FCClassElement("Debugger", "System.Diagnostics", gDiagnosticsDebugger)
FCClassElement("Delegate", "System", gDelegateFuncs)
FCClassElement("MdUtf8String", "System", gMdUtf8String)
FCClassElement("MetadataImport", "System.Reflection", gMetaDataImport)
FCClassElement("MissingMemberException", "System", gMissingMemberExceptionFuncs)
+FCClassElement("MngdFixedArrayMarshaler", "System.StubHelpers", gMngdFixedArrayMarshalerFuncs)
#ifdef FEATURE_COMINTEROP
FCClassElement("MngdHiddenLengthArrayMarshaler", "System.StubHelpers", gMngdHiddenLengthArrayMarshalerFuncs)
#endif // FEATURE_COMINTEROP
#ifdef FEATURE_UTF8STRING
FCClassElement("Utf8String", "System", gUtf8StringFuncs)
#endif // FEATURE_UTF8STRING
-FCClassElement("ValueClassMarshaler", "System.StubHelpers", gValueClassMarshalerFuncs)
FCClassElement("ValueType", "System", gValueTypeFuncs)
#ifdef FEATURE_COMINTEROP
FCClassElement("Variant", "System", gVariantFuncs)
// Used by the classloader to post illegal layout
//==========================================================================
VOID DECLSPEC_NORETURN ThrowFieldLayoutError(mdTypeDef cl, // cl of the NStruct being loaded
- Module* pModule, // Module that defines the scope, loader and heap (for allocate FieldMarshalers)
+ Module* pModule, // Module that defines the scope, loader and heap (for allocated NativeFieldDescriptors)
DWORD dwOffset, // Offset of field
DWORD dwID) // Message id
{
UINT resIDWhy);
VOID DECLSPEC_NORETURN ThrowFieldLayoutError(mdTypeDef cl, // cl of the NStruct being loaded
- Module* pModule, // Module that defines the scope, loader and heap (for allocate FieldMarshalers)
+ Module* pModule, // Module that defines the scope, loader and heap (for allocated NativeFieldDescriptors)
DWORD dwOffset, // Field offset
DWORD dwID);
#include <winstring.h>
#endif // FEATURE_COMINTEROP
-// forward declaration
-BOOL CheckForPrimitiveType(CorElementType elemType, CQuickArray<WCHAR> *pStrPrimitiveType);
-TypeHandle ArraySubTypeLoadWorker(const SString &strUserDefTypeName, Assembly* pAssembly);
-BOOL CheckIfDisqualifiedFromManagedSequential(CorElementType corElemType, LayoutRawFieldInfo * pfwalk, MetaSig &fsig);
-TypeHandle GetFieldTypeHandleWorker(MetaSig *pFieldSig);
-#ifdef _DEBUG
-BOOL IsFixedBuffer(mdFieldDef field, IMDInternalImport *pInternalImport);
-#endif
-
-
-//=======================================================================
-// A database of NFT types.
-//=======================================================================
-
-struct NFTDataBaseEntry
-{
- UINT32 m_cbNativeSize; // native size of field (0 if not constant)
- bool m_fWinRTSupported; // true if the field marshaler is supported for WinRT
-};
-
-static const NFTDataBaseEntry NFTDataBase[] =
-{
- #undef DEFINE_NFT
- #define DEFINE_NFT(name, nativesize, fWinRTSupported) { nativesize, fWinRTSupported },
- #include "nsenums.h"
-};
-
-template<typename TFieldMarshaler, typename TSpace, typename... TArgs>
-NStructFieldType InitFieldMarshaler(TSpace& space, NativeFieldFlags flags, TArgs&&... args)
-{
- static_assert_no_msg(sizeof(TFieldMarshaler) <= MAXFIELDMARSHALERSIZE);
- static_assert_no_msg(sizeof(TSpace) == MAXFIELDMARSHALERSIZE);
- TFieldMarshaler* marshaler = new (&space) TFieldMarshaler(std::forward<TArgs>(args)...);
- marshaler->SetNStructFieldType(TFieldMarshaler::s_nft);
- marshaler->SetNativeFieldFlags(flags);
- return TFieldMarshaler::s_nft;
-}
-
-#ifdef _PREFAST_
-#pragma warning(push)
-#pragma warning(disable:21000) // Suppress PREFast warning about overly large function
-#endif
VOID ParseNativeType(Module* pModule,
- PCCOR_SIGNATURE pCOMSignature,
- DWORD cbCOMSignature,
- ParseNativeTypeFlags flags,
- LayoutRawFieldInfo* pfwalk,
- PCCOR_SIGNATURE pNativeType,
- ULONG cbNativeType,
- mdTypeDef cl,
- const SigTypeContext * pTypeContext,
- BOOL *pfDisqualifyFromManagedSequential // set to TRUE if needed (never set to FALSE, it may come in as TRUE!)
+ SigPointer sig,
+ mdFieldDef fd,
+ ParseNativeTypeFlags flags,
+ NativeFieldDescriptor* pNFD,
+ const SigTypeContext * pTypeContext
#ifdef _DEBUG
- ,
- LPCUTF8 szNamespace,
- LPCUTF8 szClassName,
- LPCUTF8 szFieldName
+ ,
+ LPCUTF8 szNamespace,
+ LPCUTF8 szClassName,
+ LPCUTF8 szFieldName
#endif
- )
+ )
{
CONTRACTL
{
STANDARD_VM_CHECK;
- PRECONDITION(CheckPointer(pfwalk));
+ PRECONDITION(CheckPointer(pNFD));
}
CONTRACTL_END;
-
- // Make sure that there is no junk in the unused part of the field marshaler space (ngen image determinism)
- ZeroMemory(&pfwalk->m_FieldMarshaler, MAXFIELDMARSHALERSIZE);
-
-
BOOL fAnsi = (flags == ParseNativeTypeFlags::IsAnsi);
#ifdef FEATURE_COMINTEROP
BOOL fIsWinRT = (flags == ParseNativeTypeFlags::IsWinRT);
#endif // FEATURE_COMINTEROP
- CorElementType corElemType = ELEMENT_TYPE_END;
- PCCOR_SIGNATURE pNativeTypeStart = pNativeType;
- ULONG cbNativeTypeStart = cbNativeType;
- CorNativeType ntype;
- BOOL fDefault;
- BOOL BestFit;
- BOOL ThrowOnUnmappableChar;
-
- if (cbNativeType == 0)
- {
- ntype = NATIVE_TYPE_DEFAULT;
- fDefault = TRUE;
- }
- else
- {
- ntype = (CorNativeType) *( ((BYTE*&)pNativeType)++ );
- cbNativeType--;
- fDefault = (ntype == NATIVE_TYPE_DEFAULT);
- }
-
- // Setup the signature and normalize
- MetaSig fsig(pCOMSignature, cbCOMSignature, pModule, pTypeContext, MetaSig::sigField);
- corElemType = fsig.NextArgNormalized();
-
-
- if (!(*pfDisqualifyFromManagedSequential))
- {
- *pfDisqualifyFromManagedSequential = CheckIfDisqualifiedFromManagedSequential(corElemType, pfwalk, fsig);
- }
-
- NStructFieldType selectedNft = NFT_NONE;
-
-#ifdef FEATURE_COMINTEROP
- if (fIsWinRT && !fDefault)
- {
- // Do not allow any MarshalAs in WinRT scenarios - marshaling is fully described by the field type.
- selectedNft = InitFieldMarshaler<FieldMarshaler_Illegal>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_ILLEGAL, IDS_EE_BADMARSHAL_WINRT_MARSHAL_AS);
- }
-#endif // FEATURE_COMINTEROP
-
-#ifdef _TARGET_X86_
- // Normalization might have put corElementType and ntype out of sync which can
- // result in problems with non-default ntype being validated against the
- // normalized primitive corElemType.
- //
- VerifyAndAdjustNormalizedType(pModule, fsig.GetArgProps(), fsig.GetSigTypeContext(), &corElemType, &ntype);
-
- fDefault = (ntype == NATIVE_TYPE_DEFAULT);
-#endif // _TARGET_X86_
-
- CorElementType sigElemType;
- IfFailThrow(fsig.GetArgProps().PeekElemType(&sigElemType));
- if ((sigElemType == ELEMENT_TYPE_GENERICINST || sigElemType == ELEMENT_TYPE_VAR) && corElemType == ELEMENT_TYPE_CLASS)
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Illegal>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_ILLEGAL, IDS_EE_BADMARSHAL_GENERICS_RESTRICTION);
- }
- else switch (corElemType)
+
+ EX_TRY
{
- case ELEMENT_TYPE_CHAR:
- if (fDefault)
- {
- if (fAnsi)
- {
- ReadBestFitCustomAttribute(pModule, cl, &BestFit, &ThrowOnUnmappableChar);
- selectedNft = InitFieldMarshaler<FieldMarshaler_Ansi>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_INTEGER_LIKE, BestFit, ThrowOnUnmappableChar);
- }
- else
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Copy2>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_BLITTABLE_INTEGER);
- }
- }
- else if (ntype == NATIVE_TYPE_I1 || ntype == NATIVE_TYPE_U1)
- {
- ReadBestFitCustomAttribute(pModule, cl, &BestFit, &ThrowOnUnmappableChar);
- selectedNft = InitFieldMarshaler<FieldMarshaler_Ansi>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_INTEGER_LIKE, BestFit, ThrowOnUnmappableChar);
-
- }
- else if (ntype == NATIVE_TYPE_I2 || ntype == NATIVE_TYPE_U2)
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Copy2>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_BLITTABLE_INTEGER);
- }
- else
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Illegal>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_ILLEGAL, IDS_EE_BADMARSHAL_CHAR);
- }
- break;
-
- case ELEMENT_TYPE_BOOLEAN:
- if (fDefault)
- {
-#ifdef FEATURE_COMINTEROP
- if (fIsWinRT)
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_CBool>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_INTEGER_LIKE);
- }
- else
-#endif // FEATURE_COMINTEROP
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_WinBool>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_INTEGER_LIKE);
- }
- }
- else if (ntype == NATIVE_TYPE_BOOLEAN)
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_WinBool>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_INTEGER_LIKE);
- }
-#ifdef FEATURE_COMINTEROP
- else if (ntype == NATIVE_TYPE_VARIANTBOOL)
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_VariantBool>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_COM_STRUCT);
- }
-#endif // FEATURE_COMINTEROP
- else if (ntype == NATIVE_TYPE_U1 || ntype == NATIVE_TYPE_I1)
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_CBool>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_INTEGER_LIKE);
- }
- else
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Illegal>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_ILLEGAL, IDS_EE_BADMARSHAL_BOOLEAN);
- }
- break;
-
-
- case ELEMENT_TYPE_I1:
- if (fDefault || ntype == NATIVE_TYPE_I1 || ntype == NATIVE_TYPE_U1)
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Copy1>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_BLITTABLE_INTEGER);
- }
- else
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Illegal>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_ILLEGAL, IDS_EE_BADMARSHAL_I1);
- }
- break;
-
- case ELEMENT_TYPE_U1:
- if (fDefault || ntype == NATIVE_TYPE_U1 || ntype == NATIVE_TYPE_I1)
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Copy1>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_BLITTABLE_INTEGER);
- }
- else
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Illegal>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_ILLEGAL, IDS_EE_BADMARSHAL_I1);
- }
- break;
-
- case ELEMENT_TYPE_I2:
- if (fDefault || ntype == NATIVE_TYPE_I2 || ntype == NATIVE_TYPE_U2)
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Copy2>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_BLITTABLE_INTEGER);
- }
- else
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Illegal>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_ILLEGAL, IDS_EE_BADMARSHAL_I2);
- }
- break;
-
- case ELEMENT_TYPE_U2:
- if (fDefault || ntype == NATIVE_TYPE_U2 || ntype == NATIVE_TYPE_I2)
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Copy2>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_BLITTABLE_INTEGER);
- }
- else
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Illegal>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_ILLEGAL, IDS_EE_BADMARSHAL_I2);
- }
- break;
-
- case ELEMENT_TYPE_I4:
- if (fDefault || ntype == NATIVE_TYPE_I4 || ntype == NATIVE_TYPE_U4 || ntype == NATIVE_TYPE_ERROR)
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Copy4>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_BLITTABLE_INTEGER);
- }
- else
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Illegal>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_ILLEGAL, IDS_EE_BADMARSHAL_I4);
- }
- break;
-
- case ELEMENT_TYPE_U4:
- if (fDefault || ntype == NATIVE_TYPE_U4 || ntype == NATIVE_TYPE_I4 || ntype == NATIVE_TYPE_ERROR)
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Copy4>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_BLITTABLE_INTEGER);
- }
- else
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Illegal>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_ILLEGAL, IDS_EE_BADMARSHAL_I4);
- }
- break;
-
- case ELEMENT_TYPE_I8:
- if (fDefault || ntype == NATIVE_TYPE_I8 || ntype == NATIVE_TYPE_U8)
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Copy8>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_BLITTABLE_INTEGER);
- }
- else
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Illegal>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_ILLEGAL, IDS_EE_BADMARSHAL_I8);
- }
- break;
-
- case ELEMENT_TYPE_U8:
- if (fDefault || ntype == NATIVE_TYPE_U8 || ntype == NATIVE_TYPE_I8)
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Copy8>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_BLITTABLE_INTEGER);
- }
- else
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Illegal>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_ILLEGAL, IDS_EE_BADMARSHAL_I8);
- }
- break;
-
- case ELEMENT_TYPE_I: //fallthru
- case ELEMENT_TYPE_U:
-#ifdef FEATURE_COMINTEROP
- if (fIsWinRT)
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Illegal>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_ILLEGAL, IDS_EE_BADMARSHAL_WINRT_ILLEGAL_TYPE);
- }
- else
-#endif // FEATURE_COMINTEROP
- if (fDefault || ntype == NATIVE_TYPE_INT || ntype == NATIVE_TYPE_UINT)
- {
-#ifdef _TARGET_64BIT_
- selectedNft = InitFieldMarshaler<FieldMarshaler_Copy8>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_BLITTABLE_INTEGER);
-#else // !_TARGET_64BIT_
- selectedNft = InitFieldMarshaler<FieldMarshaler_Copy4>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_BLITTABLE_INTEGER);
-#endif // !_TARGET_64BIT_
- }
- else
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Illegal>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_ILLEGAL, IDS_EE_BADMARSHAL_I);
- }
- break;
- case ELEMENT_TYPE_R4:
- if (fDefault || ntype == NATIVE_TYPE_R4)
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Copy4>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_R4);
- }
- else
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Illegal>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_ILLEGAL, IDS_EE_BADMARSHAL_R4);
- }
- break;
-
- case ELEMENT_TYPE_R8:
- if (fDefault || ntype == NATIVE_TYPE_R8)
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Copy8>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_R8);
- }
- else
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Illegal>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_ILLEGAL, IDS_EE_BADMARSHAL_R8);
- }
- break;
+ MarshalInfo mlInfo(
+ pModule,
+ sig,
+ pTypeContext,
+ fd,
+#if FEATURE_COMINTEROP
+ fIsWinRT ? MarshalInfo::MARSHAL_SCENARIO_WINRT_FIELD : MarshalInfo::MARSHAL_SCENARIO_FIELD,
+#else
+ MarshalInfo::MARSHAL_SCENARIO_FIELD,
+#endif
+ fAnsi ? nltAnsi : nltUnicode,
+ nlfNone,
+ FALSE,
+ 0,
+ 0,
+ FALSE, // We only need validation of the native signature and the MARSHAL_TYPE_*
+ FALSE, // so we don't need to accurately get the BestFitCustomAttribute data for this construction.
+ FALSE, /* fEmitsIL */
+ FALSE, /* onInstanceMethod */
+ nullptr,
+ FALSE, /* fUseCustomMarshal */
+ TRUE /* fCalculatingFieldMetadata */
+#ifdef _DEBUG
+ ,
+ szFieldName,
+ szClassName,
+ -1 /* field */
+#endif
+ );
- case ELEMENT_TYPE_PTR:
-#ifdef FEATURE_COMINTEROP
- if (fIsWinRT)
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Illegal>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_ILLEGAL, IDS_EE_BADMARSHAL_WINRT_ILLEGAL_TYPE);
- }
- else
-#endif // FEATURE_COMINTEROP
- if (fDefault)
- {
-#ifdef _TARGET_64BIT_
- selectedNft = InitFieldMarshaler<FieldMarshaler_Copy8>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_BLITTABLE_INTEGER);
-#else // !_TARGET_64BIT_
- selectedNft = InitFieldMarshaler<FieldMarshaler_Copy4>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_BLITTABLE_INTEGER);
-#endif // !_TARGET_64BIT_
- }
- else
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Illegal>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_ILLEGAL, IDS_EE_BADMARSHAL_PTR);
- }
- break;
+ OverrideProcArgs const* const pargs = mlInfo.GetOverrideProcArgs();
- case ELEMENT_TYPE_VALUETYPE:
+ switch (mlInfo.GetMarshalType())
{
- // This may cause a TypeLoadException, which we currently seem to have to swallow.
- // This happens with structs that contain fields of class type where the class itself
- // refers to the struct in a field.
- TypeHandle thNestedType = GetFieldTypeHandleWorker(&fsig);
- if (!thNestedType.GetMethodTable())
+ case MarshalInfo::MARSHAL_TYPE_GENERIC_1:
+ case MarshalInfo::MARSHAL_TYPE_GENERIC_U1:
+ *pNFD = NativeFieldDescriptor(NATIVE_FIELD_CATEGORY_BLITTABLE_INTEGER, sizeof(INT8), alignof(INT8));
break;
-#ifdef FEATURE_COMINTEROP
- if (fIsWinRT && sigElemType == ELEMENT_TYPE_GENERICINST)
- {
- // If this is a generic value type, lets see whether it is a Nullable<T>
- TypeHandle genType = fsig.GetLastTypeHandleThrowing();
- if(genType != nullptr && genType.GetMethodTable()->HasSameTypeDefAs(g_pNullableClass))
- {
- // The generic type is System.Nullable<T>.
- // Lets extract the typeArg and check if the typeArg is valid.
- // typeArg is invalid if
- // 1. It is not a value type.
- // 2. It is string
- // 3. We have an open type with us.
- Instantiation inst = genType.GetMethodTable()->GetInstantiation();
- MethodTable* typeArgMT = inst[0].GetMethodTable();
- if (!typeArgMT->IsLegalNonArrayWinRTType())
- {
- // Type is not a valid WinRT value type.
- selectedNft = InitFieldMarshaler<FieldMarshaler_Illegal>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_ILLEGAL, IDS_EE_BADMARSHAL_NULLABLE_RESTRICTION);
- }
- else
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Nullable>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_WELL_KNOWN, genType.GetMethodTable());
- }
- break;
- }
- }
-#endif
- if (fsig.IsClass(g_DateClassName))
- {
- if (fDefault || ntype == NATIVE_TYPE_STRUCT)
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Date>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_DATE);
- }
- else
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Illegal>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_ILLEGAL, IDS_EE_BADMARSHAL_DATETIME);
- }
- }
- else if (fsig.IsClass(g_DecimalClassName))
- {
- if (fDefault || ntype == NATIVE_TYPE_STRUCT)
- {
- // The decimal type can't be blittable since the managed and native alignment requirements differ.
- // Native needs 8-byte alignment since one field is a 64-bit integer, but managed only needs 4-byte alignment since all fields are ints.
- selectedNft = InitFieldMarshaler<FieldMarshaler_Decimal>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_NESTED);
- }
-#ifdef FEATURE_COMINTEROP
- else if (ntype == NATIVE_TYPE_CURRENCY)
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Currency>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_COM_STRUCT);
- }
-#endif // FEATURE_COMINTEROP
- else
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Illegal>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_ILLEGAL, IDS_EE_BADMARSHALFIELD_DECIMAL);
- }
- }
-#ifdef FEATURE_COMINTEROP
- else if (fsig.IsClass(g_DateTimeOffsetClassName))
- {
- if (fDefault || ntype == NATIVE_TYPE_STRUCT)
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_DateTimeOffset>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_WELL_KNOWN);
- }
- else
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Illegal>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_ILLEGAL, IDS_EE_BADMARSHAL_DATETIMEOFFSET);
- }
- }
- else if (fIsWinRT && !thNestedType.GetMethodTable()->IsLegalNonArrayWinRTType())
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Illegal>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_ILLEGAL, IDS_EE_BADMARSHAL_WINRT_ILLEGAL_TYPE);
- }
-#endif // FEATURE_COMINTEROP
- else if (thNestedType.GetMethodTable()->HasLayout())
- {
- if (fDefault || ntype == NATIVE_TYPE_STRUCT)
- {
- if (IsStructMarshalable(thNestedType))
- {
-#ifdef _DEBUG
- selectedNft = InitFieldMarshaler<FieldMarshaler_NestedValueClass>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_NESTED_VALUE_CLASS, thNestedType.GetMethodTable(), IsFixedBuffer(pfwalk->m_MD, pModule->GetMDImport()));
+ case MarshalInfo::MARSHAL_TYPE_GENERIC_2:
+ case MarshalInfo::MARSHAL_TYPE_GENERIC_U2:
+ *pNFD = NativeFieldDescriptor(NATIVE_FIELD_CATEGORY_BLITTABLE_INTEGER, sizeof(INT16), alignof(INT16));
+ break;
+ case MarshalInfo::MARSHAL_TYPE_GENERIC_4:
+ case MarshalInfo::MARSHAL_TYPE_GENERIC_U4:
+ *pNFD = NativeFieldDescriptor(NATIVE_FIELD_CATEGORY_BLITTABLE_INTEGER, sizeof(INT32), alignof(INT32));
+ break;
+ case MarshalInfo::MARSHAL_TYPE_GENERIC_8:
+#if defined(_TARGET_X86_) && defined(UNIX_X86_ABI)
+ *pNFD = NativeFieldDescriptor(NATIVE_FIELD_CATEGORY_BLITTABLE_INTEGER, sizeof(INT64), 4);
#else
- selectedNft = InitFieldMarshaler<FieldMarshaler_NestedValueClass>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_NESTED_VALUE_CLASS, thNestedType.GetMethodTable());
+ *pNFD = NativeFieldDescriptor(NATIVE_FIELD_CATEGORY_BLITTABLE_INTEGER, sizeof(INT64), sizeof(INT64));
#endif
- }
- else
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Illegal>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_ILLEGAL, IDS_EE_BADMARSHAL_NOTMARSHALABLE);
- }
- }
- else
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Illegal>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_ILLEGAL, IDS_EE_BADMARSHAL_VALUETYPE);
- }
- }
- else
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Illegal>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_ILLEGAL, IDS_EE_BADMARSHAL_NOTMARSHALABLE);
- }
- break;
- }
-
- case ELEMENT_TYPE_CLASS:
- {
- // This may cause a TypeLoadException, which we currently seem to have to swallow.
- // This happens with structs that contain fields of class type where the class itself
- // refers to the struct in a field.
- TypeHandle thNestedType = GetFieldTypeHandleWorker(&fsig);
- if (!thNestedType.GetMethodTable())
break;
-
- if (thNestedType.GetMethodTable()->IsObjectClass())
- {
-#ifdef FEATURE_COMINTEROP
- if (fDefault || ntype == NATIVE_TYPE_IUNKNOWN || ntype == NATIVE_TYPE_IDISPATCH || ntype == NATIVE_TYPE_INTF)
- {
- // Only NATIVE_TYPE_IDISPATCH maps to an IDispatch based interface pointer.
- DWORD dwFlags = ItfMarshalInfo::ITF_MARSHAL_USE_BASIC_ITF;
- if (ntype == NATIVE_TYPE_IDISPATCH)
- {
- dwFlags |= ItfMarshalInfo::ITF_MARSHAL_DISP_ITF;
- }
- selectedNft = InitFieldMarshaler<FieldMarshaler_Interface>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_INTERFACE_TYPE, nullptr, nullptr, dwFlags);
- }
- else if (ntype == NATIVE_TYPE_STRUCT)
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Variant>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_COM_STRUCT);
- }
-#else // FEATURE_COMINTEROP
- if (fDefault || ntype == NATIVE_TYPE_IUNKNOWN || ntype == NATIVE_TYPE_IDISPATCH || ntype == NATIVE_TYPE_INTF)
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Illegal>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_ILLEGAL, IDS_EE_OBJECT_TO_ITF_NOT_SUPPORTED);
- }
- else if (ntype == NATIVE_TYPE_STRUCT)
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Illegal>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_ILLEGAL, IDS_EE_OBJECT_TO_VARIANT_NOT_SUPPORTED);
- }
-#endif // FEATURE_COMINTEROP
- else
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Illegal>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_ILLEGAL, IDS_EE_BADMARSHALFIELD_OBJECT);
- }
- }
-#ifdef FEATURE_COMINTEROP
- else if (ntype == NATIVE_TYPE_INTF || thNestedType.IsInterface())
- {
- if (fIsWinRT && !thNestedType.GetMethodTable()->IsLegalNonArrayWinRTType())
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Illegal>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_ILLEGAL, IDS_EE_BADMARSHAL_WINRT_ILLEGAL_TYPE);
- }
- else if (COMDelegate::IsDelegate(thNestedType.GetMethodTable()))
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Illegal>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_ILLEGAL, IDS_EE_BADMARSHAL_DELEGATE_TLB_INTERFACE);
- }
- else
- {
- ItfMarshalInfo itfInfo;
- if (FAILED(MarshalInfo::TryGetItfMarshalInfo(thNestedType, FALSE, FALSE, &itfInfo)))
- break;
-
- selectedNft = InitFieldMarshaler<FieldMarshaler_Interface>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_INTERFACE_TYPE, itfInfo.thClass.GetMethodTable(), itfInfo.thItf.GetMethodTable(), itfInfo.dwFlags);
- }
- }
-#else // FEATURE_COMINTEROP
- else if (ntype == NATIVE_TYPE_INTF || thNestedType.IsInterface())
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Illegal>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_ILLEGAL, IDS_EE_OBJECT_TO_ITF_NOT_SUPPORTED);
- }
-#endif // FEATURE_COMINTEROP
- else if (ntype == NATIVE_TYPE_CUSTOMMARSHALER)
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Illegal>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_ILLEGAL, IDS_EE_BADMARSHALFIELD_NOCUSTOMMARSH);
- }
- else if (thNestedType == TypeHandle(g_pStringClass))
- {
- if (fDefault)
- {
-#ifdef FEATURE_COMINTEROP
- if (fIsWinRT)
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_HSTRING>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_COM_STRUCT);
- }
- else
-#endif // FEATURE_COMINTEROP
- if (fAnsi)
- {
- ReadBestFitCustomAttribute(pModule, cl, &BestFit, &ThrowOnUnmappableChar);
- selectedNft = InitFieldMarshaler<FieldMarshaler_StringAnsi>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_INTEGER_LIKE, BestFit, ThrowOnUnmappableChar);
- }
- else
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_StringUni>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_INTEGER_LIKE);
- }
- }
- else
- {
- switch (ntype)
- {
- case NATIVE_TYPE_LPSTR:
- ReadBestFitCustomAttribute(pModule, cl, &BestFit, &ThrowOnUnmappableChar);
- selectedNft = InitFieldMarshaler<FieldMarshaler_StringAnsi>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_INTEGER_LIKE, BestFit, ThrowOnUnmappableChar);
- break;
-
- case NATIVE_TYPE_LPWSTR:
- selectedNft = InitFieldMarshaler<FieldMarshaler_StringUni>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_INTEGER_LIKE);
- break;
-
- case NATIVE_TYPE_LPUTF8STR:
- selectedNft = InitFieldMarshaler<FieldMarshaler_StringUtf8>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_INTEGER_LIKE);
- break;
-
- case NATIVE_TYPE_LPTSTR:
- // We no longer support Win9x so LPTSTR always maps to a Unicode string.
- selectedNft = InitFieldMarshaler<FieldMarshaler_StringUni>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_INTEGER_LIKE);
- break;
-
- case NATIVE_TYPE_BSTR:
- selectedNft = InitFieldMarshaler<FieldMarshaler_BSTR>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_INTEGER_LIKE);
- break;
-
-#ifdef FEATURE_COMINTEROP
- case NATIVE_TYPE_HSTRING:
- selectedNft = InitFieldMarshaler<FieldMarshaler_HSTRING>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_COM_STRUCT);
- break;
-#endif // FEATURE_COMINTEROP
- case NATIVE_TYPE_FIXEDSYSSTRING:
- {
- ULONG nchars;
- ULONG udatasize = CorSigUncompressedDataSize(pNativeType);
-
- if (cbNativeType < udatasize)
- break;
-
- nchars = CorSigUncompressData(pNativeType);
- cbNativeType -= udatasize;
-
- if (nchars == 0)
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Illegal>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_ILLEGAL, IDS_EE_BADMARSHALFIELD_ZEROLENGTHFIXEDSTRING);
- break;
- }
-
- if (fAnsi)
- {
- ReadBestFitCustomAttribute(pModule, cl, &BestFit, &ThrowOnUnmappableChar);
- selectedNft = InitFieldMarshaler<FieldMarshaler_FixedStringAnsi>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_INTEGER_LIKE, nchars, BestFit, ThrowOnUnmappableChar);
- }
- else
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_FixedStringUni>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_INTEGER_LIKE, nchars);
- }
- }
- break;
-
- default:
- selectedNft = InitFieldMarshaler<FieldMarshaler_Illegal>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_ILLEGAL, IDS_EE_BADMARSHALFIELD_STRING);
- break;
- }
- }
- }
+ case MarshalInfo::MARSHAL_TYPE_ANSICHAR:
+ *pNFD = NativeFieldDescriptor(NATIVE_FIELD_CATEGORY_INTEGER_LIKE, sizeof(CHAR), sizeof(CHAR));
+ break;
+ case MarshalInfo::MARSHAL_TYPE_WINBOOL:
+ *pNFD = NativeFieldDescriptor(NATIVE_FIELD_CATEGORY_INTEGER_LIKE, sizeof(BOOL), sizeof(BOOL));
+ break;
+ case MarshalInfo::MARSHAL_TYPE_CBOOL:
+ *pNFD = NativeFieldDescriptor(NATIVE_FIELD_CATEGORY_INTEGER_LIKE, sizeof(bool), sizeof(bool));
+ break;
#ifdef FEATURE_COMINTEROP
- else if (fIsWinRT && fsig.IsClass(g_TypeClassName))
- { // Note: If the System.Type field is in non-WinRT struct, do not change the previously shipped behavior
- selectedNft = InitFieldMarshaler<FieldMarshaler_SystemType>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_WELL_KNOWN);
- }
- else if (fIsWinRT && fsig.IsClass(g_ExceptionClassName)) // Marshal Windows.Foundation.HResult as System.Exception for WinRT.
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Exception>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_WELL_KNOWN);
- }
-#endif //FEATURE_COMINTEROP
-#ifdef FEATURE_CLASSIC_COMINTEROP
- else if (thNestedType.GetMethodTable() == g_pArrayClass)
- {
- if (ntype == NATIVE_TYPE_SAFEARRAY)
- {
- NativeTypeParamInfo ParamInfo;
- CorElementType etyp = ELEMENT_TYPE_OBJECT;
- MethodTable* pMT = nullptr;
- VARTYPE vtElement = VT_EMPTY;
-
- // Compat: If no safe array used def subtype was specified, we assume TypeOf(Object).
- TypeHandle thElement = TypeHandle(g_pObjectClass);
-
- // If we have no native type data, assume default behavior
- if (S_OK != CheckForCompressedData(pNativeTypeStart, pNativeType, cbNativeTypeStart))
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_SafeArray>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_COM_STRUCT, VT_EMPTY, nullptr);
- break;
- }
-
- vtElement = (VARTYPE) (CorSigUncompressData(/*modifies*/pNativeType));
-
- // Extract the name of the record type's.
- if (S_OK == CheckForCompressedData(pNativeTypeStart, pNativeType, cbNativeTypeStart))
- {
- ULONG strLen;
- if (FAILED(CPackedLen::SafeGetData(pNativeType, pNativeTypeStart + cbNativeTypeStart, &strLen, &pNativeType)))
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Illegal>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_ILLEGAL, IDS_EE_BADMARSHAL_BADMETADATA);
- break;
- }
- if (strLen > 0)
- {
- // Load the type. Use a SString for the string since we need to null terminate the string
- // that comes from the metadata.
- StackSString safeArrayUserDefTypeName(SString::Utf8, (LPCUTF8)pNativeType, strLen);
- _ASSERTE((ULONG)(pNativeType + strLen - pNativeTypeStart) == cbNativeTypeStart);
-
- // Sadly this may cause a TypeLoadException, which we currently have to swallow.
- // This happens with structs that contain fields of class type where the class itself
- // refers to the struct in a field.
- thElement = ArraySubTypeLoadWorker(safeArrayUserDefTypeName, pModule->GetAssembly());
- if (thElement.IsNull())
- break;
- }
- }
-
- ArrayMarshalInfo arrayMarshalInfo(amiRuntime);
- arrayMarshalInfo.InitForSafeArray(MarshalInfo::MARSHAL_SCENARIO_FIELD, thElement, vtElement, fAnsi);
-
- if (!arrayMarshalInfo.IsValid())
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Illegal>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_ILLEGAL, arrayMarshalInfo.GetErrorResourceId());
- break;
- }
-
- selectedNft = InitFieldMarshaler<FieldMarshaler_SafeArray>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_COM_STRUCT, arrayMarshalInfo.GetElementVT(), arrayMarshalInfo.GetElementTypeHandle().GetMethodTable());
- }
- else if (ntype == NATIVE_TYPE_FIXEDARRAY)
- {
- // Check for the number of elements. This is required, if not present fail.
- if (S_OK != CheckForCompressedData(pNativeTypeStart, pNativeType, cbNativeTypeStart))
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Illegal>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_ILLEGAL, IDS_EE_BADMARSHALFIELD_FIXEDARRAY_NOSIZE);
- break;
- }
-
- ULONG numElements = CorSigUncompressData(/*modifies*/pNativeType);
-
- if (numElements == 0)
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Illegal>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_ILLEGAL, IDS_EE_BADMARSHALFIELD_FIXEDARRAY_ZEROSIZE);
- break;
- }
-
- // Since these always export to arrays of BSTRs, we don't need to fetch the native type.
-
- // Compat: FixedArrays of System.Arrays map to fixed arrays of BSTRs.
- selectedNft = InitFieldMarshaler<FieldMarshaler_FixedArray>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_NESTED, pModule, cl, numElements, VT_BSTR, g_pStringClass);
- }
- }
-#endif // FEATURE_CLASSIC_COMINTEROP
- else if (COMDelegate::IsDelegate(thNestedType.GetMethodTable()))
- {
- if (fDefault || ntype == NATIVE_TYPE_FUNC)
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Delegate>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_INTEGER_LIKE, thNestedType.GetMethodTable());
- }
-#ifdef FEATURE_COMINTEROP
- else if (ntype == NATIVE_TYPE_IDISPATCH)
- {
- ItfMarshalInfo itfInfo;
- if (FAILED(MarshalInfo::TryGetItfMarshalInfo(thNestedType, FALSE, FALSE, &itfInfo)))
- break;
-
- selectedNft = InitFieldMarshaler<FieldMarshaler_Interface>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_INTERFACE_TYPE, itfInfo.thClass.GetMethodTable(), itfInfo.thItf.GetMethodTable(), itfInfo.dwFlags);
- }
-#endif // FEATURE_COMINTEROP
- else
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Illegal>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_ILLEGAL, IDS_EE_BADMARSHAL_DELEGATE);
- }
- }
- else if (thNestedType.CanCastTo(TypeHandle(MscorlibBinder::GetClass(CLASS__SAFE_HANDLE))))
- {
- if (fDefault)
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_SafeHandle>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_INTEGER_LIKE);
- }
- else
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Illegal>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_ILLEGAL, IDS_EE_BADMARSHAL_SAFEHANDLE);
- }
- }
- else if (thNestedType.CanCastTo(TypeHandle(MscorlibBinder::GetClass(CLASS__CRITICAL_HANDLE))))
- {
- if (fDefault)
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_CriticalHandle>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_INTEGER_LIKE);
- }
- else
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Illegal>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_ILLEGAL, IDS_EE_BADMARSHAL_CRITICALHANDLE);
- }
- }
- else if (fsig.IsClass(g_StringBufferClassName))
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Illegal>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_ILLEGAL, IDS_EE_BADMARSHALFIELD_NOSTRINGBUILDER);
- }
- else if (IsStructMarshalable(thNestedType))
- {
- if (fDefault || ntype == NATIVE_TYPE_STRUCT)
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_NestedLayoutClass>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_NESTED, thNestedType.GetMethodTable());
- }
- else
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Illegal>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_ILLEGAL, IDS_EE_BADMARSHALFIELD_LAYOUTCLASS);
- }
- }
-#ifdef FEATURE_COMINTEROP
- else if (fIsWinRT)
- {
- // no other reference types are allowed as field types in WinRT
- selectedNft = InitFieldMarshaler<FieldMarshaler_Illegal>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_ILLEGAL, IDS_EE_BADMARSHAL_WINRT_ILLEGAL_TYPE);
- }
- else if (fDefault)
- {
- ItfMarshalInfo itfInfo;
- if (FAILED(MarshalInfo::TryGetItfMarshalInfo(thNestedType, FALSE, FALSE, &itfInfo)))
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Illegal>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_ILLEGAL, IDS_EE_BADMARSHAL_BADMANAGED);
- }
- else
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Interface>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_INTERFACE_TYPE, itfInfo.thClass.GetMethodTable(), itfInfo.thItf.GetMethodTable(), itfInfo.dwFlags);
- }
- }
-#endif // FEATURE_COMINTEROP
- break;
- }
-
- case ELEMENT_TYPE_SZARRAY:
- case ELEMENT_TYPE_ARRAY:
- {
-#ifdef FEATURE_COMINTEROP
- if (fIsWinRT)
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Illegal>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_ILLEGAL, IDS_EE_BADMARSHAL_WINRT_ILLEGAL_TYPE);
- break;
- }
-#endif // FEATURE_COMINTEROP
-
- // This may cause a TypeLoadException, which we currently seem to have to swallow.
- // This happens with structs that contain fields of class type where the class itself
- // refers to the struct in a field.
- TypeHandle thArray = GetFieldTypeHandleWorker(&fsig);
- if (thArray.IsNull() || !thArray.IsArray())
- break;
-
- TypeHandle thElement = thArray.AsArray()->GetArrayElementTypeHandle();
- if (thElement.IsNull())
+ case MarshalInfo::MARSHAL_TYPE_VTBOOL:
+ *pNFD = NativeFieldDescriptor(NATIVE_FIELD_CATEGORY_INTEGER_LIKE, sizeof(VARIANT_BOOL), sizeof(VARIANT_BOOL));
break;
-
- if (ntype == NATIVE_TYPE_FIXEDARRAY)
- {
- CorNativeType elementNativeType = NATIVE_TYPE_DEFAULT;
-
- // The size constant must be specified, if it isn't then the struct can't be marshalled.
- if (S_OK != CheckForCompressedData(pNativeTypeStart, pNativeType, cbNativeTypeStart))
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Illegal>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_ILLEGAL, IDS_EE_BADMARSHALFIELD_FIXEDARRAY_NOSIZE);
- break;
- }
-
- // Read the size const, if it's 0, then the struct can't be marshalled.
- ULONG numElements = CorSigUncompressData(pNativeType);
- if (numElements == 0)
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Illegal>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_ILLEGAL, IDS_EE_BADMARSHALFIELD_FIXEDARRAY_ZEROSIZE);
- break;
- }
-
- // The array sub type is optional so extract it if specified.
- if (S_OK == CheckForCompressedData(pNativeTypeStart, pNativeType, cbNativeTypeStart))
- elementNativeType = (CorNativeType)CorSigUncompressData(pNativeType);
-
- ArrayMarshalInfo arrayMarshalInfo(amiRuntime);
- arrayMarshalInfo.InitForFixedArray(thElement, elementNativeType, fAnsi);
-
- if (!arrayMarshalInfo.IsValid())
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Illegal>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_ILLEGAL, arrayMarshalInfo.GetErrorResourceId());
- break;
- }
-
- if (arrayMarshalInfo.GetElementVT() == VTHACK_ANSICHAR)
- {
- // We need to special case fixed sized arrays of ANSI chars since the OleVariant code
- // that is used by the generic fixed size array marshaller doesn't support them
- // properly.
- ReadBestFitCustomAttribute(pModule, cl, &BestFit, &ThrowOnUnmappableChar);
- selectedNft = InitFieldMarshaler<FieldMarshaler_FixedCharArrayAnsi>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_INTEGER_LIKE, numElements, BestFit, ThrowOnUnmappableChar);
- break;
- }
- else
- {
- VARTYPE elementVT = arrayMarshalInfo.GetElementVT();
-
- selectedNft = InitFieldMarshaler<FieldMarshaler_FixedArray>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_NESTED, pModule, cl, numElements, elementVT, arrayMarshalInfo.GetElementTypeHandle().GetMethodTable());
- break;
- }
- }
-#ifdef FEATURE_CLASSIC_COMINTEROP
- else if (fDefault || ntype == NATIVE_TYPE_SAFEARRAY)
- {
- VARTYPE vtElement = VT_EMPTY;
-
- // Check for data remaining in the signature before we attempt to grab some.
- if (S_OK == CheckForCompressedData(pNativeTypeStart, pNativeType, cbNativeTypeStart))
- vtElement = (VARTYPE) (CorSigUncompressData(/*modifies*/pNativeType));
-
- ArrayMarshalInfo arrayMarshalInfo(amiRuntime);
- arrayMarshalInfo.InitForSafeArray(MarshalInfo::MARSHAL_SCENARIO_FIELD, thElement, vtElement, fAnsi);
-
- if (!arrayMarshalInfo.IsValid())
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Illegal>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_ILLEGAL, arrayMarshalInfo.GetErrorResourceId());
- break;
- }
-
- selectedNft = InitFieldMarshaler<FieldMarshaler_SafeArray>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_COM_STRUCT, arrayMarshalInfo.GetElementVT(), arrayMarshalInfo.GetElementTypeHandle().GetMethodTable());
- }
-#endif //FEATURE_CLASSIC_COMINTEROP
- else
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Illegal>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_ILLEGAL, IDS_EE_BADMARSHALFIELD_ARRAY);
- }
- break;
- }
-
- case ELEMENT_TYPE_OBJECT:
- case ELEMENT_TYPE_STRING:
- break;
-
- default:
- // let it fall thru as NFT_NONE
- break;
- }
-
- if (selectedNft == NFT_NONE)
- {
- selectedNft = InitFieldMarshaler<FieldMarshaler_Illegal>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_ILLEGAL, IDS_EE_BADMARSHAL_BADMANAGED);
- }
-#ifdef FEATURE_COMINTEROP
- else if (fIsWinRT && !NFTDataBase[(UINT16)selectedNft].m_fWinRTSupported)
- {
- // the field marshaler we came up with is not supported in WinRT scenarios
- ZeroMemory(&pfwalk->m_FieldMarshaler, MAXFIELDMARSHALERSIZE);
- selectedNft = InitFieldMarshaler<FieldMarshaler_Illegal>(pfwalk->m_FieldMarshaler, NATIVE_FIELD_CATEGORY_ILLEGAL, IDS_EE_BADMARSHAL_WINRT_ILLEGAL_TYPE);
- }
-#endif // FEATURE_COMINTEROP
-}
-
-#ifdef _PREFAST_
-#pragma warning(pop)
-#endif
-
-BOOL CheckIfDisqualifiedFromManagedSequential(CorElementType corElemType, LayoutRawFieldInfo * pRawFieldInfo, MetaSig &fsig)
-{
- // This type may qualify for ManagedSequential. Collect managed size and alignment info.
- if (CorTypeInfo::IsPrimitiveType(corElemType))
- {
- pRawFieldInfo->m_managedPlacement.m_size = ((UINT32)CorTypeInfo::Size(corElemType)); // Safe cast - no primitive type is larger than 4gb!
-#if defined(_TARGET_X86_) && defined(UNIX_X86_ABI)
- switch (corElemType)
- {
- // The System V ABI for i386 defines different packing for these types.
- case ELEMENT_TYPE_I8:
- case ELEMENT_TYPE_U8:
- case ELEMENT_TYPE_R8:
- {
- pRawFieldInfo->m_managedPlacement.m_alignment = 4;
- break;
- }
-
- default:
- {
- pRawFieldInfo->m_managedPlacement.m_alignment = pRawFieldInfo->m_managedPlacement.m_size;
- break;
- }
- }
-#else // _TARGET_X86_ && UNIX_X86_ABI
- pRawFieldInfo->m_managedPlacement.m_alignment = pRawFieldInfo->m_managedPlacement.m_size;
-#endif
-
- return FALSE;
- }
- else if (corElemType == ELEMENT_TYPE_PTR)
- {
- pRawFieldInfo->m_managedPlacement.m_size = TARGET_POINTER_SIZE;
- pRawFieldInfo->m_managedPlacement.m_alignment = TARGET_POINTER_SIZE;
-
- return FALSE;
- }
- else if (corElemType == ELEMENT_TYPE_VALUETYPE)
- {
- TypeHandle pNestedType = fsig.GetLastTypeHandleThrowing(ClassLoader::LoadTypes,
- CLASS_LOAD_APPROXPARENTS,
- TRUE);
- if (!pNestedType.GetMethodTable()->IsManagedSequential())
- {
- return TRUE;
- }
-
- pRawFieldInfo->m_managedPlacement.m_size = (pNestedType.GetMethodTable()->GetNumInstanceFieldBytes());
-
- _ASSERTE(pNestedType.GetMethodTable()->HasLayout()); // If it is ManagedSequential(), it also has Layout but doesn't hurt to check before we do a cast!
- pRawFieldInfo->m_managedPlacement.m_alignment = pNestedType.GetMethodTable()->GetLayoutInfo()->m_ManagedLargestAlignmentRequirementOfAllMembers;
-
- return FALSE;
- }
- // No other type permitted for ManagedSequential.
- return TRUE;
-}
-
-
-TypeHandle ArraySubTypeLoadWorker(const SString &strUserDefTypeName, Assembly* pAssembly)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- PRECONDITION(CheckPointer(pAssembly));
- }
- CONTRACTL_END;
-
- TypeHandle th;
-
- EX_TRY
- {
- // Load the user defined type.
- StackScratchBuffer utf8Name;
- th = TypeName::GetTypeUsingCASearchRules(strUserDefTypeName.GetUTF8(utf8Name), pAssembly);
- }
- EX_CATCH
- {
- }
- EX_END_CATCH(RethrowTerminalExceptions)
-
- return th;
-}
-
-
-TypeHandle GetFieldTypeHandleWorker(MetaSig *pFieldSig)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- PRECONDITION(CheckPointer(pFieldSig));
- }
- CONTRACTL_END;
-
- TypeHandle th;
-
- EX_TRY
- {
- // Load the user defined type.
- th = pFieldSig->GetLastTypeHandleThrowing(ClassLoader::LoadTypes,
- CLASS_LOAD_APPROXPARENTS,
- TRUE /*dropGenericArgumentLevel*/);
- }
- EX_CATCH
- {
- }
- EX_END_CATCH(RethrowTerminalExceptions)
-
- return th;
-}
-
-
-//=======================================================================
-// This function returns TRUE if the type passed in is either a value class or a class and if it has layout information
-// and is marshalable. In all other cases it will return FALSE.
-//=======================================================================
-BOOL IsStructMarshalable(TypeHandle th)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(!th.IsNull());
- }
- CONTRACTL_END;
-
- if (th.IsBlittable())
- {
- // th.IsBlittable will return true for arrays of blittable types, however since IsStructMarshalable
- // is only supposed to return true for value classes or classes with layout that are marshallable
- // we need to return false if the type is an array.
- if (th.IsArray())
- return FALSE;
- else
- return TRUE;
- }
-
- // Check to see if the type has layout.
- if (!th.HasLayout())
- return FALSE;
-
- MethodTable *pMT= th.GetMethodTable();
- PREFIX_ASSUME(pMT != NULL);
-
- if (pMT->IsStructMarshalable())
- return TRUE;
-
- const FieldMarshaler *pFieldMarshaler = pMT->GetLayoutInfo()->GetFieldMarshalers();
- UINT numReferenceFields = pMT->GetLayoutInfo()->GetNumCTMFields();
-
- while (numReferenceFields--)
- {
- if (pFieldMarshaler->IsIllegalMarshaler())
- return FALSE;
-
- ((BYTE*&)pFieldMarshaler) += MAXFIELDMARSHALERSIZE;
- }
-
- return TRUE;
-}
-
-BOOL IsFieldBlittable(FieldMarshaler* pFM)
-{
- if (pFM->GetNativeFieldFlags() & NATIVE_FIELD_SUBCATEGORY_MAYBE_BLITTABLE)
- {
- if (pFM->GetNativeFieldFlags() & NATIVE_FIELD_SUBCATEGORY_FLOAT)
- {
- return TRUE;
- }
- else if (pFM->GetNativeFieldFlags() & NATIVE_FIELD_SUBCATEGORY_INTEGER)
- {
- return TRUE;
- }
- else if (pFM->GetNativeFieldFlags() & NATIVE_FIELD_SUBCATEGORY_NESTED)
- {
- FieldMarshaler_NestedType *pNestedFM = (FieldMarshaler_NestedType*)pFM;
-
- if (pNestedFM->GetNestedNativeMethodTable()->IsBlittable())
- {
- return TRUE;
- }
- }
- }
- return FALSE;
-}
-
-#ifdef _DEBUG
-BOOL IsFixedBuffer(mdFieldDef field, IMDInternalImport *pInternalImport)
-{
- HRESULT hr = pInternalImport->GetCustomAttributeByName(field, g_FixedBufferAttribute, NULL, NULL);
-
- return hr == S_OK ? TRUE : FALSE;
-}
#endif
-
-#ifndef CROSSGEN_COMPILE
-
-//=======================================================================
-// For each reference-typed FieldMarshaler field, marshals the current CLR value
-// to a new native instance and stores it in the fixed portion of the FieldMarshaler.
-//
-// This function does not attempt to delete the native value that it overwrites.
-//
-// If there is a SafeHandle field, ppCleanupWorkListOnStack must be non-null, otherwise
-// InvalidOperationException is thrown.
-//=======================================================================
-VOID LayoutUpdateNative(LPVOID *ppProtectedManagedData, SIZE_T offsetbias, MethodTable *pMT, BYTE* pNativeData, OBJECTREF *ppCleanupWorkListOnStack)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(CheckPointer(pMT));
- }
- CONTRACTL_END;
-
- FieldMarshaler* pFM = pMT->GetLayoutInfo()->GetFieldMarshalers();
- UINT numReferenceFields = pMT->GetLayoutInfo()->GetNumCTMFields();
-
- OBJECTREF pCLRValue = NULL;
- LPVOID scalar = NULL;
-
- GCPROTECT_BEGIN(pCLRValue)
- GCPROTECT_BEGININTERIOR(scalar)
- {
- g_IBCLogger.LogFieldMarshalersReadAccess(pMT);
-
- while (numReferenceFields--)
- {
- pFM->Restore();
-
- DWORD internalOffset = pFM->GetFieldDesc()->GetOffset();
-
- if (pFM->IsScalarMarshaler())
- {
- scalar = (LPVOID)(internalOffset + offsetbias + (BYTE*)(*ppProtectedManagedData));
- // Note this will throw for FieldMarshaler_Illegal
- pFM->ScalarUpdateNative(scalar, pNativeData + pFM->GetExternalOffset() );
-
- }
- else if (pFM->IsNestedValueClassMarshaler())
- {
- pFM->NestedValueClassUpdateNative((const VOID **)ppProtectedManagedData, internalOffset + offsetbias, pNativeData + pFM->GetExternalOffset(),
- ppCleanupWorkListOnStack);
- }
- else
- {
- pCLRValue = *(OBJECTREF*)(internalOffset + offsetbias + (BYTE*)(*ppProtectedManagedData));
- pFM->UpdateNative(&pCLRValue, pNativeData + pFM->GetExternalOffset(), ppCleanupWorkListOnStack);
- SetObjectReference( (OBJECTREF*) (internalOffset + offsetbias + (BYTE*)(*ppProtectedManagedData)), pCLRValue);
- }
-
- // The cleanup work list is not used to clean up the native contents. It is used
- // to handle cleanup of any additional resources the FieldMarshalers allocate.
-
- ((BYTE*&)pFM) += MAXFIELDMARSHALERSIZE;
- }
- }
- GCPROTECT_END();
- GCPROTECT_END();
-}
-
-VOID FmtClassUpdateNative(OBJECTREF *ppProtectedManagedData, BYTE *pNativeData, OBJECTREF *ppCleanupWorkListOnStack)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(CheckPointer(ppProtectedManagedData));
- }
- CONTRACTL_END;
-
- MethodTable *pMT = (*ppProtectedManagedData)->GetMethodTable();
- _ASSERTE(pMT->IsBlittable() || pMT->HasLayout());
- UINT32 cbsize = pMT->GetNativeSize();
-
- if (pMT->IsBlittable())
- {
- memcpyNoGCRefs(pNativeData, (*ppProtectedManagedData)->GetData(), cbsize);
- }
- else
- {
- // This allows us to do a partial LayoutDestroyNative in the case of
- // a marshaling error on one of the fields.
- FillMemory(pNativeData, cbsize, 0);
- NativeLayoutDestroyer nld(pNativeData, pMT, cbsize);
-
- LayoutUpdateNative( (VOID**)ppProtectedManagedData,
- Object::GetOffsetOfFirstField(),
- pMT,
- pNativeData,
- ppCleanupWorkListOnStack);
-
- nld.SuppressRelease();
- }
-
-}
-
-
-VOID FmtClassUpdateCLR(OBJECTREF *ppProtectedManagedData, BYTE *pNativeData)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- }
- CONTRACTL_END;
-
- MethodTable *pMT = (*ppProtectedManagedData)->GetMethodTable();
- _ASSERTE(pMT->IsBlittable() || pMT->HasLayout());
- UINT32 cbsize = pMT->GetNativeSize();
-
- if (pMT->IsBlittable())
- {
- memcpyNoGCRefs((*ppProtectedManagedData)->GetData(), pNativeData, cbsize);
- }
- else
- {
- LayoutUpdateCLR((VOID**)ppProtectedManagedData,
- Object::GetOffsetOfFirstField(),
- pMT,
- (BYTE*)pNativeData
- );
- }
-}
-
-
-
-//=======================================================================
-// For each reference-typed FieldMarshaler field, marshals the current CLR value
-// to a new CLR instance and stores it in the GC portion of the FieldMarshaler.
-//
-// If fDeleteNativeCopies is true, it will also destroy the native version.
-//
-// NOTE: To avoid error-path leaks, this function attempts to destroy
-// all of the native fields even if one or more of the conversions fail.
-//=======================================================================
-VOID LayoutUpdateCLR(LPVOID *ppProtectedManagedData, SIZE_T offsetbias, MethodTable *pMT, BYTE *pNativeData)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(CheckPointer(pMT));
- }
- CONTRACTL_END;
-
- // Don't try to destroy/free native the structure on exception, we may not own it. If we do own it and
- // are supposed to destroy/free it, we do it upstack (e.g. in a helper called from the marshaling stub).
-
- FieldMarshaler* pFM = pMT->GetLayoutInfo()->GetFieldMarshalers();
- UINT numReferenceFields = pMT->GetLayoutInfo()->GetNumCTMFields();
-
- struct _gc
- {
- OBJECTREF pCLRValue;
- OBJECTREF pOldCLRValue;
- } gc;
-
- gc.pCLRValue = NULL;
- gc.pOldCLRValue = NULL;
- LPVOID scalar = NULL;
-
- GCPROTECT_BEGIN(gc)
- GCPROTECT_BEGININTERIOR(scalar)
- {
- g_IBCLogger.LogFieldMarshalersReadAccess(pMT);
-
- while (numReferenceFields--)
- {
- pFM->Restore();
-
- DWORD internalOffset = pFM->GetFieldDesc()->GetOffset();
-
- if (pFM->IsScalarMarshaler())
- {
- scalar = (LPVOID)(internalOffset + offsetbias + (BYTE*)(*ppProtectedManagedData));
- // Note this will throw for FieldMarshaler_Illegal
- pFM->ScalarUpdateCLR( pNativeData + pFM->GetExternalOffset(), scalar);
- }
- else if (pFM->IsNestedValueClassMarshaler())
- {
- pFM->NestedValueClassUpdateCLR(pNativeData + pFM->GetExternalOffset(), ppProtectedManagedData, internalOffset + offsetbias);
- }
- else
- {
- gc.pOldCLRValue = *(OBJECTREF*)(internalOffset + offsetbias + (BYTE*)(*ppProtectedManagedData));
- pFM->UpdateCLR( pNativeData + pFM->GetExternalOffset(), &gc.pCLRValue, &gc.pOldCLRValue );
- SetObjectReference( (OBJECTREF*) (internalOffset + offsetbias + (BYTE*)(*ppProtectedManagedData)), gc.pCLRValue );
- }
-
- ((BYTE*&)pFM) += MAXFIELDMARSHALERSIZE;
- }
- }
- GCPROTECT_END();
- GCPROTECT_END();
-}
-
-
-VOID LayoutDestroyNative(LPVOID pNative, MethodTable *pMT)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_TRIGGERS;
- MODE_ANY;
- PRECONDITION(CheckPointer(pMT));
- }
- CONTRACTL_END;
-
- FieldMarshaler *pFM = pMT->GetLayoutInfo()->GetFieldMarshalers();
- UINT numReferenceFields = pMT->GetLayoutInfo()->GetNumCTMFields();
- BYTE *pNativeData = (BYTE*)pNative;
-
- while (numReferenceFields--)
- {
- pFM->DestroyNative( pNativeData + pFM->GetExternalOffset() );
- ((BYTE*&)pFM) += MAXFIELDMARSHALERSIZE;
- }
-}
-
-VOID FmtClassDestroyNative(LPVOID pNative, MethodTable *pMT)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_TRIGGERS;
- MODE_ANY;
- PRECONDITION(CheckPointer(pMT));
- }
- CONTRACTL_END;
-
- if (pNative)
- {
- if (!(pMT->IsBlittable()))
- {
- _ASSERTE(pMT->HasLayout());
- LayoutDestroyNative(pNative, pMT);
- }
- }
-}
-
-VOID FmtValueTypeUpdateNative(LPVOID pProtectedManagedData, MethodTable *pMT, BYTE *pNativeData, OBJECTREF *ppCleanupWorkListOnStack)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(CheckPointer(pMT));
- }
- CONTRACTL_END;
-
- _ASSERTE(pMT->IsValueType() && (pMT->IsBlittable() || pMT->HasLayout()));
- UINT32 cbsize = pMT->GetNativeSize();
-
- if (pMT->IsBlittable())
- {
- memcpyNoGCRefs(pNativeData, pProtectedManagedData, cbsize);
- }
- else
- {
- // This allows us to do a partial LayoutDestroyNative in the case of
- // a marshaling error on one of the fields.
- FillMemory(pNativeData, cbsize, 0);
-
- NativeLayoutDestroyer nld(pNativeData, pMT, cbsize);
-
- LayoutUpdateNative( (VOID**)pProtectedManagedData,
- 0,
- pMT,
- pNativeData,
- ppCleanupWorkListOnStack);
-
- nld.SuppressRelease();
- }
-}
-
-VOID FmtValueTypeUpdateCLR(LPVOID pProtectedManagedData, MethodTable *pMT, BYTE *pNativeData)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(CheckPointer(pMT));
- }
- CONTRACTL_END;
-
- _ASSERTE(pMT->IsValueType() && (pMT->IsBlittable() || pMT->HasLayout()));
- UINT32 cbsize = pMT->GetNativeSize();
-
- if (pMT->IsBlittable())
- {
- memcpyNoGCRefs(pProtectedManagedData, pNativeData, cbsize);
- }
- else
- {
- LayoutUpdateCLR((VOID**)pProtectedManagedData,
- 0,
- pMT,
- (BYTE*)pNativeData);
- }
-}
-
-//=======================================================================
-// BSTR <--> System.String
-// See FieldMarshaler for details.
-//=======================================================================
-VOID FieldMarshaler_BSTR::UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_COOPERATIVE;
- INJECT_FAULT(COMPlusThrowOM());
- PRECONDITION(CheckPointer(pNativeValue));
- }
- CONTRACTL_END;
-
- STRINGREF pString;
- *((OBJECTREF*)&pString) = *pCLRValue;
-
- if (pString == NULL)
- MAYBE_UNALIGNED_WRITE(pNativeValue, _PTR, NULL);
- else
- {
- BSTR pBSTR = SysAllocStringLen(pString->GetBuffer(), pString->GetStringLength());
- if (!pBSTR)
- COMPlusThrowOM();
-
- MAYBE_UNALIGNED_WRITE(pNativeValue, _PTR, pBSTR);
- }
-}
-
-
-//=======================================================================
-// BSTR <--> System.String
-// See FieldMarshaler for details.
-//=======================================================================
-VOID FieldMarshaler_BSTR::UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const
-{
- STATIC_CONTRACT_THROWS;
- STATIC_CONTRACT_GC_TRIGGERS;
- STATIC_CONTRACT_MODE_COOPERATIVE;
-
- _ASSERTE(NULL != pNativeValue);
- _ASSERTE(NULL != ppProtectedCLRValue);
-
- STRINGREF pString;
- BSTR pBSTR = (BSTR)MAYBE_UNALIGNED_READ(pNativeValue, _PTR);
-
- if (!pBSTR)
- pString = NULL;
- else
- {
- struct Param : CallOutFilterParam {
- int length;
- BSTR pBSTR;
- }; Param param;
-
- param.OneShot = TRUE;
- param.length = 0;
- param.pBSTR = pBSTR;
-
- PAL_TRY(Param *, pParam, ¶m)
- {
- pParam->length = SysStringLen(pParam->pBSTR);
- }
- PAL_EXCEPT_FILTER(CallOutFilter)
- {
- _ASSERTE(!"CallOutFilter returned EXECUTE_HANDLER.");
- }
- PAL_ENDTRY;
-
- pString = StringObject::NewString(pBSTR, param.length);
- }
-
- *((STRINGREF*)ppProtectedCLRValue) = pString;
-}
-
-
-//=======================================================================
-// BSTR <--> System.String
-// See FieldMarshaler for details.
-//=======================================================================
-VOID FieldMarshaler_BSTR::DestroyNativeImpl(LPVOID pNativeValue) const
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(CheckPointer(pNativeValue));
- }
- CONTRACTL_END;
-
- BSTR pBSTR = (BSTR)MAYBE_UNALIGNED_READ(pNativeValue, _PTR);
- MAYBE_UNALIGNED_WRITE(pNativeValue, _PTR, NULL);
-
- if (pBSTR)
- {
- // BSTR has been created, Delay load will not fail.
- CONTRACT_VIOLATION(ThrowsViolation);
- SysFreeString(pBSTR);
- }
-}
-
-#ifdef FEATURE_COMINTEROP
-//===========================================================================================
-// Windows.Foundation.IReference'1<-- System.Nullable'1
-//
-VOID FieldMarshaler_Nullable::ScalarUpdateNativeImpl(LPVOID pCLR, LPVOID pNative) const
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- INJECT_FAULT(COMPlusThrowOM());
- PRECONDITION(CheckPointer(pNative));
- PRECONDITION(CheckPointer(pCLR));
- }
- CONTRACTL_END;
-
- IUnknown *pUnk = NULL;
-
- // ConvertToNative<T>(ref Nullable<T> pManaged) where T : struct
- MethodDescCallSite convertToNative(GetMethodDescForGenericInstantiation(MscorlibBinder::GetMethod(METHOD__NULLABLEMARSHALER__CONVERT_TO_NATIVE)));
- ARG_SLOT args[] =
- {
- PtrToArgSlot(pCLR)
- };
-
- pUnk = (IUnknown*) convertToNative.Call_RetLPVOID(args);
-
- MAYBE_UNALIGNED_WRITE(pNative, _PTR, pUnk);
-}
-
-//===========================================================================================
-// Windows.Foundation.IReference'1--> System.Nullable'1
-//
-VOID FieldMarshaler_Nullable::ScalarUpdateCLRImpl(const VOID *pNative, LPVOID pCLR) const
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(CheckPointer(pNative));
- PRECONDITION(CheckPointer(pCLR));
- }
- CONTRACTL_END;
-
- IUnknown *pUnk = (IUnknown*)MAYBE_UNALIGNED_READ(pNative, _PTR);
-
- MethodDescCallSite convertToManaged(GetMethodDescForGenericInstantiation(MscorlibBinder::GetMethod(METHOD__NULLABLEMARSHALER__CONVERT_TO_MANAGED_RET_VOID)));
-
- ARG_SLOT args[] =
- {
- PtrToArgSlot(pUnk),
- PtrToArgSlot(pCLR)
- };
-
- //ConvertToManaged<T>(Intptr pNative, ref Nullable<T> retObj) where T : struct;
- convertToManaged.Call(args);
-}
-
-//===========================================================================================
-// Windows.Foundation.IReference'1<--> System.Nullable'1
-//
-VOID FieldMarshaler_Nullable::DestroyNativeImpl(const VOID* pNative) const
-{
- CONTRACTL
- {
- NOTHROW;
- GC_TRIGGERS;
- MODE_ANY;
- PRECONDITION(CheckPointer(pNative));
- }
- CONTRACTL_END;
-
- IUnknown *pUnk = (IUnknown*)MAYBE_UNALIGNED_READ(pNative, _PTR);
- MAYBE_UNALIGNED_WRITE(pNative, _PTR, NULL);
-
- if (pUnk != NULL)
- {
- ULONG cbRef = SafeRelease(pUnk);
- LogInteropRelease(pUnk, cbRef, "Field marshaler destroy native");
- }
-}
-
-//=======================================================================
-// HSTRING <--> System.String
-// See FieldMarshaler for details.
-//=======================================================================
-VOID FieldMarshaler_HSTRING::UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(CheckPointer(pCLRValue));
- PRECONDITION(CheckPointer(pNativeValue));
- }
- CONTRACTL_END;
-
- if (!WinRTSupported())
- {
- COMPlusThrow(kPlatformNotSupportedException, W("PlatformNotSupported_WinRT"));
- }
-
- STRINGREF stringref = (STRINGREF)(*pCLRValue);
-
- if (stringref == NULL)
- {
- DefineFullyQualifiedNameForClassW();
- StackSString ssFieldName(SString::Utf8, GetFieldDesc()->GetName());
-
- SString errorString;
- errorString.LoadResource(CCompRC::Error, IDS_EE_BADMARSHALFIELD_NULL_HSTRING);
-
- COMPlusThrow(kMarshalDirectiveException,
- IDS_EE_BADMARSHALFIELD_ERROR_MSG,
- GetFullyQualifiedNameForClassW(GetFieldDesc()->GetEnclosingMethodTable()),
- ssFieldName.GetUnicode(),
- errorString.GetUnicode());
- }
-
- HSTRING hstring;
- IfFailThrow(WindowsCreateString(stringref->GetBuffer(), stringref->GetStringLength(), &hstring));
-
- MAYBE_UNALIGNED_WRITE(pNativeValue, _PTR, hstring);
-}
-
-//=======================================================================
-// HSTRING <--> System.String
-// See FieldMarshaler for details.
-//=======================================================================
-VOID FieldMarshaler_HSTRING::UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(CheckPointer(pNativeValue));
- PRECONDITION(CheckPointer(ppProtectedCLRValue));
- }
- CONTRACTL_END;
-
- if (!WinRTSupported())
- {
- COMPlusThrow(kPlatformNotSupportedException, W("PlatformNotSupported_WinRT"));
- }
-
- // NULL HSTRINGS are equivilent to empty strings
- UINT32 cchString = 0;
- LPCWSTR pwszString = W("");
-
- HSTRING hstring = (HSTRING)MAYBE_UNALIGNED_READ(pNativeValue, _PTR);
- if (hstring != NULL)
- {
- pwszString = WindowsGetStringRawBuffer(hstring, &cchString);
- }
-
- STRINGREF stringref = StringObject::NewString(pwszString, cchString);
- *((STRINGREF *)ppProtectedCLRValue) = stringref;
-}
-
-//=======================================================================
-// HSTRING <--> System.String
-// See FieldMarshaler for details.
-//=======================================================================
-VOID FieldMarshaler_HSTRING::DestroyNativeImpl(LPVOID pNativeValue) const
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(CheckPointer(pNativeValue));
- }
- CONTRACTL_END;
-
- HSTRING hstring = (HSTRING)MAYBE_UNALIGNED_READ(pNativeValue, _PTR);
- MAYBE_UNALIGNED_WRITE(pNativeValue, _PTR, NULL);
-
- if (hstring != NULL)
- {
- // We need this for code:System.Runtime.InteropServices.Marshal.DestroyStructure (user can explicitly call it)
- if (WinRTSupported())
- {
- // If WinRT is supported we've already loaded combase.dll, which means
- // this delay load will succeed
- CONTRACT_VIOLATION(ThrowsViolation);
- WindowsDeleteString(hstring);
- }
- }
-}
-
-//=======================================================================================
-// Windows.UI.Xaml.Interop.TypeName <--> System.Type
-//
-VOID FieldMarshaler_SystemType::UpdateNativeImpl(OBJECTREF * pCLRValue, LPVOID pNativeValue, OBJECTREF * ppCleanupWorkListOnStack) const
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(CheckPointer(pCLRValue));
- PRECONDITION(CheckPointer(pNativeValue));
- }
- CONTRACTL_END;
-
- // ConvertToNative(System.Type managedType, TypeName *pTypeName)
- MethodDescCallSite convertToNative(METHOD__SYSTEMTYPEMARSHALER__CONVERT_TO_NATIVE);
- ARG_SLOT args[] =
- {
- ObjToArgSlot(*pCLRValue),
- PtrToArgSlot(pNativeValue)
- };
- convertToNative.Call(args);
-}
-
-//=======================================================================================
-// Windows.UI.Xaml.Interop.TypeName <--> System.Type
-//
-VOID FieldMarshaler_SystemType::UpdateCLRImpl(const VOID * pNativeValue, OBJECTREF * ppProtectedCLRValue, OBJECTREF * ppProtectedOldCLRValue) const
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(CheckPointer(pNativeValue));
- PRECONDITION(CheckPointer(ppProtectedCLRValue));
- }
- CONTRACTL_END;
-
- // ConvertToManaged(TypeName *pTypeName, out System.Type)
- MethodDescCallSite convertToManaged(METHOD__SYSTEMTYPEMARSHALER__CONVERT_TO_MANAGED);
- ARG_SLOT args[] =
- {
- PtrToArgSlot(pNativeValue),
- PtrToArgSlot(ppProtectedCLRValue)
- };
-
- convertToManaged.Call(args);
-}
-
-//=======================================================================================
-// Windows.UI.Xaml.Interop.TypeName <--> System.Type
-// Clear the HSTRING field
-//
-VOID FieldMarshaler_SystemType::DestroyNativeImpl(LPVOID pNativeValue) const
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(CheckPointer(pNativeValue));
- PRECONDITION(WinRTSupported());
- }
- CONTRACTL_END;
-
- //
- // Call WindowsDeleteString instead of SystemTypeMarshaler.ClearNative
- // because WindowsDeleteString does not throw and is much faster
- //
- size_t offset = offsetof(TypeNameNative, typeName);
- HSTRING hstring = (HSTRING)MAYBE_UNALIGNED_READ((LPBYTE) pNativeValue + offset , _PTR);
- MAYBE_UNALIGNED_WRITE((LPBYTE) pNativeValue + offset, _PTR, NULL);
-
- if (hstring != NULL)
- {
- // Note: we've already loaded combase.dll, which means this delay load will succeed
- CONTRACT_VIOLATION(ThrowsViolation);
- WindowsDeleteString(hstring);
- }
-}
-
-//=======================================================================================
-// Windows.Foundation.HResult <--> System.Exception
-// Note: The WinRT struct has exactly 1 field, Value (an HRESULT)
-//
-VOID FieldMarshaler_Exception::UpdateNativeImpl(OBJECTREF * pCLRValue, LPVOID pNativeValue, OBJECTREF * ppCleanupWorkListOnStack) const
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(CheckPointer(pCLRValue));
- PRECONDITION(CheckPointer(pNativeValue));
- }
- CONTRACTL_END;
-
- // int ConvertToNative(Exception ex)
- MethodDescCallSite convertToNative(METHOD__HRESULTEXCEPTIONMARSHALER__CONVERT_TO_NATIVE);
- ARG_SLOT args[] =
- {
- ObjToArgSlot(*pCLRValue)
- };
- int iReturnedValue = convertToNative.Call_RetI4(args);
- MAYBE_UNALIGNED_WRITE(pNativeValue, 32, iReturnedValue);
-}
-
-//=======================================================================================
-// Windows.Foundation.HResult <--> System.Exception
-// Note: The WinRT struct has exactly 1 field, Value (an HRESULT)
-//
-VOID FieldMarshaler_Exception::UpdateCLRImpl(const VOID * pNativeValue, OBJECTREF * ppProtectedCLRValue, OBJECTREF * ppProtectedOldCLRValue) const
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(CheckPointer(pNativeValue));
- PRECONDITION(CheckPointer(ppProtectedCLRValue));
- }
- CONTRACTL_END;
-
- // Exception ConvertToManaged(int hr)
- MethodDescCallSite convertToManaged(METHOD__HRESULTEXCEPTIONMARSHALER__CONVERT_TO_MANAGED);
- ARG_SLOT args[] =
- {
- (ARG_SLOT)MAYBE_UNALIGNED_READ(pNativeValue, 32)
- };
- *ppProtectedCLRValue = convertToManaged.Call_RetOBJECTREF(args);
-}
-
-#endif // FEATURE_COMINTEROP
-
-
-//=======================================================================
-// Nested structure conversion
-// See FieldMarshaler for details.
-//=======================================================================
-VOID FieldMarshaler_NestedLayoutClass::UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- INJECT_FAULT(COMPlusThrowOM());
- PRECONDITION(CheckPointer(pNativeValue));
- }
- CONTRACTL_END;
-
- UINT32 cbNativeSize = GetMethodTable()->GetNativeSize();
-
- if (*pCLRValue == NULL)
- {
- ZeroMemoryInGCHeap(pNativeValue, cbNativeSize);
- }
- else
- {
- LayoutUpdateNative((LPVOID*)pCLRValue, Object::GetOffsetOfFirstField(),
- GetMethodTable(), (BYTE*)pNativeValue, ppCleanupWorkListOnStack);
- }
-
-}
-
-
-//=======================================================================
-// Nested structure conversion
-// See FieldMarshaler for details.
-//=======================================================================
-VOID FieldMarshaler_NestedLayoutClass::UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- INJECT_FAULT(COMPlusThrowOM());
- PRECONDITION(CheckPointer(pNativeValue));
- PRECONDITION(CheckPointer(ppProtectedCLRValue));
- }
- CONTRACTL_END;
-
- *ppProtectedCLRValue = GetMethodTable()->Allocate();
-
- LayoutUpdateCLR( (LPVOID*)ppProtectedCLRValue,
- Object::GetOffsetOfFirstField(),
- GetMethodTable(),
- (BYTE *)pNativeValue);
-
-}
-
-
-//=======================================================================
-// Nested structure conversion
-// See FieldMarshaler for details.
-//=======================================================================
-VOID FieldMarshaler_NestedLayoutClass::DestroyNativeImpl(LPVOID pNativeValue) const
-{
- CONTRACTL
- {
- NOTHROW;
- GC_TRIGGERS;
- MODE_ANY;
- PRECONDITION(CheckPointer(pNativeValue));
- }
- CONTRACTL_END;
-
- LayoutDestroyNative(pNativeValue, GetMethodTable());
-}
-
-#endif // CROSSGEN_COMPILE
-
-
-//=======================================================================
-// Nested structure conversion
-// See FieldMarshaler for details.
-//=======================================================================
-UINT32 FieldMarshaler_NestedLayoutClass::NativeSizeImpl() const
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- return GetMethodTable()->GetLayoutInfo()->GetNativeSize();
-}
-
-//=======================================================================
-// Nested structure conversion
-// See FieldMarshaler for details.
-//=======================================================================
-UINT32 FieldMarshaler_NestedLayoutClass::AlignmentRequirementImpl() const
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- return GetMethodTable()->GetLayoutInfo()->GetLargestAlignmentRequirementOfAllMembers();
-}
-
-#if FEATURE_COMINTEROP
-MethodDesc* FieldMarshaler_Nullable::GetMethodDescForGenericInstantiation(MethodDesc* pMD) const
-{
- MethodDesc *pMethodInstantiation;
-
- pMethodInstantiation = MethodDesc::FindOrCreateAssociatedMethodDesc(
- pMD,
- pMD->GetMethodTable(),
- FALSE,
- GetMethodTable()->GetInstantiation(),
- FALSE,
- TRUE);
-
- _ASSERTE(pMethodInstantiation != NULL);
-
- return pMethodInstantiation;
-}
-#endif //FEATURE_COMINTEROP
-
-#ifndef CROSSGEN_COMPILE
-
-//=======================================================================
-// Nested structure conversion
-// See FieldMarshaler for details.
-//=======================================================================
-VOID FieldMarshaler_NestedValueClass::NestedValueClassUpdateNativeImpl(const VOID **ppProtectedCLR, SIZE_T startoffset, LPVOID pNative, OBJECTREF *ppCleanupWorkListOnStack) const
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- INJECT_FAULT(COMPlusThrowOM());
- PRECONDITION(CheckPointer(ppProtectedCLR));
- PRECONDITION(CheckPointer(pNative));
- }
- CONTRACTL_END;
-
- MethodTable* pMT = GetMethodTable();
-
- // would be better to detect this at class load time (that have a nested value
- // class with no layout) but don't have a way to know
- if (!pMT->GetLayoutInfo())
- COMPlusThrow(kArgumentException, IDS_NOLAYOUT_IN_EMBEDDED_VALUECLASS);
-
- if (pMT->IsBlittable())
- {
- memcpyNoGCRefs(pNative, (BYTE*)(*ppProtectedCLR) + startoffset, pMT->GetNativeSize());
- }
- else
- {
-#ifdef _DEBUG
- _ASSERTE_MSG(!IsFixedBuffer(), "Cannot correctly marshal fixed buffers of non-blittable types");
-#endif
- LayoutUpdateNative((LPVOID*)ppProtectedCLR, startoffset, pMT, (BYTE*)pNative, ppCleanupWorkListOnStack);
- }
-}
-
-
-//=======================================================================
-// Nested structure conversion
-// See FieldMarshaler for details.
-//=======================================================================
-VOID FieldMarshaler_NestedValueClass::NestedValueClassUpdateCLRImpl(const VOID *pNative, LPVOID *ppProtectedCLR, SIZE_T startoffset) const
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(CheckPointer(pNative));
- PRECONDITION(CheckPointer(ppProtectedCLR));
- }
- CONTRACTL_END;
-
- MethodTable* pMT = GetMethodTable();
-
- // would be better to detect this at class load time (that have a nested value
- // class with no layout) but don't have a way to know
- if (!pMT->GetLayoutInfo())
- COMPlusThrow(kArgumentException, IDS_NOLAYOUT_IN_EMBEDDED_VALUECLASS);
-
- if (pMT->IsBlittable())
- {
- memcpyNoGCRefs((BYTE*)(*ppProtectedCLR) + startoffset, pNative, pMT->GetNativeSize());
- }
- else
- {
-#ifdef _DEBUG
- _ASSERTE_MSG(!IsFixedBuffer(), "Cannot correctly marshal fixed buffers of non-blittable types");
-#endif
- LayoutUpdateCLR((LPVOID*)ppProtectedCLR,
- startoffset,
- pMT,
- (BYTE *)pNative);
- }
-}
-
-
-//=======================================================================
-// Nested structure conversion
-// See FieldMarshaler for details.
-//=======================================================================
-VOID FieldMarshaler_NestedValueClass::DestroyNativeImpl(LPVOID pNativeValue) const
-{
- CONTRACTL
- {
- NOTHROW;
- GC_TRIGGERS;
- MODE_ANY;
- PRECONDITION(CheckPointer(pNativeValue));
- }
- CONTRACTL_END;
-
- MethodTable* pMT = GetMethodTable();
-
- if (!pMT->IsBlittable())
- {
- LayoutDestroyNative(pNativeValue, pMT);
- }
-}
-
-#endif // CROSSGEN_COMPILE
-
-
-//=======================================================================
-// Nested structure conversion
-// See FieldMarshaler for details.
-//=======================================================================
-UINT32 FieldMarshaler_NestedValueClass::NativeSizeImpl() const
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- // this can't be marshalled as native type if no layout, so we allow the
- // native size info to be created if available, but the size will only
- // be valid for native, not unions. Marshaller will throw exception if
- // try to marshall a value class with no layout
- if (GetMethodTable()->HasLayout())
- return GetMethodTable()->GetLayoutInfo()->GetNativeSize();
-
- return 0;
-}
-
-
-//=======================================================================
-// Nested structure conversion
-// See FieldMarshaler for details.
-//=======================================================================
-UINT32 FieldMarshaler_NestedValueClass::AlignmentRequirementImpl() const
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- // this can't be marshalled as native type if no layout, so we allow the
- // native size info to be created if available, but the alignment will only
- // be valid for native, not unions. Marshaller will throw exception if
- // try to marshall a value class with no layout
- if (GetMethodTable()->HasLayout())
- {
- UINT32 uAlignmentReq = GetMethodTable()->GetLayoutInfo()->GetLargestAlignmentRequirementOfAllMembers();
- return uAlignmentReq;
- }
- return 1;
-}
-
-
-#ifndef CROSSGEN_COMPILE
-
-//=======================================================================
-// CoTask Uni <--> System.String
-// See FieldMarshaler for details.
-//=======================================================================
-VOID FieldMarshaler_StringUni::UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_COOPERATIVE;
- INJECT_FAULT(COMPlusThrowOM());
- PRECONDITION(CheckPointer(pNativeValue));
- }
- CONTRACTL_END;
-
- STRINGREF pString;
- *((OBJECTREF*)&pString) = *pCLRValue;
-
- if (pString == NULL)
- {
- MAYBE_UNALIGNED_WRITE(pNativeValue, _PTR, NULL);
- }
- else
- {
- DWORD nc = pString->GetStringLength();
- if (nc > MAX_SIZE_FOR_INTEROP)
- COMPlusThrow(kMarshalDirectiveException, IDS_EE_STRING_TOOLONG);
-
- LPWSTR wsz = (LPWSTR)CoTaskMemAlloc( (nc + 1) * sizeof(WCHAR) );
- if (!wsz)
- COMPlusThrowOM();
-
- memcpyNoGCRefs(wsz, pString->GetBuffer(), nc*sizeof(WCHAR));
- wsz[nc] = W('\0');
- MAYBE_UNALIGNED_WRITE(pNativeValue, _PTR, wsz);
- }
-}
-
-
-//=======================================================================
-// CoTask Uni <--> System.String
-// See FieldMarshaler for details.
-//=======================================================================
-VOID FieldMarshaler_StringUni::UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(CheckPointer(pNativeValue));
- PRECONDITION(CheckPointer(ppProtectedCLRValue));
- }
- CONTRACTL_END;
-
- STRINGREF pString;
- LPCWSTR wsz = (LPCWSTR)MAYBE_UNALIGNED_READ(pNativeValue, _PTR);
-
- if (!wsz)
- pString = NULL;
- else
- {
- SIZE_T length = wcslen(wsz);
- if (length > MAX_SIZE_FOR_INTEROP)
- COMPlusThrow(kMarshalDirectiveException, IDS_EE_STRING_TOOLONG);
-
- pString = StringObject::NewString(wsz, (DWORD)length);
- }
-
- *((STRINGREF*)ppProtectedCLRValue) = pString;
-}
-
-
-//=======================================================================
-// CoTask Uni <--> System.String
-// See FieldMarshaler for details.
-//=======================================================================
-VOID FieldMarshaler_StringUni::DestroyNativeImpl(LPVOID pNativeValue) const
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(CheckPointer(pNativeValue));
- }
- CONTRACTL_END;
-
- LPWSTR wsz = (LPWSTR)MAYBE_UNALIGNED_READ(pNativeValue, _PTR);
- MAYBE_UNALIGNED_WRITE(pNativeValue, _PTR, NULL);
- if (wsz)
- CoTaskMemFree(wsz);
-}
-
-
-
-//=======================================================================
-// CoTask Ansi <--> System.String
-// See FieldMarshaler for details.
-//=======================================================================
-VOID FieldMarshaler_StringAnsi::UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- INJECT_FAULT(COMPlusThrowOM());
- PRECONDITION(CheckPointer(pNativeValue));
- }
- CONTRACTL_END;
-
- STRINGREF pString;
- *((OBJECTREF*)&pString) = *pCLRValue;
-
- if (pString == NULL)
- {
- MAYBE_UNALIGNED_WRITE(pNativeValue, _PTR, NULL);
- }
- else
- {
- DWORD nc = pString->GetStringLength();
- if (nc > MAX_SIZE_FOR_INTEROP)
- COMPlusThrow(kMarshalDirectiveException, IDS_EE_STRING_TOOLONG);
-
- LPSTR sz = (LPSTR)CoTaskMemAlloc( (nc + 1) * 2 /* 2 for MBCS */ );
- if (!sz)
- COMPlusThrowOM();
-
- int nbytes = InternalWideToAnsi(pString->GetBuffer(),
- nc,
- sz,
- nc*2,
- m_BestFitMap,
- m_ThrowOnUnmappableChar);
- sz[nbytes] = '\0';
-
- MAYBE_UNALIGNED_WRITE(pNativeValue, _PTR, sz);
- }
-}
-
-
-//=======================================================================
-// CoTask Ansi <--> System.String
-// See FieldMarshaler for details.
-//=======================================================================
-VOID FieldMarshaler_StringAnsi::UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- INJECT_FAULT(COMPlusThrowOM());
- PRECONDITION(CheckPointer(pNativeValue));
- PRECONDITION(CheckPointer(ppProtectedCLRValue));
- }
- CONTRACTL_END;
-
- STRINGREF pString = NULL;
- LPCSTR sz = (LPCSTR)MAYBE_UNALIGNED_READ(pNativeValue, _PTR);
- if (!sz)
- pString = NULL;
- else
- {
- MAKE_WIDEPTR_FROMANSI(wsztemp, sz);
- pString = StringObject::NewString(wsztemp, __lwsztemp - 1);
- }
-
- *((STRINGREF*)ppProtectedCLRValue) = pString;
-}
-
-
-//=======================================================================
-// CoTask Ansi <--> System.String
-// See FieldMarshaler for details.
-//=======================================================================
-VOID FieldMarshaler_StringAnsi::DestroyNativeImpl(LPVOID pNativeValue) const
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(CheckPointer(pNativeValue));
- }
- CONTRACTL_END;
-
- LPSTR sz = (LPSTR)MAYBE_UNALIGNED_READ(pNativeValue, _PTR);
- MAYBE_UNALIGNED_WRITE(pNativeValue, _PTR, NULL);
- if (sz)
- CoTaskMemFree(sz);
-}
-
-//=======================================================================
-// CoTask Utf8 <--> System.String
-// See FieldMarshaler for details.
-//=======================================================================
-VOID FieldMarshaler_StringUtf8::UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- INJECT_FAULT(COMPlusThrowOM());
- PRECONDITION(CheckPointer(pNativeValue));
- }
- CONTRACTL_END;
-
- STRINGREF pString = (STRINGREF)(*pCLRValue);
- if (pString == NULL)
- {
- MAYBE_UNALIGNED_WRITE(pNativeValue, _PTR, NULL);
- }
- else
- {
- DWORD nc = pString->GetStringLength();
- if (nc > MAX_SIZE_FOR_INTEROP)
- COMPlusThrow(kMarshalDirectiveException, IDS_EE_STRING_TOOLONG);
-
- // Characters would be # of characters + 1 in case left over high surrogate is ?
- // Max 3 bytes per char for basic multi-lingual plane.
- nc = (nc + 1) * MAX_UTF8_CHAR_SIZE;
- // +1 for '\0'
- LPUTF8 lpBuffer = (LPUTF8)CoTaskMemAlloc(nc + 1);
- if (!lpBuffer)
- {
- COMPlusThrowOM();
- }
-
- // UTF8Marshaler.ConvertToNative
- MethodDescCallSite convertToNative(METHOD__CUTF8MARSHALER__CONVERT_TO_NATIVE);
-
- ARG_SLOT args[] =
- {
- ((ARG_SLOT)(CLR_I4)0),
- ObjToArgSlot(*pCLRValue),
- PtrToArgSlot(lpBuffer)
- };
- convertToNative.Call(args);
- MAYBE_UNALIGNED_WRITE(pNativeValue, _PTR, lpBuffer);
- }
-}
-
-
-//=======================================================================
-// CoTask Utf8 <--> System.String
-// See FieldMarshaler for details.
-//=======================================================================
-VOID FieldMarshaler_StringUtf8::UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- INJECT_FAULT(COMPlusThrowOM());
- PRECONDITION(CheckPointer(pNativeValue));
- PRECONDITION(CheckPointer(ppProtectedCLRValue));
- }
- CONTRACTL_END;
-
- STRINGREF pString = NULL;
- LPCUTF8 sz = (LPCUTF8)MAYBE_UNALIGNED_READ(pNativeValue, _PTR);
- if (sz)
- {
- MethodDescCallSite convertToManaged(METHOD__CUTF8MARSHALER__CONVERT_TO_MANAGED);
- ARG_SLOT args[] =
- {
- PtrToArgSlot(sz),
- };
- pString = convertToManaged.Call_RetSTRINGREF(args);
- }
- *((STRINGREF*)ppProtectedCLRValue) = pString;
-}
-
-//=======================================================================
-// CoTask Utf8 <--> System.String
-// See FieldMarshaler for details.
-//=======================================================================
-VOID FieldMarshaler_StringUtf8::DestroyNativeImpl(LPVOID pNativeValue) const
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(CheckPointer(pNativeValue));
- }
- CONTRACTL_END;
-
- LPCUTF8 lpBuffer = (LPCUTF8)MAYBE_UNALIGNED_READ(pNativeValue, _PTR);
- MAYBE_UNALIGNED_WRITE(pNativeValue, _PTR, NULL);
- if (lpBuffer)
- CoTaskMemFree((LPVOID)lpBuffer);
-}
-
-//=======================================================================
-// FixedString <--> System.String
-// See FieldMarshaler for details.
-//=======================================================================
-VOID FieldMarshaler_FixedStringUni::UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_COOPERATIVE;
- PRECONDITION(CheckPointer(pNativeValue));
- }
- CONTRACTL_END;
-
- STRINGREF pString;
- *((OBJECTREF*)&pString) = *pCLRValue;
-
- if (pString == NULL)
- {
- MAYBE_UNALIGNED_WRITE(pNativeValue, 16, W('\0'));
- }
- else
- {
- DWORD nc = pString->GetStringLength();
- if (nc >= m_numchar)
- nc = m_numchar - 1;
-
- memcpyNoGCRefs(pNativeValue, pString->GetBuffer(), nc*sizeof(WCHAR));
- MAYBE_UNALIGNED_WRITE(&(((WCHAR*)pNativeValue)[nc]), 16, W('\0'));
- }
-
-}
-
-
-//=======================================================================
-// FixedString <--> System.String
-// See FieldMarshaler for details.
-//=======================================================================
-VOID FieldMarshaler_FixedStringUni::UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(CheckPointer(pNativeValue));
- PRECONDITION(CheckPointer(ppProtectedCLRValue));
- }
- CONTRACTL_END;
-
- STRINGREF pString;
- SIZE_T ncActual = wcsnlen((const WCHAR *)pNativeValue, m_numchar);
-
- if (!FitsIn<int>(ncActual))
- COMPlusThrowHR(COR_E_OVERFLOW);
-
- pString = StringObject::NewString((const WCHAR *)pNativeValue, (int)ncActual);
- *((STRINGREF*)ppProtectedCLRValue) = pString;
-}
-
-
-
-
-
-
-
-//=======================================================================
-// FixedString <--> System.String
-// See FieldMarshaler for details.
-//=======================================================================
-VOID FieldMarshaler_FixedStringAnsi::UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(CheckPointer(pNativeValue));
- }
- CONTRACTL_END;
-
- STRINGREF pString;
- *((OBJECTREF*)&pString) = *pCLRValue;
-
- if (pString == NULL)
- *((CHAR*)pNativeValue) = W('\0');
- else
- {
- DWORD nc = pString->GetStringLength();
- if (nc >= m_numchar)
- nc = m_numchar - 1;
-
- int cbwritten = InternalWideToAnsi(pString->GetBuffer(),
- nc,
- (CHAR*)pNativeValue,
- m_numchar,
- m_BestFitMap,
- m_ThrowOnUnmappableChar);
-
- // Handle the case where SizeConst == Number of bytes.For single byte chars
- // this will never be the case since nc >= m_numchar check will truncate the last
- // character, but for multibyte chars nc>= m_numchar check won't truncate since GetStringLength
- // gives number of characters but not the actual number of bytes. For such cases need to make
- // sure that we dont write one past the buffer.
- if (cbwritten == (int) m_numchar)
- --cbwritten;
-
- ((CHAR*)pNativeValue)[cbwritten] = '\0';
- }
-}
-
-
-//=======================================================================
-// FixedString <--> System.String
-// See FieldMarshaler for details.
-//=======================================================================
-VOID FieldMarshaler_FixedStringAnsi::UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- INJECT_FAULT(COMPlusThrowOM());
- PRECONDITION(CheckPointer(pNativeValue));
- PRECONDITION(CheckPointer(ppProtectedCLRValue));
-
- // should not have slipped past the metadata
- PRECONDITION(m_numchar != 0);
- }
- CONTRACTL_END;
-
- STRINGREF pString;
- if (m_numchar == 0)
- {
- // but if it does, better to throw an exception tardily rather than
- // allow a memory corrupt.
- COMPlusThrow(kMarshalDirectiveException);
- }
-
- UINT32 allocSize = m_numchar + 2;
- if (allocSize < m_numchar)
- ThrowOutOfMemory();
-
- LPSTR tempbuf = (LPSTR)(_alloca((size_t)allocSize));
- if (!tempbuf)
- ThrowOutOfMemory();
-
- memcpyNoGCRefs(tempbuf, pNativeValue, m_numchar);
- tempbuf[m_numchar-1] = '\0';
- tempbuf[m_numchar] = '\0';
- tempbuf[m_numchar+1] = '\0';
-
- allocSize = m_numchar * sizeof(WCHAR);
- if (allocSize < m_numchar)
- ThrowOutOfMemory();
-
- LPWSTR wsztemp = (LPWSTR)_alloca( (size_t)allocSize );
- int ncwritten = MultiByteToWideChar(CP_ACP,
- MB_PRECOMPOSED,
- tempbuf,
- -1, // # of CHAR's in inbuffer
- wsztemp,
- m_numchar // size (in WCHAR) of outbuffer
- );
-
- if (!ncwritten)
- {
- // intentionally not throwing for MB2WC failure. We don't always know
- // whether to expect a valid string in the buffer and we don't want
- // to throw exceptions randomly.
- ncwritten++;
- }
-
- pString = StringObject::NewString((const WCHAR *)wsztemp, ncwritten-1);
- *((STRINGREF*)ppProtectedCLRValue) = pString;
-}
-
-
-//=======================================================================
-// CHAR[] <--> char[]
-// See FieldMarshaler for details.
-//=======================================================================
-VOID FieldMarshaler_FixedCharArrayAnsi::UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- INJECT_FAULT(COMPlusThrowOM());
- PRECONDITION(CheckPointer(pNativeValue));
- }
- CONTRACTL_END;
-
- I2ARRAYREF pArray;
- *((OBJECTREF*)&pArray) = *pCLRValue;
-
- if (pArray == NULL)
- FillMemory(pNativeValue, m_numElems * sizeof(CHAR), 0);
- else
- {
- if (pArray->GetNumComponents() < m_numElems)
- COMPlusThrow(kArgumentException, IDS_WRONGSIZEARRAY_IN_NSTRUCT);
- else
- {
- InternalWideToAnsi((const WCHAR*) pArray->GetDataPtr(),
- m_numElems,
- (CHAR*)pNativeValue,
- m_numElems * sizeof(CHAR),
- m_BestFitMap,
- m_ThrowOnUnmappableChar);
- }
- }
-}
-
-
-//=======================================================================
-// CHAR[] <--> char[]
-// See FieldMarshaler for details.
-//=======================================================================
-VOID FieldMarshaler_FixedCharArrayAnsi::UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- INJECT_FAULT(COMPlusThrowOM());
- PRECONDITION(CheckPointer(pNativeValue));
- PRECONDITION(CheckPointer(ppProtectedCLRValue));
- }
- CONTRACTL_END;
-
- *ppProtectedCLRValue = AllocatePrimitiveArray(ELEMENT_TYPE_CHAR, m_numElems);
-
- MultiByteToWideChar(CP_ACP,
- MB_PRECOMPOSED,
- (const CHAR *)pNativeValue,
- m_numElems * sizeof(CHAR), // size, in bytes, of in buffer
- (WCHAR*) ((*((I2ARRAYREF*)ppProtectedCLRValue))->GetDirectPointerToNonObjectElements()),
- m_numElems); // size, in WCHAR's of outbuffer
-}
-
-#endif // CROSSGEN_COMPILE
-
-
-//=======================================================================
-// Embedded array
-// See FieldMarshaler for details.
-//=======================================================================
-FieldMarshaler_FixedArray::FieldMarshaler_FixedArray(Module *pModule, mdTypeDef cl, UINT32 numElems, VARTYPE vt, MethodTable* pElementMT)
-: m_numElems(numElems)
-, m_vt(vt)
-, m_BestFitMap(FALSE)
-, m_ThrowOnUnmappableChar(FALSE)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- PRECONDITION(CheckPointer(pElementMT));
- PRECONDITION(vt != VTHACK_ANSICHAR); // This must be handled by the FixedCharArrayAnsi marshaler.
- }
- CONTRACTL_END;
-
- // Only attempt to read the best fit mapping attribute if required to minimize
- // custom attribute accesses.
- if (vt == VT_LPSTR || vt == VT_RECORD)
- {
- BOOL BestFitMap = FALSE;
- BOOL ThrowOnUnmappableChar = FALSE;
- ReadBestFitCustomAttribute(pModule, cl, &BestFitMap, &ThrowOnUnmappableChar);
- m_BestFitMap = !!BestFitMap;
- m_ThrowOnUnmappableChar = !!ThrowOnUnmappableChar;
- }
-
- m_arrayType.SetValue(ClassLoader::LoadArrayTypeThrowing(TypeHandle(pElementMT),
- ELEMENT_TYPE_SZARRAY,
- 0,
- ClassLoader::LoadTypes,
- pElementMT->GetLoadLevel()));
-}
-
-
-#ifndef CROSSGEN_COMPILE
-
-//=======================================================================
-// Embedded array
-// See FieldMarshaler for details.
-//=======================================================================
-VOID FieldMarshaler_FixedArray::UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(CheckPointer(pNativeValue));
- }
- CONTRACTL_END;
-
- if (*pCLRValue == NULL)
- {
- FillMemory(pNativeValue, NativeSize(), 0);
- }
- else
- {
- // Make sure the size of the array is >= as specified in the MarshalAs attribute (via the SizeConst field).
- if ((*pCLRValue)->GetNumComponents() < m_numElems)
- COMPlusThrow(kArgumentException, IDS_WRONGSIZEARRAY_IN_NSTRUCT);
-
- // Marshal the contents from the managed array to the native array.
- const OleVariant::Marshaler *pMarshaler = OleVariant::GetMarshalerForVarType(m_vt, TRUE);
- if (pMarshaler == NULL || pMarshaler->ComToOleArray == NULL)
- {
- memcpyNoGCRefs(pNativeValue, (*(BASEARRAYREF*)pCLRValue)->GetDataPtr(), NativeSize());
- }
- else
- {
- MethodTable *pElementMT = m_arrayType.GetValue().AsArray()->GetArrayElementTypeHandle().GetMethodTable();
-
- // We never operate on an uninitialized native layout here, we have zero'ed it if needed.
- // Therefore fOleArrayIsValid is always TRUE.
- pMarshaler->ComToOleArray((BASEARRAYREF*)pCLRValue, pNativeValue, pElementMT, m_BestFitMap, m_ThrowOnUnmappableChar, TRUE, m_numElems);
- }
- }
-}
-
-
-//=======================================================================
-// Embedded array
-// See FieldMarshaler for details.
-//=======================================================================
-VOID FieldMarshaler_FixedArray::UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- INJECT_FAULT(COMPlusThrowOM());
- PRECONDITION(CheckPointer(pNativeValue));
- PRECONDITION(CheckPointer(ppProtectedCLRValue));
- }
- CONTRACTL_END;
-
- // Allocate the value class array.
- *ppProtectedCLRValue = AllocateSzArray(m_arrayType.GetValue(), (INT32)m_numElems);
-
- // Marshal the contents from the native array to the managed array.
- const OleVariant::Marshaler *pMarshaler = OleVariant::GetMarshalerForVarType(m_vt, TRUE);
- if (pMarshaler == NULL || pMarshaler->OleToComArray == NULL)
- {
- memcpyNoGCRefs((*(BASEARRAYREF*)ppProtectedCLRValue)->GetDataPtr(), pNativeValue, NativeSize());
- }
- else
- {
- MethodTable *pElementMT = m_arrayType.GetValue().AsArray()->GetArrayElementTypeHandle().GetMethodTable();
- pMarshaler->OleToComArray((VOID *)pNativeValue, (BASEARRAYREF*)ppProtectedCLRValue, pElementMT);
- }
-}
-
-//=======================================================================
-// Embedded array
-// See FieldMarshaler for details.
-//=======================================================================
-VOID FieldMarshaler_FixedArray::DestroyNativeImpl(LPVOID pNativeValue) const
-{
- CONTRACTL
- {
- NOTHROW;
- GC_TRIGGERS;
- MODE_ANY;
- INJECT_FAULT(COMPlusThrowOM());
- PRECONDITION(CheckPointer(pNativeValue));
- }
- CONTRACTL_END;
-
- const OleVariant::Marshaler *pMarshaler = OleVariant::GetMarshalerForVarType(m_vt, FALSE);
-
- if (pMarshaler != NULL && pMarshaler->ClearOleArray != NULL)
- {
- MethodTable *pElementMT = m_arrayType.GetValue().AsArray()->GetArrayElementTypeHandle().GetMethodTable();
- pMarshaler->ClearOleArray(pNativeValue, m_numElems, pElementMT);
- }
-}
-
-#endif // CROSSGEN_COMPILE
-
-
-//=======================================================================
-// Embedded array
-// See FieldMarshaler for details.
-//=======================================================================
-UINT32 FieldMarshaler_FixedArray::AlignmentRequirementImpl() const
-{
- WRAPPER_NO_CONTRACT;
-
- UINT32 alignment = 0;
- TypeHandle elementType = m_arrayType.GetValue().AsArray()->GetArrayElementTypeHandle();
-
- switch (m_vt)
- {
- case VT_DECIMAL:
- alignment = 8;
- break;
-
- case VT_VARIANT:
- alignment = 8;
- break;
-
- case VT_RECORD:
- alignment = elementType.GetMethodTable()->GetLayoutInfo()->GetLargestAlignmentRequirementOfAllMembers();
- break;
-
- default:
- alignment = OleVariant::GetElementSizeForVarType(m_vt, elementType.GetMethodTable());
- break;
- }
-
- return alignment;
-}
-
-#ifndef CROSSGEN_COMPILE
-
-#ifdef FEATURE_CLASSIC_COMINTEROP
-//=======================================================================
-// SafeArray
-// See FieldMarshaler for details.
-//=======================================================================
-VOID FieldMarshaler_SafeArray::UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(CheckPointer(pNativeValue));
- }
- CONTRACTL_END;
-
- BASEARRAYREF pArray;
- *((OBJECTREF*)&pArray) = *pCLRValue;
- if ((pArray == NULL) || (OBJECTREFToObject(pArray) == NULL))
- {
- FillMemory(pNativeValue, sizeof(LPSAFEARRAY*), 0);
- return;
- }
-
- LPSAFEARRAY* pSafeArray;
- pSafeArray = (LPSAFEARRAY*)pNativeValue;
-
- VARTYPE vt = m_vt;
- MethodTable* pMT = m_pMT.GetValueMaybeNull();
-
- GCPROTECT_BEGIN(pArray)
- {
- if (vt == VT_EMPTY)
- vt = OleVariant::GetElementVarTypeForArrayRef(pArray);
-
- if (!pMT)
- pMT = OleVariant::GetArrayElementTypeWrapperAware(&pArray).GetMethodTable();
-
- // OleVariant calls throw on error.
- *pSafeArray = OleVariant::CreateSafeArrayForArrayRef(&pArray, vt, pMT);
- OleVariant::MarshalSafeArrayForArrayRef(&pArray, *pSafeArray, vt, pMT);
- }
- GCPROTECT_END();
-}
-
-
-//=======================================================================
-// SafeArray
-// See FieldMarshaler for details.
-//=======================================================================
-VOID FieldMarshaler_SafeArray::UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- INJECT_FAULT(COMPlusThrowOM());
- PRECONDITION(CheckPointer(pNativeValue));
- PRECONDITION(CheckPointer(ppProtectedCLRValue));
- }
- CONTRACTL_END;
-
- LPSAFEARRAY* pSafeArray;
- pSafeArray = (LPSAFEARRAY*)pNativeValue;
-
- if ((pSafeArray == NULL) || (*pSafeArray == NULL))
- {
- *ppProtectedCLRValue = NULL;
- return;
- }
-
- VARTYPE vt = m_vt;
- MethodTable* pMT = m_pMT.GetValueMaybeNull();
-
- // If we have an empty vartype, get it from the safearray vartype
- if (vt == VT_EMPTY)
- {
- if (FAILED(ClrSafeArrayGetVartype(*pSafeArray, &vt)))
- COMPlusThrow(kArgumentException, IDS_EE_INVALID_SAFEARRAY);
- }
-
- // Get the method table if we need to.
- if ((vt == VT_RECORD) && (!pMT))
- pMT = OleVariant::GetElementTypeForRecordSafeArray(*pSafeArray).GetMethodTable();
-
- // If we have a single dimension safearray, it will be converted into a SZArray.
- // SZArray must have a lower bound of zero.
- LONG LowerBound = -1;
- UINT Dimensions = SafeArrayGetDim( (SAFEARRAY*)*pSafeArray );
-
- if (Dimensions == 1)
- {
- HRESULT hr = SafeArrayGetLBound((SAFEARRAY*)*pSafeArray, 1, &LowerBound);
- if ( FAILED(hr) || LowerBound != 0)
- COMPlusThrow(kSafeArrayRankMismatchException, IDS_EE_SAFEARRAYSZARRAYMISMATCH);
- }
-
- // OleVariant calls throw on error.
- *ppProtectedCLRValue = OleVariant::CreateArrayRefForSafeArray(*pSafeArray, vt, pMT);
- OleVariant::MarshalArrayRefForSafeArray(*pSafeArray, (BASEARRAYREF*)ppProtectedCLRValue, vt, pMT);
-}
-
-
-//=======================================================================
-// SafeArray
-// See FieldMarshaler for details.
-//=======================================================================
-VOID FieldMarshaler_SafeArray::DestroyNativeImpl(LPVOID pNativeValue) const
-{
- CONTRACTL
- {
- NOTHROW;
- GC_TRIGGERS;
- MODE_ANY;
- PRECONDITION(CheckPointer(pNativeValue));
- }
- CONTRACTL_END;
-
- HRESULT hr;
- GCX_PREEMP();
-
- LPSAFEARRAY psa = (LPSAFEARRAY)MAYBE_UNALIGNED_READ(pNativeValue, _PTR);
- MAYBE_UNALIGNED_WRITE(pNativeValue, _PTR, NULL);
-
- if (psa)
- {
- _ASSERTE (GetModuleHandleA("oleaut32.dll") != NULL);
- // SafeArray has been created, which means oleaut32 should have been loaded.
- // Delay load will not fail.
- CONTRACT_VIOLATION(ThrowsViolation);
- hr = SafeArrayDestroy(psa);
- _ASSERTE(!FAILED(hr));
- }
-}
-#endif //FEATURE_CLASSIC_COMINTEROP
-
-
-//=======================================================================
-// function ptr <--> Delegate
-// See FieldMarshaler for details.
-//=======================================================================
-VOID FieldMarshaler_Delegate::UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(CheckPointer(pNativeValue));
- }
- CONTRACTL_END;
-
- LPVOID fnPtr = COMDelegate::ConvertToCallback(*pCLRValue);
-
- // If there is no CleanupWorkList (i.e. a call from Marshal.StructureToPtr), we don't use it to manage delegate lifetime.
- // In that case, it falls on the user to manage the delegate lifetime. This is the cleanest way to do this since there is no well-defined
- // object lifetime for the unmanaged memory that the structure would be marshalled to in the Marshal.StructureToPtr case.
- 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);
-
- ARG_SLOT args[] =
- {
- (ARG_SLOT)ppCleanupWorkListOnStack,
- ObjToArgSlot(*pCLRValue)
- };
-
- AddToCleanupList.Call(args);
- }
-
- MAYBE_UNALIGNED_WRITE(pNativeValue, _PTR, fnPtr);
-}
-
-
-//=======================================================================
-// function ptr <--> Delegate
-// See FieldMarshaler for details.
-//=======================================================================
-VOID FieldMarshaler_Delegate::UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(CheckPointer(pNativeValue));
- PRECONDITION(CheckPointer(ppProtectedCLRValue));
- }
- CONTRACTL_END;
-
- *ppProtectedCLRValue = COMDelegate::ConvertToDelegate((LPVOID)MAYBE_UNALIGNED_READ(pNativeValue, _PTR), GetMethodTable());
-}
-
-
-//=======================================================================
-// SafeHandle <--> Handle
-// See FieldMarshaler for details.
-//=======================================================================
-VOID FieldMarshaler_SafeHandle::UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(CheckPointer(pNativeValue));
- PRECONDITION(CheckPointer(ppCleanupWorkListOnStack, NULL_OK));
- }
- CONTRACTL_END;
-
- SAFEHANDLE *pSafeHandleObj = ((SAFEHANDLE *)pCLRValue);
-
- // A cleanup list MUST be specified in order for us to be able to marshal
- // the SafeHandle.
- if (ppCleanupWorkListOnStack == NULL)
- COMPlusThrow(kInvalidOperationException, IDS_EE_SH_FIELD_INVALID_OPERATION);
-
- if (*pSafeHandleObj == NULL)
- COMPlusThrow(kArgumentNullException, W("ArgumentNull_SafeHandle"));
-
- // Call StubHelpers.AddToCleanupList to AddRef and schedule Release on this SafeHandle
- // This is realiable, i.e. the cleanup will happen if and only if the SH was actually AddRef'ed.
- MethodDescCallSite AddToCleanupList(METHOD__STUBHELPERS__ADD_TO_CLEANUP_LIST_SAFEHANDLE);
-
- ARG_SLOT args[] =
- {
- (ARG_SLOT)ppCleanupWorkListOnStack,
- ObjToArgSlot(*pSafeHandleObj)
- };
-
- LPVOID handle = AddToCleanupList.Call_RetLPVOID(args);
-
- MAYBE_UNALIGNED_WRITE(pNativeValue, _PTR, handle);
-}
-
-
-//=======================================================================
-// SafeHandle <--> Handle
-// See FieldMarshaler for details.
-//=======================================================================
-VOID FieldMarshaler_SafeHandle::UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(CheckPointer(pNativeValue));
- PRECONDITION(CheckPointer(ppProtectedCLRValue));
- PRECONDITION(CheckPointer(ppProtectedOldCLRValue));
- }
- CONTRACTL_END;
-
- // Since we dissallow marshaling SafeHandle fields from unmanaged to managed, check
- // to see if this handle was obtained from a SafeHandle and if it was that the
- // handle value hasn't changed.
- SAFEHANDLE *pSafeHandleObj = (SAFEHANDLE *)ppProtectedOldCLRValue;
- if (!*pSafeHandleObj || (*pSafeHandleObj)->GetHandle() != (LPVOID)MAYBE_UNALIGNED_READ(pNativeValue, _PTR))
- COMPlusThrow(kNotSupportedException, IDS_EE_CANNOT_CREATE_SAFEHANDLE_FIELD);
-
- // Now that we know the handle hasn't changed we just copy set the new SafeHandle
- // to the old one.
- *ppProtectedCLRValue = *ppProtectedOldCLRValue;
-}
-
-
-//=======================================================================
-// CriticalHandle <--> Handle
-// See FieldMarshaler for details.
-//=======================================================================
-VOID FieldMarshaler_CriticalHandle::UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(CheckPointer(pNativeValue));
- }
- CONTRACTL_END;
-
- LPVOID handle = ((CRITICALHANDLE)*pCLRValue)->GetHandle();
- MAYBE_UNALIGNED_WRITE(pNativeValue, _PTR, handle);
-}
-
-
-//=======================================================================
-// CriticalHandle <--> Handle
-// See FieldMarshaler for details.
-//=======================================================================
-VOID FieldMarshaler_CriticalHandle::UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(CheckPointer(pNativeValue));
- PRECONDITION(CheckPointer(ppProtectedCLRValue));
- PRECONDITION(CheckPointer(ppProtectedOldCLRValue));
- }
- CONTRACTL_END;
-
- // Since we dissallow marshaling CriticalHandle fields from unmanaged to managed, check
- // to see if this handle was obtained from a CriticalHandle and if it was that the
- // handle value hasn't changed.
- CRITICALHANDLE *pCriticalHandleObj = (CRITICALHANDLE *)ppProtectedOldCLRValue;
- if (!*pCriticalHandleObj || (*pCriticalHandleObj)->GetHandle() != (LPVOID)MAYBE_UNALIGNED_READ(pNativeValue, _PTR))
- COMPlusThrow(kNotSupportedException, IDS_EE_CANNOT_CREATE_CRITICALHANDLE_FIELD);
-
- // Now that we know the handle hasn't changed we just copy set the new CriticalHandle
- // to the old one.
- *ppProtectedCLRValue = *ppProtectedOldCLRValue;
-}
-
+ case MarshalInfo::MARSHAL_TYPE_FLOAT:
+ *pNFD = NativeFieldDescriptor(NATIVE_FIELD_CATEGORY_R4, sizeof(float), sizeof(float));
+ break;
+ case MarshalInfo::MARSHAL_TYPE_DOUBLE:
+#if defined(_TARGET_X86_) && defined(UNIX_X86_ABI)
+ *pNFD = NativeFieldDescriptor(NATIVE_FIELD_CATEGORY_R8, sizeof(double), 4);
+#else
+ *pNFD = NativeFieldDescriptor(NATIVE_FIELD_CATEGORY_R8, sizeof(double), sizeof(double));
+#endif
+ break;
+ case MarshalInfo::MARSHAL_TYPE_CURRENCY:
+ *pNFD = NativeFieldDescriptor(MscorlibBinder::GetClass(CLASS__CURRENCY));
+ break;
+ case MarshalInfo::MARSHAL_TYPE_DECIMAL:
+ // The decimal type can't be blittable since the managed and native alignment requirements differ.
+ // Native needs 8-byte alignment since one field is a 64-bit integer, but managed only needs 4-byte alignment since all fields are ints.
+ *pNFD = NativeFieldDescriptor(MscorlibBinder::GetClass(CLASS__NATIVEDECIMAL));
+ break;
+ case MarshalInfo::MARSHAL_TYPE_GUID:
+ *pNFD = NativeFieldDescriptor(MscorlibBinder::GetClass(CLASS__GUID), 1 /* numElements */, true /* isBlittable */);
+ break;
+ case MarshalInfo::MARSHAL_TYPE_DATE:
+ *pNFD = NativeFieldDescriptor(NATIVE_FIELD_CATEGORY_DATE, sizeof(double), sizeof(double));
+ break;
+ case MarshalInfo::MARSHAL_TYPE_LPWSTR:
+ case MarshalInfo::MARSHAL_TYPE_LPSTR:
+ case MarshalInfo::MARSHAL_TYPE_LPUTF8STR:
+ case MarshalInfo::MARSHAL_TYPE_BSTR:
+ case MarshalInfo::MARSHAL_TYPE_ANSIBSTR:
+ *pNFD = NativeFieldDescriptor(NATIVE_FIELD_CATEGORY_INTEGER_LIKE, sizeof(void*), sizeof(void*));
+ break;
+#ifdef FEATURE_COMINTEROP
+ case MarshalInfo::MARSHAL_TYPE_HSTRING:
+ *pNFD = NativeFieldDescriptor(NATIVE_FIELD_CATEGORY_COM_STRUCT, sizeof(HSTRING), sizeof(HSTRING));
+ break;
+ case MarshalInfo::MARSHAL_TYPE_DATETIME:
+ *pNFD = NativeFieldDescriptor(NATIVE_FIELD_CATEGORY_WELL_KNOWN, sizeof(INT64), alignof(INT64));
+ break;
+ case MarshalInfo::MARSHAL_TYPE_INTERFACE:
+ *pNFD = NativeFieldDescriptor(NATIVE_FIELD_CATEGORY_INTERFACE_TYPE, sizeof(IUnknown*), sizeof(IUnknown*));
+ break;
+ case MarshalInfo::MARSHAL_TYPE_SAFEARRAY:
+ *pNFD = NativeFieldDescriptor(NATIVE_FIELD_CATEGORY_INTERFACE_TYPE, sizeof(SAFEARRAY*), sizeof(SAFEARRAY*));
+ break;
+#endif
+ case MarshalInfo::MARSHAL_TYPE_DELEGATE:
+ *pNFD = NativeFieldDescriptor(NATIVE_FIELD_CATEGORY_INTEGER_LIKE, sizeof(void*), sizeof(void*));
+ break;
+ case MarshalInfo::MARSHAL_TYPE_BLITTABLEVALUECLASS:
+ *pNFD = NativeFieldDescriptor(pargs->m_pMT, 1, true);
+ break;
+ case MarshalInfo::MARSHAL_TYPE_VALUECLASS: // If we get MARSHAL_TYPE_VALUECLASS, we know that the nested type is not blittable.
+ case MarshalInfo::MARSHAL_TYPE_LAYOUTCLASS:
+ case MarshalInfo::MARSHAL_TYPE_BLITTABLE_LAYOUTCLASS: // Since a LayoutClass is a reference type, it can't be blittable.
+ *pNFD = NativeFieldDescriptor(pargs->m_pMT);
+ break;
#ifdef FEATURE_COMINTEROP
+ case MarshalInfo::MARSHAL_TYPE_OBJECT:
+ *pNFD = NativeFieldDescriptor(MscorlibBinder::GetClass(CLASS__NATIVEVARIANT));
+ break;
+#endif
+ case MarshalInfo::MARSHAL_TYPE_SAFEHANDLE:
+ case MarshalInfo::MARSHAL_TYPE_CRITICALHANDLE:
+ *pNFD = NativeFieldDescriptor(NATIVE_FIELD_CATEGORY_INTEGER_LIKE, sizeof(void*), sizeof(void*));
+ break;
+ case MarshalInfo::MARSHAL_TYPE_FIXED_ARRAY:
+ {
+ CREATE_MARSHALER_CARRAY_OPERANDS mops;
+ mlInfo.GetMops(&mops);
-//=======================================================================
-// COM IP <--> interface
-// See FieldMarshaler for details.
-//=======================================================================
-VOID FieldMarshaler_Interface::UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(CheckPointer(pNativeValue));
- }
- CONTRACTL_END;
+ MethodTable *pMT = mops.methodTable;
- IUnknown *pUnk = NULL;
+ if (pMT->IsEnum())
+ {
+ pMT = MscorlibBinder::GetElementType(pMT->GetInternalCorElementType());
+ }
- if (!m_pItfMT.IsNull())
- {
- pUnk = GetComIPFromObjectRef(pCLRValue, GetInterfaceMethodTable());
- }
- else if (!(m_dwFlags & ItfMarshalInfo::ITF_MARSHAL_USE_BASIC_ITF))
- {
- pUnk = GetComIPFromObjectRef(pCLRValue, GetMethodTable());
- }
- else
- {
- ComIpType ReqIpType = !!(m_dwFlags & ItfMarshalInfo::ITF_MARSHAL_DISP_ITF) ? ComIpType_Dispatch : ComIpType_Unknown;
- pUnk = GetComIPFromObjectRef(pCLRValue, ReqIpType, NULL);
+ *pNFD = NativeFieldDescriptor(OleVariant::GetNativeMethodTableForVarType(mops.elementType, pMT), mops.additive);
+ break;
+ }
+ case MarshalInfo::MARSHAL_TYPE_FIXED_CSTR:
+ *pNFD = NativeFieldDescriptor(MscorlibBinder::GetClass(CLASS__BYTE), pargs->fs.fixedStringLength);
+ break;
+ case MarshalInfo::MARSHAL_TYPE_FIXED_WSTR:
+ *pNFD = NativeFieldDescriptor(MscorlibBinder::GetClass(CLASS__UINT16), pargs->fs.fixedStringLength);
+ break;
+#ifdef FEATURE_COMINTEROP
+ case MarshalInfo::MARSHAL_TYPE_SYSTEMTYPE:
+ *pNFD = NativeFieldDescriptor(NATIVE_FIELD_CATEGORY_COM_STRUCT, sizeof(TypeNameNative), alignof(TypeNameNative));
+ break;
+ case MarshalInfo::MARSHAL_TYPE_EXCEPTION:
+ *pNFD = NativeFieldDescriptor(NATIVE_FIELD_CATEGORY_INTEGER_LIKE, sizeof(int), alignof(int));
+ break;
+ case MarshalInfo::MARSHAL_TYPE_NULLABLE:
+ *pNFD = NativeFieldDescriptor(NATIVE_FIELD_CATEGORY_WELL_KNOWN, sizeof(IUnknown*), sizeof(IUnknown*));
+ break;
+#endif
+ case MarshalInfo::MARSHAL_TYPE_UNKNOWN:
+ default:
+ *pNFD = NativeFieldDescriptor();
+ break;
+ }
}
-
- MAYBE_UNALIGNED_WRITE(pNativeValue, _PTR, pUnk);
-}
-
-
-//=======================================================================
-// COM IP <--> interface
-// See FieldMarshaler for details.
-//=======================================================================
-VOID FieldMarshaler_Interface::UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const
-{
- CONTRACTL
+ EX_CATCH
{
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(CheckPointer(pNativeValue));
- PRECONDITION(CheckPointer(ppProtectedCLRValue));
- PRECONDITION(IsProtectedByGCFrame(ppProtectedCLRValue));
+ // We were unable to determine the native type, likely because there is a mutually recursive type reference
+ // in this field's type. Mark this field as an "illegal" native field type. We'll throw an exception
+ // if the user actually tries to marshal this type from managed code to native code.
+ *pNFD = NativeFieldDescriptor();
}
- CONTRACTL_END;
-
- IUnknown *pUnk = (IUnknown*)MAYBE_UNALIGNED_READ(pNativeValue, _PTR);
+ EX_END_CATCH(RethrowTerminalExceptions);
- MethodTable *pItfMT = GetInterfaceMethodTable();
- if (pItfMT != NULL && !pItfMT->IsInterface())
- pItfMT = NULL;
-
- GetObjectRefFromComIP(
- ppProtectedCLRValue, // Created object
- pUnk, // Interface pointer
- GetMethodTable(), // Class MT
- pItfMT, // Interface MT
- (m_dwFlags & ItfMarshalInfo::ITF_MARSHAL_CLASS_IS_HINT) // Flags
- );
}
-
//=======================================================================
-// COM IP <--> interface
-// See FieldMarshaler for details.
+// This function returns TRUE if the type passed in is either a value class or a class and if it has layout information
+// and is marshalable. In all other cases it will return FALSE.
//=======================================================================
-VOID FieldMarshaler_Interface::DestroyNativeImpl(LPVOID pNativeValue) const
+BOOL IsStructMarshalable(TypeHandle th)
{
CONTRACTL
{
NOTHROW;
- GC_TRIGGERS;
+ GC_NOTRIGGER;
MODE_ANY;
- PRECONDITION(CheckPointer(pNativeValue));
+ PRECONDITION(!th.IsNull());
}
CONTRACTL_END;
-
- IUnknown *pUnk = (IUnknown*)MAYBE_UNALIGNED_READ(pNativeValue, _PTR);
- MAYBE_UNALIGNED_WRITE(pNativeValue, _PTR, NULL);
-
- if (pUnk != NULL)
+
+ if (th.IsBlittable())
{
- ULONG cbRef = SafeRelease(pUnk);
- LogInteropRelease(pUnk, cbRef, "Field marshaler destroy native");
+ // th.IsBlittable will return true for arrays of blittable types, however since IsStructMarshalable
+ // is only supposed to return true for value classes or classes with layout that are marshallable
+ // we need to return false if the type is an array.
+ if (th.IsArray())
+ return FALSE;
+ else
+ return TRUE;
}
-}
-#endif // FEATURE_COMINTEROP
+ // Check to see if the type has layout.
+ if (!th.HasLayout())
+ return FALSE;
+ MethodTable *pMT= th.GetMethodTable();
+ PREFIX_ASSUME(pMT != NULL);
+
+ if (pMT->IsStructMarshalable())
+ return TRUE;
-//=======================================================================
-// See FieldMarshaler for details.
-//=======================================================================
-VOID FieldMarshaler_Date::ScalarUpdateNativeImpl(LPVOID pCLR, LPVOID pNative) const
-{
- CONTRACTL
+ const NativeFieldDescriptor *pNativeFieldDescriptors = pMT->GetLayoutInfo()->GetNativeFieldDescriptors();
+ UINT numReferenceFields = pMT->GetLayoutInfo()->GetNumCTMFields();
+
+ for (UINT i = 0; i < numReferenceFields; ++i)
{
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(CheckPointer(pCLR));
- PRECONDITION(CheckPointer(pNative));
+ if (pNativeFieldDescriptors[i].IsUnmarshalable())
+ return FALSE;
}
- CONTRACTL_END;
- // <TODO> Handle unaligned native fields </TODO>
- *((DATE*)pNative) = COMDateTime::TicksToDoubleDate(*((INT64*)pCLR));
+ return TRUE;
}
-
-//=======================================================================
-// See FieldMarshaler for details.
-//=======================================================================
-VOID FieldMarshaler_Date::ScalarUpdateCLRImpl(const VOID *pNative, LPVOID pCLR) const
+NativeFieldDescriptor::NativeFieldDescriptor()
+ :m_nativeSize(1),
+ m_alignmentRequirement(1),
+ m_offset(0),
+ m_flags(NATIVE_FIELD_CATEGORY_ILLEGAL),
+ m_isNestedType(false)
{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(CheckPointer(pNative));
- PRECONDITION(CheckPointer(pCLR));
- }
- CONTRACTL_END;
-
- // <TODO> Handle unaligned native fields </TODO>
- *((INT64*)pCLR) = COMDateTime::DoubleDateToTicks(*((DATE*)pNative));
+ m_pFD.SetValueMaybeNull(nullptr);
}
-
-#ifdef FEATURE_COMINTEROP
-
-//=======================================================================
-// See FieldMarshaler for details.
-//=======================================================================
-VOID FieldMarshaler_Currency::ScalarUpdateNativeImpl(LPVOID pCLR, LPVOID pNative) const
+NativeFieldDescriptor::NativeFieldDescriptor(NativeFieldFlags flags, ULONG nativeSize, ULONG alignment)
+ :m_nativeSize(nativeSize),
+ m_alignmentRequirement(alignment),
+ m_offset(0),
+ m_flags(flags),
+ m_isNestedType(false)
{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- PRECONDITION(CheckPointer(pCLR));
- PRECONDITION(CheckPointer(pNative));
- }
- CONTRACTL_END;
-
- // no need to switch to preemptive mode because it's very primitive operaion, doesn't take
- // long and is guaranteed not to call 3rd party code.
- // But if we do need to switch to preemptive mode, we can't pass the managed pointer to native code directly
- HRESULT hr = VarCyFromDec( (DECIMAL *)pCLR, (CURRENCY*)pNative);
- if (FAILED(hr))
- COMPlusThrowHR(hr);
-
+ m_pFD.SetValueMaybeNull(nullptr);
}
-
-//=======================================================================
-// See FieldMarshaler for details.
-//=======================================================================
-VOID FieldMarshaler_Currency::ScalarUpdateCLRImpl(const VOID *pNative, LPVOID pCLR) const
+NativeFieldDescriptor::NativeFieldDescriptor(PTR_MethodTable pMT, int numElements, bool isBlittable)
+ :m_isNestedType(true)
{
CONTRACTL
{
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- PRECONDITION(CheckPointer(pNative));
- PRECONDITION(CheckPointer(pCLR));
+ PRECONDITION(CheckPointer(pMT));
+ PRECONDITION(pMT->HasLayout());
}
CONTRACTL_END;
- // no need to switch to preemptive mode because it's very primitive operaion, doesn't take
- // long and is guaranteed not to call 3rd party code.
- // But if we do need to switch to preemptive mode, we can't pass the managed pointer to native code directly
- VarDecFromCyCanonicalize( *(CURRENCY*)pNative, (DECIMAL *)pCLR );
+ m_pFD.SetValueMaybeNull(nullptr);
+ m_pNestedType.SetValue(pMT);
+ m_numElements = numElements;
+ m_flags = isBlittable ? NATIVE_FIELD_CATEGORY_NESTED_BLITTABLE : NATIVE_FIELD_CATEGORY_NESTED;
+ m_isNestedType = true;
}
-VOID FieldMarshaler_DateTimeOffset::ScalarUpdateNativeImpl(LPVOID pCLR, LPVOID pNative) const
+NativeFieldDescriptor::NativeFieldDescriptor(const NativeFieldDescriptor& other)
+ :m_offset(other.m_offset),
+ m_flags(other.m_flags),
+ m_isNestedType(other.m_isNestedType)
{
- CONTRACTL
+ m_pFD.SetValueMaybeNull(other.m_pFD.GetValueMaybeNull());
+ if (m_isNestedType)
{
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(CheckPointer(pCLR));
- PRECONDITION(CheckPointer(pNative));
+ m_pNestedType.SetValueMaybeNull(other.m_pNestedType.GetValueMaybeNull());
+ m_numElements = other.m_numElements;
}
- CONTRACTL_END;
-
- MethodDescCallSite convertToNative(METHOD__DATETIMEOFFSETMARSHALER__CONVERT_TO_NATIVE);
- ARG_SLOT args[] =
+ else
{
- PtrToArgSlot(pCLR),
- PtrToArgSlot(pNative)
- };
- convertToNative.Call(args);
+ m_nativeSize = other.m_nativeSize;
+ m_alignmentRequirement = other.m_alignmentRequirement;
+ }
}
-VOID FieldMarshaler_DateTimeOffset::ScalarUpdateCLRImpl(const VOID *pNative, LPVOID pCLR) const
+NativeFieldDescriptor& NativeFieldDescriptor::operator=(const NativeFieldDescriptor& other)
{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(CheckPointer(pNative));
- PRECONDITION(CheckPointer(pCLR));
- }
- CONTRACTL_END;
+ m_offset = other.m_offset;
+ m_flags = other.m_flags;
+ m_isNestedType = other.m_isNestedType;
+ m_pFD.SetValueMaybeNull(other.m_pFD.GetValueMaybeNull());
- MethodDescCallSite convertToManaged(METHOD__DATETIMEOFFSETMARSHALER__CONVERT_TO_MANAGED);
- ARG_SLOT args[] =
+ if (m_isNestedType)
{
- PtrToArgSlot(pCLR),
- PtrToArgSlot(pNative)
- };
- convertToManaged.Call(args);
-}
-
-#endif // FEATURE_COMINTEROP
-
-
-//=======================================================================
-// See FieldMarshaler for details.
-//=======================================================================
-VOID FieldMarshaler_Illegal::ScalarUpdateNativeImpl(LPVOID pCLR, LPVOID pNative) const
-{
- CONTRACTL
+ m_pNestedType.SetValueMaybeNull(other.m_pNestedType.GetValueMaybeNull());
+ m_numElements = other.m_numElements;
+ }
+ else
{
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(CheckPointer(pCLR));
- PRECONDITION(CheckPointer(pNative));
+ m_nativeSize = other.m_nativeSize;
+ m_alignmentRequirement = other.m_alignmentRequirement;
}
- CONTRACTL_END;
- DefineFullyQualifiedNameForClassW();
-
- StackSString ssFieldName(SString::Utf8, GetFieldDesc()->GetName());
-
- StackSString errorString(W("Unknown error."));
- errorString.LoadResource(CCompRC::Error, m_resIDWhy);
-
- COMPlusThrow(kTypeLoadException, IDS_EE_BADMARSHALFIELD_ERROR_MSG,
- GetFullyQualifiedNameForClassW(GetFieldDesc()->GetEnclosingMethodTable()),
- ssFieldName.GetUnicode(), errorString.GetUnicode());
+ return *this;
}
-
-//=======================================================================
-// See FieldMarshaler for details.
-//=======================================================================
-VOID FieldMarshaler_Illegal::ScalarUpdateCLRImpl(const VOID *pNative, LPVOID pCLR) const
+PTR_MethodTable NativeFieldDescriptor::GetNestedNativeMethodTable() const
{
- CONTRACTL
+ CONTRACT(PTR_MethodTable)
{
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(CheckPointer(pNative));
- PRECONDITION(CheckPointer(pCLR));
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ PRECONDITION(IsRestored());
+ PRECONDITION(m_isNestedType);
+ POSTCONDITION(CheckPointer(RETVAL));
}
- CONTRACTL_END;
-
- DefineFullyQualifiedNameForClassW();
-
- StackSString ssFieldName(SString::Utf8, GetFieldDesc()->GetName());
-
- StackSString errorString(W("Unknown error."));
- errorString.LoadResource(CCompRC::Error,m_resIDWhy);
+ CONTRACT_END;
- COMPlusThrow(kTypeLoadException, IDS_EE_BADMARSHALFIELD_ERROR_MSG,
- GetFullyQualifiedNameForClassW(GetFieldDesc()->GetEnclosingMethodTable()),
- ssFieldName.GetUnicode(), errorString.GetUnicode());
+ RETURN m_pNestedType.GetValue();
}
-#ifdef FEATURE_COMINTEROP
-
-
-//=======================================================================
-// See FieldMarshaler for details.
-//=======================================================================
-VOID FieldMarshaler_Variant::UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const
+PTR_FieldDesc NativeFieldDescriptor::GetFieldDesc() const
{
- CONTRACTL
+ CONTRACT(PTR_FieldDesc)
{
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(CheckPointer(pNativeValue));
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
}
- CONTRACTL_END;
-
- OleVariant::MarshalOleVariantForObject(pCLRValue, (VARIANT*)pNativeValue);
+ CONTRACT_END;
+ RETURN m_pFD.GetValueMaybeNull();
}
-
-//=======================================================================
-// See FieldMarshaler for details.
-//=======================================================================
-VOID FieldMarshaler_Variant::UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const
+#ifdef _DEBUG
+BOOL NativeFieldDescriptor::IsRestored() const
{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(CheckPointer(pNativeValue));
- PRECONDITION(CheckPointer(ppProtectedCLRValue));
- }
- CONTRACTL_END;
+ WRAPPER_NO_CONTRACT;
- OleVariant::MarshalObjectForOleVariant((VARIANT*)pNativeValue, ppProtectedCLRValue);
+#ifdef FEATURE_PREJIT
+ return m_pNestedType.IsNull() || (!m_pNestedType.IsTagged() && m_pNestedType.GetValue()->IsRestored());
+#else // FEATURE_PREJIT
+ // putting the IsFullyLoaded check here is tempting but incorrect
+ return TRUE;
+#endif // FEATURE_PREJIT
}
+#endif
-
-//=======================================================================
-// See FieldMarshaler for details.
-//=======================================================================
-VOID FieldMarshaler_Variant::DestroyNativeImpl(LPVOID pNativeValue) const
+void NativeFieldDescriptor::Restore()
{
CONTRACTL
{
- NOTHROW;
+ THROWS;
GC_TRIGGERS;
MODE_ANY;
- PRECONDITION(CheckPointer(pNativeValue));
+ PRECONDITION(!m_isNestedType || CheckPointer(m_pNestedType.GetValue()));
}
CONTRACTL_END;
- SafeVariantClear( (VARIANT*)pNativeValue );
-}
-
-#endif // FEATURE_COMINTEROP
-
-#endif // CROSSGEN_COMPILE
-
-
-//
-// Implementation of the virtual functions using switch statements.
-//
-// We are not able bake pointers to the FieldMarshaller vtables into NGen images. We store
-// the field marshaller id instead, and implement the virtualization by switch based on the id.
-//
-
-#ifdef FEATURE_CLASSIC_COMINTEROP
-#define FieldMarshaler_SafeArray_Case(rettype, name, args) case NFT_SAFEARRAY: rettype ((FieldMarshaler_SafeArray*)this)->name##Impl args; break;
-#else
-#define FieldMarshaler_SafeArray_Case(rettype, name, args)
-#endif
-
-#ifdef FEATURE_COMINTEROP
-
-#define FieldMarshaler_VTable(name, rettype, args) \
- switch (GetNStructFieldType()) { \
- case NFT_STRINGUNI: rettype ((FieldMarshaler_StringUni*)this)->name##Impl args; break; \
- case NFT_STRINGANSI: rettype ((FieldMarshaler_StringAnsi*)this)->name##Impl args; break; \
- case NFT_STRINGUTF8: rettype ((FieldMarshaler_StringUtf8*)this)->name##Impl args; break; \
- case NFT_FIXEDSTRINGUNI: rettype ((FieldMarshaler_FixedStringUni*)this)->name##Impl args; break; \
- case NFT_FIXEDSTRINGANSI: rettype ((FieldMarshaler_FixedStringAnsi*)this)->name##Impl args; break; \
- case NFT_FIXEDCHARARRAYANSI: rettype ((FieldMarshaler_FixedCharArrayAnsi*)this)->name##Impl args; break; \
- case NFT_FIXEDARRAY: rettype ((FieldMarshaler_FixedArray*)this)->name##Impl args; break; \
- case NFT_DELEGATE: rettype ((FieldMarshaler_Delegate*)this)->name##Impl args; break; \
- case NFT_COPY1: rettype ((FieldMarshaler_Copy1*)this)->name##Impl args; break; \
- case NFT_COPY2: rettype ((FieldMarshaler_Copy2*)this)->name##Impl args; break; \
- case NFT_COPY4: rettype ((FieldMarshaler_Copy4*)this)->name##Impl args; break; \
- case NFT_COPY8: rettype ((FieldMarshaler_Copy8*)this)->name##Impl args; break; \
- case NFT_ANSICHAR: rettype ((FieldMarshaler_Ansi*)this)->name##Impl args; break; \
- case NFT_WINBOOL: rettype ((FieldMarshaler_WinBool*)this)->name##Impl args; break; \
- case NFT_NESTEDLAYOUTCLASS: rettype ((FieldMarshaler_NestedLayoutClass*)this)->name##Impl args; break; \
- case NFT_NESTEDVALUECLASS: rettype ((FieldMarshaler_NestedValueClass*)this)->name##Impl args; break; \
- case NFT_CBOOL: rettype ((FieldMarshaler_CBool*)this)->name##Impl args; break; \
- case NFT_DATE: rettype ((FieldMarshaler_Date*)this)->name##Impl args; break; \
- case NFT_DECIMAL: rettype ((FieldMarshaler_Decimal*)this)->name##Impl args; break; \
- case NFT_INTERFACE: rettype ((FieldMarshaler_Interface*)this)->name##Impl args; break; \
- case NFT_SAFEHANDLE: rettype ((FieldMarshaler_SafeHandle*)this)->name##Impl args; break; \
- case NFT_CRITICALHANDLE: rettype ((FieldMarshaler_CriticalHandle*)this)->name##Impl args; break; \
- FieldMarshaler_SafeArray_Case(rettype, name, args) \
- case NFT_BSTR: rettype ((FieldMarshaler_BSTR*)this)->name##Impl args; break; \
- case NFT_HSTRING: rettype ((FieldMarshaler_HSTRING*)this)->name##Impl args; break; \
- case NFT_VARIANT: rettype ((FieldMarshaler_Variant*)this)->name##Impl args; break; \
- case NFT_VARIANTBOOL: rettype ((FieldMarshaler_VariantBool*)this)->name##Impl args; break; \
- case NFT_CURRENCY: rettype ((FieldMarshaler_Currency*)this)->name##Impl args; break; \
- case NFT_DATETIMEOFFSET: rettype ((FieldMarshaler_DateTimeOffset*)this)->name##Impl args; break; \
- case NFT_SYSTEMTYPE: rettype ((FieldMarshaler_SystemType *)this)->name##Impl args; break; \
- case NFT_WINDOWSFOUNDATIONHRESULT: rettype ((FieldMarshaler_Exception*)this)->name##Impl args; break; \
- case NFT_WINDOWSFOUNDATIONIREFERENCE: rettype ((FieldMarshaler_Nullable*)this)->name##Impl args; break; \
- case NFT_ILLEGAL: rettype ((FieldMarshaler_Illegal*)this)->name##Impl args; break; \
- default: UNREACHABLE_MSG("unexpected type of FieldMarshaler"); break; \
- }
-
-#else // FEATURE_COMINTEROP
-
-#define FieldMarshaler_VTable(name, rettype, args) \
- switch (GetNStructFieldType()) { \
- case NFT_STRINGUNI: rettype ((FieldMarshaler_StringUni*)this)->name##Impl args; break; \
- case NFT_STRINGANSI: rettype ((FieldMarshaler_StringAnsi*)this)->name##Impl args; break; \
- case NFT_STRINGUTF8: rettype ((FieldMarshaler_StringUtf8*)this)->name##Impl args; break; \
- case NFT_FIXEDSTRINGUNI: rettype ((FieldMarshaler_FixedStringUni*)this)->name##Impl args; break; \
- case NFT_FIXEDSTRINGANSI: rettype ((FieldMarshaler_FixedStringAnsi*)this)->name##Impl args; break; \
- case NFT_FIXEDCHARARRAYANSI: rettype ((FieldMarshaler_FixedCharArrayAnsi*)this)->name##Impl args; break; \
- case NFT_FIXEDARRAY: rettype ((FieldMarshaler_FixedArray*)this)->name##Impl args; break; \
- case NFT_DELEGATE: rettype ((FieldMarshaler_Delegate*)this)->name##Impl args; break; \
- case NFT_COPY1: rettype ((FieldMarshaler_Copy1*)this)->name##Impl args; break; \
- case NFT_COPY2: rettype ((FieldMarshaler_Copy2*)this)->name##Impl args; break; \
- case NFT_COPY4: rettype ((FieldMarshaler_Copy4*)this)->name##Impl args; break; \
- case NFT_COPY8: rettype ((FieldMarshaler_Copy8*)this)->name##Impl args; break; \
- case NFT_ANSICHAR: rettype ((FieldMarshaler_Ansi*)this)->name##Impl args; break; \
- case NFT_WINBOOL: rettype ((FieldMarshaler_WinBool*)this)->name##Impl args; break; \
- case NFT_NESTEDLAYOUTCLASS: rettype ((FieldMarshaler_NestedLayoutClass*)this)->name##Impl args; break; \
- case NFT_NESTEDVALUECLASS: rettype ((FieldMarshaler_NestedValueClass*)this)->name##Impl args; break; \
- case NFT_CBOOL: rettype ((FieldMarshaler_CBool*)this)->name##Impl args; break; \
- case NFT_DATE: rettype ((FieldMarshaler_Date*)this)->name##Impl args; break; \
- case NFT_DECIMAL: rettype ((FieldMarshaler_Decimal*)this)->name##Impl args; break; \
- case NFT_SAFEHANDLE: rettype ((FieldMarshaler_SafeHandle*)this)->name##Impl args; break; \
- case NFT_CRITICALHANDLE: rettype ((FieldMarshaler_CriticalHandle*)this)->name##Impl args; break; \
- case NFT_BSTR: rettype ((FieldMarshaler_BSTR*)this)->name##Impl args; break; \
- case NFT_ILLEGAL: rettype ((FieldMarshaler_Illegal*)this)->name##Impl args; break; \
- default: UNREACHABLE_MSG("unexpected type of FieldMarshaler"); break; \
- }
-
-#endif // FEATURE_COMINTEROP
-
-#define IMPLEMENT_FieldMarshaler_METHOD(ret, name, argsdecl, rettype, args) \
- ret FieldMarshaler::name argsdecl { \
- WRAPPER_NO_CONTRACT; \
- FieldMarshaler_VTable(name, rettype, args) \
- }
+#ifdef FEATURE_PREJIT
+ Module::RestoreFieldDescPointer(&m_pFD);
+#endif // FEATURE_PREJIT
-UINT32 FieldMarshaler::NativeSize() const
-{
- WRAPPER_NO_CONTRACT;
- // Use the NFTDataBase to lookup the native size quickly to avoid a vtable call when the result is already known.
- if (NFTDataBase[m_nft].m_cbNativeSize != 0)
- {
- return NFTDataBase[m_nft].m_cbNativeSize;
- }
- else
+ if (m_isNestedType)
{
- FieldMarshaler_VTable(NativeSize, return, ())
- }
-}
-
-IMPLEMENT_FieldMarshaler_METHOD(UINT32, AlignmentRequirement,
- () const,
- return,
- ())
-
-IMPLEMENT_FieldMarshaler_METHOD(BOOL, IsScalarMarshaler,
- () const,
- return,
- ())
-
-IMPLEMENT_FieldMarshaler_METHOD(BOOL, IsNestedValueClassMarshaler,
- () const,
- return,
- ())
-
-#ifndef CROSSGEN_COMPILE
-IMPLEMENT_FieldMarshaler_METHOD(VOID, UpdateNative,
- (OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const,
- ,
- (pCLRValue, pNativeValue, ppCleanupWorkListOnStack))
-IMPLEMENT_FieldMarshaler_METHOD(VOID, UpdateCLR,
- (const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const,
- ,
- (pNativeValue, ppProtectedCLRValue, ppProtectedOldCLRValue))
-
-IMPLEMENT_FieldMarshaler_METHOD(VOID, DestroyNative,
- (LPVOID pNativeValue) const,
- ,
- (pNativeValue))
-
-IMPLEMENT_FieldMarshaler_METHOD(VOID, ScalarUpdateNative,
- (LPVOID pCLR, LPVOID pNative) const,
- return,
- (pCLR, pNative))
-
-IMPLEMENT_FieldMarshaler_METHOD(VOID, ScalarUpdateCLR,
- (const VOID *pNative, LPVOID pCLR) const,
- return,
- (pNative, pCLR))
-
-IMPLEMENT_FieldMarshaler_METHOD(VOID, NestedValueClassUpdateNative,
- (const VOID **ppProtectedCLR, SIZE_T startoffset, LPVOID pNative, OBJECTREF *ppCleanupWorkListOnStack) const,
- ,
- (ppProtectedCLR, startoffset, pNative, ppCleanupWorkListOnStack))
-
-IMPLEMENT_FieldMarshaler_METHOD(VOID, NestedValueClassUpdateCLR,
- (const VOID *pNative, LPVOID *ppProtectedCLR, SIZE_T startoffset) const,
- ,
- (pNative, ppProtectedCLR, startoffset))
-#endif // CROSSGEN_COMPILE
-
-#ifdef FEATURE_NATIVE_IMAGE_GENERATION
-IMPLEMENT_FieldMarshaler_METHOD(void, Save,
- (DataImage *image),
- ,
- (image))
-
-IMPLEMENT_FieldMarshaler_METHOD(void, Fixup,
- (DataImage *image),
- ,
- (image))
-#endif // FEATURE_NATIVE_IMAGE_GENERATION
-
-IMPLEMENT_FieldMarshaler_METHOD(void, Restore,
- (),
- ,
- ())
-
-#ifndef DACCESS_COMPILE
-IMPLEMENT_FieldMarshaler_METHOD(VOID, CopyTo,
- (VOID *pDest, SIZE_T destSize) const,
- ,
- (pDest, destSize))
-#endif // !DACCESS_COMPILE
-
-
-
-MethodTable* FieldMarshaler_NestedType::GetNestedNativeMethodTable() const
-{
- switch (GetNStructFieldType())
- {
- case NFT_NESTEDLAYOUTCLASS:
- return ((FieldMarshaler_NestedLayoutClass*)this)->GetNestedNativeMethodTableImpl();
- case NFT_NESTEDVALUECLASS:
- return ((FieldMarshaler_NestedValueClass*)this)->GetNestedNativeMethodTableImpl();
- case NFT_FIXEDARRAY:
- return ((FieldMarshaler_FixedArray*)this)->GetNestedNativeMethodTableImpl();
- case NFT_DECIMAL:
- return ((FieldMarshaler_Decimal*)this)->GetNestedNativeMethodTableImpl();
- default:
- UNREACHABLE_MSG("unexpected type of FieldMarshaler_NestedType");
- return nullptr;
+#ifdef FEATURE_PREJIT
+ Module::RestoreMethodTablePointer(&m_pNestedType);
+#else // FEATURE_PREJIT
+ // without NGEN we only have to make sure that the type is fully loaded
+ PTR_MethodTable pMT = m_pNestedType.GetValue();
+ if (pMT != NULL)
+ ClassLoader::EnsureLoaded(pMT);
+#endif // FEATURE_PREJIT
}
}
-UINT32 FieldMarshaler_NestedType::GetNumElements() const
+void NativeFieldDescriptor::SetFieldDesc(PTR_FieldDesc pFD)
{
- switch (GetNStructFieldType())
- {
- case NFT_NESTEDLAYOUTCLASS:
- return ((FieldMarshaler_NestedLayoutClass*)this)->GetNumElementsImpl();
- case NFT_NESTEDVALUECLASS:
- return ((FieldMarshaler_NestedValueClass*)this)->GetNumElementsImpl();
- case NFT_FIXEDARRAY:
- return ((FieldMarshaler_FixedArray*)this)->GetNumElementsImpl();
- case NFT_DECIMAL:
- return ((FieldMarshaler_Decimal*)this)->GetNumElementsImpl();
- default:
- UNREACHABLE_MSG("unexpected type of FieldMarshaler_NestedType");
- return 1;
- }
+ LIMITED_METHOD_CONTRACT;
+ m_pFD.SetValueMaybeNull(pFD);
}
// File: FieldMarshaler.h
//
-//
-// FieldMarshalers are used to allow CLR programs to allocate and access
-// native structures for interop purposes. FieldMarshalers are actually normal GC
-// objects with a class, but instead of keeping fields in the GC object,
-// it keeps a hidden pointer to a fixed memory block (which may have been
-// allocated by a third party.) Field accesses to FieldMarshalers are redirected
-// to this fixed block.
-//
-
#ifndef __FieldMarshaler_h__
#define __FieldMarshaler_h__
#include "olevariant.h"
#include "nativefieldflags.h"
-#ifdef FEATURE_COMINTEROP
-#endif // FEATURE_COMINTEROP
-
#ifdef FEATURE_PREJIT
#include "compile.h"
#endif // FEATURE_PREJIT
class FieldDesc;
class MethodTable;
-class FieldMarshaler;
-class FieldMarshaler_NestedType;
-class FieldMarshaler_NestedLayoutClass;
-class FieldMarshaler_NestedValueClass;
-class FieldMarshaler_StringUni;
-class FieldMarshaler_StringAnsi;
-class FieldMarshaler_FixedStringUni;
-class FieldMarshaler_FixedStringAnsi;
-class FieldMarshaler_FixedArray;
-class FieldMarshaler_FixedCharArrayAnsi;
-class FieldMarshaler_Delegate;
-class FieldMarshaler_Illegal;
-class FieldMarshaler_Copy1;
-class FieldMarshaler_Copy2;
-class FieldMarshaler_Copy4;
-class FieldMarshaler_Copy8;
-class FieldMarshaler_Ansi;
-class FieldMarshaler_WinBool;
-class FieldMarshaler_CBool;
-class FieldMarshaler_Decimal;
-class FieldMarshaler_Date;
-class FieldMarshaler_BSTR;
-#ifdef FEATURE_COMINTEROP
-class FieldMarshaler_SafeArray;
-class FieldMarshaler_HSTRING;
-class FieldMarshaler_Interface;
-class FieldMarshaler_Variant;
-class FieldMarshaler_VariantBool;
-class FieldMarshaler_DateTimeOffset;
-class FieldMarshaler_SystemType;
-class FieldMarshaler_Exception;
-class FieldMarshaler_Nullable;
-#endif // FEATURE_COMINTEROP
-
-//=======================================================================
-// Each possible CLR/Native pairing of data type has a
-// NFT_* id. This is used to select the marshaling code.
-//=======================================================================
-#undef DEFINE_NFT
-#define DEFINE_NFT(name, nativesize, fWinRTSupported) name,
-enum NStructFieldType : short
-{
-#include "nsenums.h"
- NFT_COUNT
-};
-
-
//=======================================================================
// Magic number for default struct packing size.
//
//=======================================================================
#define DEFAULT_PACKING_SIZE 32
+//=======================================================================
+// This structure contains information about where a field is placed in a structure, as well as it's size and alignment.
+// It is used as part of type-loading to determine native layout and (where applicable) managed sequential layout.
+//=======================================================================
+struct RawFieldPlacementInfo
+{
+ UINT32 m_offset;
+ UINT32 m_size;
+ UINT32 m_alignment;
+};
+
enum class ParseNativeTypeFlags : int
{
None = 0x00,
};
VOID ParseNativeType(Module* pModule,
- PCCOR_SIGNATURE pCOMSignature,
- DWORD cbCOMSignature,
+ SigPointer sig,
+ mdFieldDef fd,
ParseNativeTypeFlags flags,
- LayoutRawFieldInfo* pfwalk,
- PCCOR_SIGNATURE pNativeType,
- ULONG cbNativeType,
- mdTypeDef cl,
- const SigTypeContext * pTypeContext,
- BOOL *pfDisqualifyFromManagedSequential
+ NativeFieldDescriptor* pNFD,
+ const SigTypeContext * pTypeContext
#ifdef _DEBUG
,
LPCUTF8 szNamespace,
#endif
);
-BOOL IsFieldBlittable(FieldMarshaler* pFM);
-
//=======================================================================
// This function returns TRUE if the type passed in is either a value class or a class and if it has layout information
// and is marshalable. In all other cases it will return FALSE.
//=======================================================================
BOOL IsStructMarshalable(TypeHandle th);
-//=======================================================================
-// This structure contains information about where a field is placed in a structure, as well as it's size and alignment.
-// It is used as part of type-loading to determine native layout and (where applicable) managed sequential layout.
-//=======================================================================
-struct RawFieldPlacementInfo
-{
- UINT32 m_offset;
- UINT32 m_size;
- UINT32 m_alignment;
-};
-
-//=======================================================================
-// The classloader stores an intermediate representation of the layout
-// metadata in an array of these structures. The dual-pass nature
-// is a bit extra overhead but building this structure requiring loading
-// other classes (for nested structures) and I'd rather keep this
-// next to the other places where we load other classes (e.g. the superclass
-// and implemented interfaces.)
-//
-// Each redirected field gets one entry in LayoutRawFieldInfo.
-// The array is terminated by one dummy record whose m_MD == mdMemberDefNil.
-//=======================================================================
-struct LayoutRawFieldInfo
-{
- mdFieldDef m_MD; // mdMemberDefNil for end of array
- UINT8 m_nft; // NFT_* value
- RawFieldPlacementInfo m_nativePlacement; // Description of the native field placement
- ULONG m_sequence; // sequence # from metadata
-
-
- // The LayoutKind.Sequential attribute now affects managed layout as well.
- // So we need to keep a parallel set of layout data for the managed side. The Size and AlignmentReq
- // is redundant since we can figure it out from the sig but since we're already accessing the sig
- // in ParseNativeType, we might as well capture it at that time.
- RawFieldPlacementInfo m_managedPlacement;
-
- // This field is needs to be 8-byte aligned
- // to ensure that the FieldMarshaler vtable pointer is aligned correctly.
- alignas(8) struct
- {
- private:
- char m_space[MAXFIELDMARSHALERSIZE];
- } m_FieldMarshaler;
-};
-
-
-//=======================================================================
-//
-//=======================================================================
-
-VOID LayoutUpdateNative(LPVOID *ppProtectedManagedData, SIZE_T offsetbias, MethodTable *pMT, BYTE* pNativeData, OBJECTREF *ppCleanupWorkListOnStack);
-VOID LayoutUpdateCLR(LPVOID *ppProtectedManagedData, SIZE_T offsetbias, MethodTable *pMT, BYTE *pNativeData);
-VOID LayoutDestroyNative(LPVOID pNative, MethodTable *pMT);
-
-VOID FmtClassUpdateNative(OBJECTREF *ppProtectedManagedData, BYTE *pNativeData, OBJECTREF *ppCleanupWorkListOnStack);
-VOID FmtClassUpdateCLR(OBJECTREF *ppProtectedManagedData, BYTE *pNativeData);
-VOID FmtClassDestroyNative(LPVOID pNative, MethodTable *pMT);
-
-VOID FmtValueTypeUpdateNative(LPVOID pProtectedManagedData, MethodTable *pMT, BYTE *pNativeData, OBJECTREF *ppCleanupWorkListOnStack);
-VOID FmtValueTypeUpdateCLR(LPVOID pProtectedManagedData, MethodTable *pMT, BYTE *pNativeData);
-
-
-//=======================================================================
-// Abstract base class. Each type of NStruct reference field extends
-// this class and implements the necessary methods.
-//
-// UpdateNativeImpl
-// - this method receives a COM+ field value and a pointer to
-// native field inside the fixed portion. it should marshal
-// the COM+ value to a new native instance and store it
-// inside *pNativeValue. Do not destroy the value you overwrite
-// in *pNativeValue.
-//
-// may throw COM+ exceptions
-//
-// UpdateCLRImpl
-// - this method receives a read-only pointer to the native field inside
-// the fixed portion. it should marshal the native value to
-// a new CLR instance and store it in *ppCLRValue.
-// (the caller keeps *ppCLRValue gc-protected.)
-//
-// may throw CLR exceptions
-//
-// DestroyNativeImpl
-// - should do the type-specific deallocation of a native instance.
-// if the type has a "NULL" value, this method should
-// overwrite the field with this "NULL" value (whether or not
-// it does, however, it's considered a bug to depend on the
-// value left over after a DestroyNativeImpl.)
-//
-// must NOT throw a CLR exception
-//
-// NativeSizeImpl
-// - returns the size, in bytes, of the native version of the field.
-//
-// AlignmentRequirementImpl
-// - returns one of 1,2,4 or 8; indicating the "natural" alignment
-// of the native field. In general,
-//
-// for scalars, the AR is equal to the size
-// for arrays, the AR is that of a single element
-// for structs, the AR is that of the member with the largest AR
-//
-//
-//=======================================================================
-
-
-#ifndef DACCESS_COMPILE
-
-#define UNUSED_METHOD_IMPL(PROTOTYPE) \
- PROTOTYPE \
- { \
- LIMITED_METHOD_CONTRACT; \
- _ASSERTE(!"Not supposed to get here."); \
- }
-
-#define ELEMENT_SIZE_IMPL(NativeSize, AlignmentReq) \
- UINT32 NativeSizeImpl() const \
- { \
- LIMITED_METHOD_CONTRACT; \
- return NativeSize; \
- } \
- UINT32 AlignmentRequirementImpl() const \
- { \
- LIMITED_METHOD_CONTRACT; \
- return AlignmentReq; \
- }
-
-#define SCALAR_MARSHALER_IMPL(NativeSize, AlignmentReq) \
- BOOL IsScalarMarshalerImpl() const \
- { \
- LIMITED_METHOD_CONTRACT; \
- return TRUE; \
- } \
- ELEMENT_SIZE_IMPL(NativeSize, AlignmentReq)
-
-#define COPY_TO_IMPL_BASE_STRUCT_ONLY() \
- VOID CopyToImpl(VOID *pDest, SIZE_T destSize) \
- { \
- static_assert(sizeof(*this) == sizeof(FieldMarshaler), \
- "Please, implement CopyToImpl for correct copy of field values"); \
- \
- FieldMarshaler::CopyToImpl(pDest, destSize); \
- }
-
-#define START_COPY_TO_IMPL(CLASS_NAME) \
- VOID CopyToImpl(VOID *pDest, SIZE_T destSize) const \
- { \
- FieldMarshaler::CopyToImpl(pDest, destSize); \
- \
- CLASS_NAME *pDestFieldMarshaller = (std::remove_const<std::remove_pointer<decltype(this)>::type>::type *) pDest; \
- _ASSERTE(sizeof(*pDestFieldMarshaller) <= destSize); \
-
-#define END_COPY_TO_IMPL(CLASS_NAME) \
- static_assert(std::is_same<CLASS_NAME *, decltype(pDestFieldMarshaller)>::value, \
- "Structure's name is required"); \
- }
-
-
-//=======================================================================
-//
-// FieldMarshaler's are constructed in place and replicated via bit-wise
-// copy, so you can't have a destructor. Make sure you don't define a
-// destructor in derived classes!!
-// We used to enforce this by defining a private destructor, by the C++
-// compiler doesn't allow that anymore.
-//
-//=======================================================================
-
-class FieldMarshaler
+class NativeFieldDescriptor
{
- template<typename TFieldMarshaler, typename TSpace, typename... TArgs>
- friend NStructFieldType InitFieldMarshaler(TSpace& space, NativeFieldFlags flags, TArgs&&... args);
-
public:
- VOID UpdateNative(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const;
- VOID UpdateCLR(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const;
- VOID DestroyNative(LPVOID pNativeValue) const;
- UINT32 NativeSize() const;
- UINT32 AlignmentRequirement() const;
- BOOL IsScalarMarshaler() const;
- BOOL IsNestedValueClassMarshaler() const;
- VOID ScalarUpdateNative(LPVOID pCLR, LPVOID pNative) const;
- VOID ScalarUpdateCLR(const VOID *pNative, LPVOID pCLR) const;
- VOID NestedValueClassUpdateNative(const VOID **ppProtectedCLR, SIZE_T startoffset, LPVOID pNative, OBJECTREF *ppCleanupWorkListOnStack) const;
- VOID NestedValueClassUpdateCLR(const VOID *pNative, LPVOID *ppProtectedCLR, SIZE_T startoffset) const;
- VOID CopyTo(VOID *pDest, SIZE_T destSize) const;
-#ifdef FEATURE_PREJIT
- void Save(DataImage *image);
- void Fixup(DataImage *image);
-#endif // FEATURE_PREJIT
- void Restore();
-
- VOID DestroyNativeImpl(LPVOID pNativeValue) const
- {
- LIMITED_METHOD_CONTRACT;
- }
-
- BOOL IsScalarMarshalerImpl() const
- {
- LIMITED_METHOD_CONTRACT;
- return FALSE;
- }
-
- BOOL IsNestedValueClassMarshalerImpl() const
- {
- LIMITED_METHOD_CONTRACT;
- return FALSE;
- }
-
- UNUSED_METHOD_IMPL(VOID ScalarUpdateNativeImpl(LPVOID pCLR, LPVOID pNative) const)
- UNUSED_METHOD_IMPL(VOID ScalarUpdateCLRImpl(const VOID *pNative, LPVOID pCLR) const)
- UNUSED_METHOD_IMPL(VOID NestedValueClassUpdateNativeImpl(const VOID **ppProtectedCLR, SIZE_T startoffset, LPVOID pNative, OBJECTREF *ppCleanupWorkListOnStack) const)
- UNUSED_METHOD_IMPL(VOID NestedValueClassUpdateCLRImpl(const VOID *pNative, LPVOID *ppProtectedCLR, SIZE_T startoffset) const)
-
-protected:
- NStructFieldType GetNStructFieldType() const
- {
- LIMITED_METHOD_CONTRACT;
- return m_nft;
- }
-
-private:
-
- void SetNStructFieldType(NStructFieldType nft)
- {
- LIMITED_METHOD_CONTRACT;
- m_nft = nft;
- }
+ NativeFieldDescriptor();
- void SetNativeFieldFlags(NativeFieldFlags nff)
- {
- LIMITED_METHOD_CONTRACT;
- _ASSERTE(m_nff == 0);
- m_nff = nff;
- }
+ NativeFieldDescriptor(NativeFieldFlags flags, ULONG nativeSize, ULONG alignment);
-public:
+ NativeFieldDescriptor(PTR_MethodTable pMT, int numElements = 1, bool isBlittable = false);
- BOOL IsIllegalMarshaler() const
- {
- return m_nft == NFT_ILLEGAL ? TRUE : FALSE;
- }
+ NativeFieldDescriptor(const NativeFieldDescriptor& other);
- NativeFieldFlags GetNativeFieldFlags() const
- {
- LIMITED_METHOD_CONTRACT;
- return m_nff;
- }
+ NativeFieldDescriptor& operator=(const NativeFieldDescriptor& other);
- //
- // Methods for saving & restoring in prejitted images:
- //
+ ~NativeFieldDescriptor() = default;
-#ifdef FEATURE_PREJIT
- void SaveImpl(DataImage *image)
+#if defined(FEATURE_PREJIT) && !defined(DACCESS_COMPILE)
+ void Save(DataImage * image)
{
STANDARD_VM_CONTRACT;
}
- void FixupImpl(DataImage *image)
+ void Fixup(DataImage * image)
{
STANDARD_VM_CONTRACT;
image->FixupFieldDescPointer(this, &m_pFD);
- }
-#endif // FEATURE_PREJIT
- void RestoreImpl()
- {
- CONTRACTL
+ if (m_isNestedType)
{
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
+ image->FixupMethodTablePointer(this, &m_pNestedType);
}
- CONTRACTL_END;
-
-#ifdef FEATURE_PREJIT
- Module::RestoreFieldDescPointer(&m_pFD);
-#endif // FEATURE_PREJIT
- }
-
- void CopyToImpl(VOID *pDest, SIZE_T destSize) const
- {
- FieldMarshaler *pDestFieldMarshaller = (FieldMarshaler *) pDest;
-
- _ASSERTE(sizeof(*pDestFieldMarshaller) <= destSize);
-
- pDestFieldMarshaller->SetFieldDesc(GetFieldDesc());
- pDestFieldMarshaller->SetExternalOffset(GetExternalOffset());
- pDestFieldMarshaller->SetNStructFieldType(GetNStructFieldType());
- pDestFieldMarshaller->SetNativeFieldFlags(GetNativeFieldFlags());
}
+#endif // defined(FEATURE_PREJIT) && !defined(DACCESS_COMPILE)
- void SetFieldDesc(FieldDesc* pFD)
- {
- LIMITED_METHOD_CONTRACT;
- m_pFD.SetValueMaybeNull(pFD);
- }
-
- FieldDesc* GetFieldDesc() const
- {
- CONTRACT (FieldDesc*)
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
- }
- CONTRACT_END;
+#ifdef _DEBUG
+ BOOL IsRestored() const;
+#endif
- RETURN m_pFD.GetValueMaybeNull();
- }
+ void Restore();
- void SetExternalOffset(UINT32 dwExternalOffset)
+ NativeFieldFlags GetNativeFieldFlags() const
{
- LIMITED_METHOD_CONTRACT;
- m_dwExternalOffset = dwExternalOffset;
+ return m_flags;
}
- UINT32 GetExternalOffset() const
- {
- LIMITED_METHOD_CONTRACT;
- return m_dwExternalOffset;
- }
-
-protected:
- FieldMarshaler()
- {
- LIMITED_METHOD_CONTRACT;
-
-#ifdef _DEBUG
- m_dwExternalOffset = 0xcccccccc;
-#endif
- }
+ PTR_MethodTable GetNestedNativeMethodTable() const;
- static inline void RestoreHelper(RelativeFixupPointer<PTR_MethodTable> *ppMT)
+ ULONG GetNumElements() const
{
CONTRACTL
{
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- PRECONDITION(CheckPointer(ppMT));
+ PRECONDITION(m_isNestedType);
}
CONTRACTL_END;
-#ifdef FEATURE_PREJIT
- Module::RestoreMethodTablePointer(ppMT);
-#else // FEATURE_PREJIT
- // without NGEN we only have to make sure that the type is fully loaded
- MethodTable* pMT = ppMT->GetValue();
- if (pMT != NULL)
- ClassLoader::EnsureLoaded(pMT);
-#endif // FEATURE_PREJIT
+ return m_numElements;
}
-#ifdef _DEBUG
- static inline BOOL IsRestoredHelper(const RelativeFixupPointer<PTR_MethodTable> &pMT)
+ UINT32 NativeSize() const
{
- WRAPPER_NO_CONTRACT;
-
-#ifdef FEATURE_PREJIT
- return pMT.IsNull() || (!pMT.IsTagged() && pMT.GetValue()->IsRestored());
-#else // FEATURE_PREJIT
- // putting the IsFullyLoaded check here is tempting but incorrect
- return TRUE;
-#endif // FEATURE_PREJIT
+ if (m_isNestedType)
+ {
+ return GetNestedNativeMethodTable()->GetLayoutInfo()->GetNativeSize() * GetNumElements();
+ }
+ else
+ {
+ return m_nativeSize;
+ }
}
-#endif // _DEBUG
- RelativeFixupPointer<PTR_FieldDesc> m_pFD; // FieldDesc
- UINT32 m_dwExternalOffset; // offset of field in the fixed portion
- NStructFieldType m_nft;
- NativeFieldFlags m_nff = (NativeFieldFlags)0;
-};
-
-class FieldMarshaler_NestedType : public FieldMarshaler
-{
-public:
- MethodTable* GetNestedNativeMethodTable() const;
- UINT32 GetNumElements() const;
- UINT32 GetNumElementsImpl() const
+ UINT32 AlignmentRequirement() const
{
- return 1;
+ if (m_isNestedType)
+ {
+ return GetNestedNativeMethodTable()->GetLayoutInfo()->GetLargestAlignmentRequirementOfAllMembers();
+ }
+ else
+ {
+ return m_alignmentRequirement;
+ }
}
-};
-
-//=======================================================================
-// BSTR <--> System.String
-//=======================================================================
-class FieldMarshaler_BSTR : public FieldMarshaler
-{
-public:
- static constexpr NStructFieldType s_nft = NFT_BSTR;
-
- VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const;
- VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const;
- VOID DestroyNativeImpl(LPVOID pNativeValue) const;
-
- ELEMENT_SIZE_IMPL(sizeof(BSTR), sizeof(BSTR))
- COPY_TO_IMPL_BASE_STRUCT_ONLY()
-};
-
-#ifdef FEATURE_COMINTEROP
-//=======================================================================
-// HSTRING <--> System.String
-//=======================================================================
-class FieldMarshaler_HSTRING : public FieldMarshaler
-{
-public:
- static constexpr NStructFieldType s_nft = NFT_HSTRING;
- VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const;
- VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const;
- VOID DestroyNativeImpl(LPVOID pNativeValue) const;
- ELEMENT_SIZE_IMPL(sizeof(HSTRING), sizeof(HSTRING))
- COPY_TO_IMPL_BASE_STRUCT_ONLY()
-};
+ PTR_FieldDesc GetFieldDesc() const;
-//=======================================================================
-// Windows.Foundation.IReference`1 <--> System.Nullable`1
-//=======================================================================
-class FieldMarshaler_Nullable : public FieldMarshaler
-{
-public:
- static constexpr NStructFieldType s_nft = NFT_WINDOWSFOUNDATIONIREFERENCE;
+ void SetFieldDesc(PTR_FieldDesc pFD);
- FieldMarshaler_Nullable(MethodTable* pMT)
+ UINT32 GetExternalOffset() const
{
- m_pNullableTypeMT.SetValueMaybeNull(pMT);
+ return m_offset;
}
- BOOL IsNullableMarshalerImpl() const
+ void SetExternalOffset(UINT32 offset)
{
- LIMITED_METHOD_CONTRACT;
- return TRUE;
+ m_offset = offset;
}
- //UnImplementedMethods.
- UNUSED_METHOD_IMPL(VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const)
- UNUSED_METHOD_IMPL(VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const)
-
- ELEMENT_SIZE_IMPL(sizeof(IUnknown*), sizeof(IUnknown*))
-
- //ImplementedMethods
- VOID ScalarUpdateNativeImpl(LPVOID pCLR, LPVOID pNative) const;
- VOID ScalarUpdateCLRImpl(const VOID *pNative, LPVOID pCLR) const;
- VOID DestroyNativeImpl(const VOID* pNativeValue) const;
- MethodDesc* GetMethodDescForGenericInstantiation(MethodDesc* pMD) const;
-
- BOOL IsScalarMarshalerImpl() const
+ BOOL IsUnmarshalable() const
{
- LIMITED_METHOD_CONTRACT;
- return TRUE;
+ return m_flags == NATIVE_FIELD_CATEGORY_ILLEGAL ? TRUE : FALSE;
}
-#ifdef FEATURE_PREJIT
- void FixupImpl(DataImage *image)
+ BOOL IsBlittable() const
{
- STANDARD_VM_CONTRACT;
-
- image->FixupMethodTablePointer(this, &m_pNullableTypeMT);
-
- FieldMarshaler::FixupImpl(image);
+ return m_flags & NATIVE_FIELD_SUBCATEGORY_BLITTABLE ? TRUE : FALSE;
}
-#endif // FEATURE_PREJIT
- void RestoreImpl()
+private:
+ RelativeFixupPointer<PTR_FieldDesc> m_pFD;
+ union
{
- CONTRACTL
+ struct
{
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- RestoreHelper(&m_pNullableTypeMT);
-
- FieldMarshaler::RestoreImpl();
- }
-
- START_COPY_TO_IMPL(FieldMarshaler_Nullable)
- {
- pDestFieldMarshaller->m_pNullableTypeMT.SetValueMaybeNull(GetMethodTable());
- }
- END_COPY_TO_IMPL(FieldMarshaler_Nullable)
-
-#ifdef _DEBUG
- BOOL IsRestored() const
- {
- WRAPPER_NO_CONTRACT;
-
- return IsRestoredHelper(m_pNullableTypeMT);
- }
-#endif
-
- MethodTable *GetMethodTable() const
- {
- CONTRACTL
+ RelativeFixupPointer<PTR_MethodTable> m_pNestedType;
+ ULONG m_numElements;
+ };
+ struct
{
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(IsRestored());
- }
- CONTRACTL_END;
-
- return m_pNullableTypeMT.GetValue();
- }
-
-private:
- RelativeFixupPointer<PTR_MethodTable> m_pNullableTypeMT;
+ UINT32 m_nativeSize;
+ UINT32 m_alignmentRequirement;
+ };
+ };
+ UINT32 m_offset;
+ NativeFieldFlags m_flags;
+ bool m_isNestedType;
};
-
//=======================================================================
-// Windows.UI.Xaml.Interop.TypeName <--> System.Type
+// The classloader stores an intermediate representation of the layout
+// metadata in an array of these structures. The dual-pass nature
+// is a bit extra overhead but building this structure requiring loading
+// other classes (for nested structures) and I'd rather keep this
+// next to the other places where we load other classes (e.g. the superclass
+// and implemented interfaces.)
+//
+// Each redirected field gets one entry in LayoutRawFieldInfo.
+// The array is terminated by one dummy record whose m_MD == mdMemberDefNil.
//=======================================================================
-class FieldMarshaler_SystemType : public FieldMarshaler
+struct LayoutRawFieldInfo
{
-public:
- static constexpr NStructFieldType s_nft = NFT_SYSTEMTYPE;
+ mdFieldDef m_MD; // mdMemberDefNil for end of array
+ RawFieldPlacementInfo m_nativePlacement; // Description of the native field placement
+ ULONG m_sequence; // sequence # from metadata
- VOID UpdateNativeImpl(OBJECTREF * pCLRValue, LPVOID pNativeValue, OBJECTREF * ppCleanupWorkListOnStack) const;
- VOID UpdateCLRImpl(const VOID * pNativeValue, OBJECTREF * ppProtectedCLRValue, OBJECTREF * ppProtectedOldCLRValue) const;
- VOID DestroyNativeImpl(LPVOID pNativeValue) const;
-
- ELEMENT_SIZE_IMPL(sizeof(HSTRING), sizeof(HSTRING))
- COPY_TO_IMPL_BASE_STRUCT_ONLY()
-};
-//=======================================================================
-// Windows.Foundation.HResult <--> System.Exception
-// Note: The WinRT struct has exactly 1 field, Value (an HRESULT)
-//=======================================================================
-class FieldMarshaler_Exception : public FieldMarshaler
-{
-public:
- static constexpr NStructFieldType s_nft = NFT_WINDOWSFOUNDATIONHRESULT;
-
- VOID UpdateNativeImpl(OBJECTREF * pCLRValue, LPVOID pNativeValue, OBJECTREF * ppCleanupWorkListOnStack) const;
- VOID UpdateCLRImpl(const VOID * pNativeValue, OBJECTREF * ppProtectedCLRValue, OBJECTREF * ppProtectedOldCLRValue) const;
-
- ELEMENT_SIZE_IMPL(sizeof(HRESULT), sizeof(HRESULT))
- COPY_TO_IMPL_BASE_STRUCT_ONLY()
-};
-
-#endif // FEATURE_COMINTEROP
-
-//=======================================================================
-// Embedded struct <--> LayoutClass
-//=======================================================================
-class FieldMarshaler_NestedLayoutClass : public FieldMarshaler_NestedType
-{
-public:
- static constexpr NStructFieldType s_nft = NFT_NESTEDLAYOUTCLASS;
-
- FieldMarshaler_NestedLayoutClass(MethodTable *pMT)
- {
- WRAPPER_NO_CONTRACT;
- m_pNestedMethodTable.SetValueMaybeNull(pMT);
- }
-
- VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const;
- VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const;
- VOID DestroyNativeImpl(LPVOID pNativeValue) const;
-
- UINT32 NativeSizeImpl() const;
- UINT32 AlignmentRequirementImpl() const;
-
-#ifdef FEATURE_PREJIT
- void FixupImpl(DataImage *image)
- {
- STANDARD_VM_CONTRACT;
-
- image->FixupMethodTablePointer(this, &m_pNestedMethodTable);
-
- FieldMarshaler::FixupImpl(image);
- }
-#endif // FEATURE_PREJIT
-
- void RestoreImpl()
- {
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- RestoreHelper(&m_pNestedMethodTable);
-
- FieldMarshaler::RestoreImpl();
- }
-
- START_COPY_TO_IMPL(FieldMarshaler_NestedLayoutClass)
- {
- pDestFieldMarshaller->m_pNestedMethodTable.SetValueMaybeNull(GetMethodTable());
- }
- END_COPY_TO_IMPL(FieldMarshaler_NestedLayoutClass)
-
-#ifdef _DEBUG
- BOOL IsRestored() const
- {
- WRAPPER_NO_CONTRACT;
-
- return IsRestoredHelper(m_pNestedMethodTable);
- }
-#endif
-
- MethodTable *GetMethodTable() const
- {
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(IsRestored());
- }
- CONTRACTL_END;
-
- return m_pNestedMethodTable.GetValueMaybeNull();
- }
-
- MethodTable* GetNestedNativeMethodTableImpl() const
- {
- return GetMethodTable();
- }
-
-private:
- // MethodTable of nested FieldMarshaler.
- RelativeFixupPointer<PTR_MethodTable> m_pNestedMethodTable;
-};
-
-
-//=======================================================================
-// Embedded struct <--> ValueClass
-//=======================================================================
-class FieldMarshaler_NestedValueClass : public FieldMarshaler_NestedType
-{
-public:
- static constexpr NStructFieldType s_nft = NFT_NESTEDVALUECLASS;
-#ifndef _DEBUG
- FieldMarshaler_NestedValueClass(MethodTable *pMT)
-#else
- FieldMarshaler_NestedValueClass(MethodTable *pMT, BOOL isFixedBuffer)
-#endif
- {
- WRAPPER_NO_CONTRACT;
- m_pNestedMethodTable.SetValueMaybeNull(pMT);
-#ifdef _DEBUG
- m_isFixedBuffer = isFixedBuffer;
-#endif
- }
-
- BOOL IsNestedValueClassMarshalerImpl() const
- {
- LIMITED_METHOD_CONTRACT;
- return TRUE;
- }
-
- UNUSED_METHOD_IMPL(VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const)
- UNUSED_METHOD_IMPL(VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const)
-
- VOID DestroyNativeImpl(LPVOID pNativeValue) const;
-
- UINT32 NativeSizeImpl() const;
- UINT32 AlignmentRequirementImpl() const;
- VOID NestedValueClassUpdateNativeImpl(const VOID **ppProtectedCLR, SIZE_T startoffset, LPVOID pNative, OBJECTREF *ppCleanupWorkListOnStack) const;
- VOID NestedValueClassUpdateCLRImpl(const VOID *pNative, LPVOID *ppProtectedCLR, SIZE_T startoffset) const;
-
-#ifdef FEATURE_PREJIT
- void FixupImpl(DataImage *image)
- {
- STANDARD_VM_CONTRACT;
-
- image->FixupMethodTablePointer(this, &m_pNestedMethodTable);
-
- FieldMarshaler::FixupImpl(image);
- }
-#endif // FEATURE_PREJIT
-
- void RestoreImpl()
- {
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- RestoreHelper(&m_pNestedMethodTable);
-
- FieldMarshaler::RestoreImpl();
- }
-
- START_COPY_TO_IMPL(FieldMarshaler_NestedValueClass)
- {
- pDestFieldMarshaller->m_pNestedMethodTable.SetValueMaybeNull(GetMethodTable());
-#ifdef _DEBUG
- pDestFieldMarshaller->m_isFixedBuffer = m_isFixedBuffer;
-#endif
- }
- END_COPY_TO_IMPL(FieldMarshaler_NestedValueClass)
-
-#ifdef _DEBUG
- BOOL IsRestored() const
- {
- WRAPPER_NO_CONTRACT;
-
- return IsRestoredHelper(m_pNestedMethodTable);
- }
-#endif
-
- BOOL IsBlittable()
- {
- WRAPPER_NO_CONTRACT;
- return GetMethodTable()->IsBlittable();
- }
-
- MethodTable *GetMethodTable() const
- {
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(IsRestored());
- }
- CONTRACTL_END;
-
- return m_pNestedMethodTable.GetValueMaybeNull();
- }
-
- MethodTable* GetNestedNativeMethodTableImpl() const
- {
- return GetMethodTable();
- }
-
-#ifdef _DEBUG
- BOOL IsFixedBuffer() const
- {
- return m_isFixedBuffer;
- }
-#endif
-
-
-private:
- // MethodTable of nested NStruct.
- RelativeFixupPointer<PTR_MethodTable> m_pNestedMethodTable;
-#ifdef _DEBUG
- BOOL m_isFixedBuffer;
-#endif
-};
-
-
-//=======================================================================
-// LPWSTR <--> System.String
-//=======================================================================
-class FieldMarshaler_StringUni : public FieldMarshaler
-{
-public:
- static constexpr NStructFieldType s_nft = NFT_STRINGUNI;
-
- VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const;
- VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const;
- VOID DestroyNativeImpl(LPVOID pNativeValue) const;
-
- ELEMENT_SIZE_IMPL(sizeof(LPWSTR), sizeof(LPWSTR))
- COPY_TO_IMPL_BASE_STRUCT_ONLY()
-};
-
-//=======================================================================
-// LPUTF8STR <--> System.String
-//=======================================================================
-class FieldMarshaler_StringUtf8 : public FieldMarshaler
-{
-public:
- static constexpr NStructFieldType s_nft = NFT_STRINGUTF8;
-
- VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const;
- VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const;
- VOID DestroyNativeImpl(LPVOID pNativeValue) const;
-
- ELEMENT_SIZE_IMPL(sizeof(LPSTR), sizeof(LPSTR))
- COPY_TO_IMPL_BASE_STRUCT_ONLY()
-};
-
-//=======================================================================
-// LPSTR <--> System.String
-//=======================================================================
-class FieldMarshaler_StringAnsi : public FieldMarshaler
-{
-public:
- static constexpr NStructFieldType s_nft = NFT_STRINGANSI;
-
- FieldMarshaler_StringAnsi(BOOL BestFit, BOOL ThrowOnUnmappableChar) :
- m_BestFitMap(!!BestFit), m_ThrowOnUnmappableChar(!!ThrowOnUnmappableChar)
- {
- WRAPPER_NO_CONTRACT;
- }
-
- VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const;
- VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const;
- VOID DestroyNativeImpl(LPVOID pNativeValue) const;
-
- ELEMENT_SIZE_IMPL(sizeof(LPSTR), sizeof(LPSTR))
-
- BOOL GetBestFit()
- {
- LIMITED_METHOD_CONTRACT;
- return m_BestFitMap;
- }
-
- BOOL GetThrowOnUnmappableChar()
- {
- LIMITED_METHOD_CONTRACT;
- return m_ThrowOnUnmappableChar;
- }
-
- START_COPY_TO_IMPL(FieldMarshaler_StringAnsi)
- {
- pDestFieldMarshaller->m_BestFitMap = m_BestFitMap;
- pDestFieldMarshaller->m_ThrowOnUnmappableChar = m_ThrowOnUnmappableChar;
- }
- END_COPY_TO_IMPL(FieldMarshaler_StringAnsi)
-
-private:
- bool m_BestFitMap:1;
- bool m_ThrowOnUnmappableChar:1;
-};
-
-
-//=======================================================================
-// Embedded LPWSTR <--> System.String
-//=======================================================================
-class FieldMarshaler_FixedStringUni : public FieldMarshaler
-{
-public:
- static constexpr NStructFieldType s_nft = NFT_FIXEDSTRINGUNI;
-
- VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const;
- VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const;
-
- ELEMENT_SIZE_IMPL(m_numchar * sizeof(WCHAR), sizeof(WCHAR))
-
- FieldMarshaler_FixedStringUni(UINT32 numChar)
- {
- WRAPPER_NO_CONTRACT;
- m_numchar = numChar;
- }
-
- START_COPY_TO_IMPL(FieldMarshaler_FixedStringUni)
- {
- pDestFieldMarshaller->m_numchar = m_numchar;
- }
- END_COPY_TO_IMPL(FieldMarshaler_FixedStringUni)
-
-private:
- // # of characters for fixed strings
- UINT32 m_numchar;
-};
-
-
-//=======================================================================
-// Embedded LPSTR <--> System.String
-//=======================================================================
-class FieldMarshaler_FixedStringAnsi : public FieldMarshaler
-{
-public:
- static constexpr NStructFieldType s_nft = NFT_FIXEDSTRINGANSI;
-
- FieldMarshaler_FixedStringAnsi(UINT32 numChar, BOOL BestFitMap, BOOL ThrowOnUnmappableChar) :
- m_numchar(numChar), m_BestFitMap(!!BestFitMap), m_ThrowOnUnmappableChar(!!ThrowOnUnmappableChar)
- {
- WRAPPER_NO_CONTRACT;
- }
-
- VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const;
- VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const;
-
- ELEMENT_SIZE_IMPL(m_numchar * sizeof(CHAR), sizeof(CHAR))
-
- BOOL GetBestFit()
- {
- LIMITED_METHOD_CONTRACT;
- return m_BestFitMap;
- }
-
- BOOL GetThrowOnUnmappableChar()
- {
- LIMITED_METHOD_CONTRACT;
- return m_ThrowOnUnmappableChar;
- }
-
- START_COPY_TO_IMPL(FieldMarshaler_FixedStringAnsi)
- {
- pDestFieldMarshaller->m_numchar = m_numchar;
- pDestFieldMarshaller->m_BestFitMap = m_BestFitMap;
- pDestFieldMarshaller->m_ThrowOnUnmappableChar = m_ThrowOnUnmappableChar;
- }
- END_COPY_TO_IMPL(FieldMarshaler_FixedStringAnsi)
-
-private:
- // # of characters for fixed strings
- UINT32 m_numchar;
- bool m_BestFitMap:1;
- bool m_ThrowOnUnmappableChar:1;
-};
-
-
-//=======================================================================
-// Embedded AnsiChar array <--> char[]
-//=======================================================================
-class FieldMarshaler_FixedCharArrayAnsi : public FieldMarshaler
-{
-public:
- static constexpr NStructFieldType s_nft = NFT_FIXEDCHARARRAYANSI;
-
- FieldMarshaler_FixedCharArrayAnsi(UINT32 numElems, BOOL BestFit, BOOL ThrowOnUnmappableChar) :
- m_numElems(numElems), m_BestFitMap(!!BestFit), m_ThrowOnUnmappableChar(!!ThrowOnUnmappableChar)
- {
- WRAPPER_NO_CONTRACT;
- }
-
- VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const;
- VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const;
-
- ELEMENT_SIZE_IMPL(m_numElems * sizeof(CHAR), sizeof(CHAR))
-
- BOOL GetBestFit()
- {
- LIMITED_METHOD_CONTRACT;
- return m_BestFitMap;
- }
-
- BOOL GetThrowOnUnmappableChar()
- {
- LIMITED_METHOD_CONTRACT;
- return m_ThrowOnUnmappableChar;
- }
-
- START_COPY_TO_IMPL(FieldMarshaler_FixedCharArrayAnsi)
- {
- pDestFieldMarshaller->m_numElems = m_numElems;
- pDestFieldMarshaller->m_BestFitMap = m_BestFitMap;
- pDestFieldMarshaller->m_ThrowOnUnmappableChar = m_ThrowOnUnmappableChar;
- }
- END_COPY_TO_IMPL(FieldMarshaler_FixedCharArrayAnsi)
-
-private:
- // # of elements for fixedchararray
- UINT32 m_numElems;
- bool m_BestFitMap:1;
- bool m_ThrowOnUnmappableChar:1;
-};
-
-
-//=======================================================================
-// Embedded arrays
-//=======================================================================
-class FieldMarshaler_FixedArray : public FieldMarshaler_NestedType
-{
-public:
- static constexpr NStructFieldType s_nft = NFT_FIXEDARRAY;
-
- FieldMarshaler_FixedArray(Module *pModule, mdTypeDef cl, UINT32 numElems, VARTYPE vt, MethodTable* pElementMT);
-
- VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const;
- VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const;
- VOID DestroyNativeImpl(LPVOID pNativeValue) const;
- UINT32 AlignmentRequirementImpl() const;
-
- UINT32 NativeSizeImpl() const
- {
- LIMITED_METHOD_CONTRACT;
-
- return OleVariant::GetElementSizeForVarType(m_vt, GetElementMethodTable()) * m_numElems;
- }
-
- UINT32 GetNumElementsImpl() const
- {
- return m_numElems;
- }
-
- MethodTable* GetElementMethodTable() const
- {
- return GetElementTypeHandle().GetMethodTable();
- }
-
- TypeHandle GetElementTypeHandle() const
- {
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(IsRestored());
- }
- CONTRACTL_END;
-
- return m_arrayType.GetValue().AsArray()->GetArrayElementTypeHandle();
- }
-
- MethodTable* GetNestedNativeMethodTableImpl() const
- {
- return OleVariant::GetNativeMethodTableForVarType(m_vt, GetElementMethodTable());
- }
-
- VARTYPE GetElementVT() const
- {
- LIMITED_METHOD_CONTRACT;
- return m_vt;
- }
-
-#ifdef FEATURE_PREJIT
- void FixupImpl(DataImage *image)
- {
- STANDARD_VM_CONTRACT;
-
- image->FixupTypeHandlePointer(this, &m_arrayType);
-
- FieldMarshaler::FixupImpl(image);
- }
-#endif // FEATURE_PREJIT
-
- void RestoreImpl()
- {
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- }
- CONTRACTL_END;
-
-#ifdef FEATURE_PREJIT
- Module::RestoreTypeHandlePointer(&m_arrayType);
-#else // FEATURE_PREJIT
- // without NGEN we only have to make sure that the type is fully loaded
- TypeHandle th = m_arrayType.GetValue();
- if (!th.IsNull())
- ClassLoader::EnsureLoaded(th);
-#endif // FEATURE_PREJIT
- FieldMarshaler::RestoreImpl();
- }
-
- START_COPY_TO_IMPL(FieldMarshaler_FixedArray)
- {
- pDestFieldMarshaller->m_arrayType.SetValueMaybeNull(m_arrayType.GetValueMaybeNull());
- pDestFieldMarshaller->m_numElems = m_numElems;
- pDestFieldMarshaller->m_vt = m_vt;
- pDestFieldMarshaller->m_BestFitMap = m_BestFitMap;
- pDestFieldMarshaller->m_ThrowOnUnmappableChar = m_ThrowOnUnmappableChar;
- }
- END_COPY_TO_IMPL(FieldMarshaler_FixedArray)
-
-#ifdef _DEBUG
- BOOL IsRestored() const
- {
- WRAPPER_NO_CONTRACT;
-
-#ifdef FEATURE_PREJIT
- return !m_arrayType.IsTagged() && (m_arrayType.IsNull() || m_arrayType.GetValue().IsRestored());
-#else // FEATURE_PREJIT
- // putting the IsFullyLoaded check here is tempting but incorrect
- return TRUE;
-#endif // FEATURE_PREJIT
- }
-#endif
-
-private:
- RelativeFixupPointer<TypeHandle> m_arrayType;
- UINT32 m_numElems;
- VARTYPE m_vt;
- bool m_BestFitMap:1; // Note: deliberately use small bools to save on working set - this is the largest FieldMarshaler and dominates the cost of the FieldMarshaler array
- bool m_ThrowOnUnmappableChar:1; // Note: deliberately use small bools to save on working set - this is the largest FieldMarshaler and dominates the cost of the FieldMarshaler array
-};
-
-
-#ifdef FEATURE_CLASSIC_COMINTEROP
-//=======================================================================
-// SafeArrays
-//=======================================================================
-class FieldMarshaler_SafeArray : public FieldMarshaler
-{
-public:
- static constexpr NStructFieldType s_nft = NFT_SAFEARRAY;
-
- VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const;
- VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const;
- VOID DestroyNativeImpl(LPVOID pNativeValue) const;
-
- ELEMENT_SIZE_IMPL(sizeof(LPSAFEARRAY), sizeof(LPSAFEARRAY))
-
- FieldMarshaler_SafeArray(VARTYPE vt, MethodTable* pMT)
- {
- WRAPPER_NO_CONTRACT;
- m_vt = vt;
- m_pMT.SetValueMaybeNull(pMT);
- }
-
-#ifdef FEATURE_PREJIT
- void FixupImpl(DataImage *image)
- {
- STANDARD_VM_CONTRACT;
-
- image->FixupMethodTablePointer(this, &m_pMT);
-
- FieldMarshaler::FixupImpl(image);
- }
-#endif // FEATURE_PREJIT
-
- void RestoreImpl()
- {
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- RestoreHelper(&m_pMT);
-
- FieldMarshaler::RestoreImpl();
- }
-
- START_COPY_TO_IMPL(FieldMarshaler_SafeArray)
- {
- pDestFieldMarshaller->m_pMT.SetValueMaybeNull(m_pMT.GetValueMaybeNull());
- pDestFieldMarshaller->m_vt = m_vt;
- }
- END_COPY_TO_IMPL(FieldMarshaler_SafeArray)
-
-#ifdef _DEBUG
- BOOL IsRestored() const
- {
- WRAPPER_NO_CONTRACT;
-
- return IsRestoredHelper(m_pMT);
- }
-#endif
-
- TypeHandle GetElementTypeHandle() const
- {
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(IsRestored());
- }
- CONTRACTL_END;
-
- return TypeHandle(m_pMT.GetValue());
- }
-
- VARTYPE GetElementVT() const
- {
- LIMITED_METHOD_CONTRACT;
- return m_vt;
- }
-
-private:
- RelativeFixupPointer<PTR_MethodTable> m_pMT;
- VARTYPE m_vt;
-};
-#endif //FEATURE_CLASSIC_COMINTEROP
-
-
-//=======================================================================
-// Embedded function ptr <--> Delegate
-//=======================================================================
-class FieldMarshaler_Delegate : public FieldMarshaler
-{
-public:
- static constexpr NStructFieldType s_nft = NFT_DELEGATE;
-
- FieldMarshaler_Delegate(MethodTable* pMT)
- {
- WRAPPER_NO_CONTRACT;
- m_pNestedMethodTable.SetValueMaybeNull(pMT);
- }
-
- VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const;
- VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const;
-
- ELEMENT_SIZE_IMPL(sizeof(LPVOID), sizeof(LPVOID))
-
-#ifdef FEATURE_PREJIT
- void FixupImpl(DataImage *image)
- {
- STANDARD_VM_CONTRACT;
-
- image->FixupMethodTablePointer(this, &m_pNestedMethodTable);
-
- FieldMarshaler::FixupImpl(image);
- }
-#endif // FEATURE_PREJIT
-
- void RestoreImpl()
- {
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- RestoreHelper(&m_pNestedMethodTable);
-
- FieldMarshaler::RestoreImpl();
- }
-
- START_COPY_TO_IMPL(FieldMarshaler_Delegate)
- {
- pDestFieldMarshaller->m_pNestedMethodTable.SetValueMaybeNull(m_pNestedMethodTable.GetValueMaybeNull());
- }
- END_COPY_TO_IMPL(FieldMarshaler_Delegate)
-
-#ifdef _DEBUG
- BOOL IsRestored() const
- {
- WRAPPER_NO_CONTRACT;
-
- return IsRestoredHelper(m_pNestedMethodTable);
- }
-#endif
-
- MethodTable *GetMethodTable() const
- {
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(IsRestored());
- }
- CONTRACTL_END;
-
- return m_pNestedMethodTable.GetValueMaybeNull();
- }
-
- RelativeFixupPointer<PTR_MethodTable> m_pNestedMethodTable;
-};
-
-
-//=======================================================================
-// Embedded SafeHandle <--> Handle. This field really only supports
-// going from managed to unmanaged. In the other direction, we only
-// check that the handle value has not changed.
-//=======================================================================
-class FieldMarshaler_SafeHandle : public FieldMarshaler
-{
-public:
- static constexpr NStructFieldType s_nft = NFT_SAFEHANDLE;
-
- VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const;
- VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const;
-
- ELEMENT_SIZE_IMPL(sizeof(LPVOID), sizeof(LPVOID))
- COPY_TO_IMPL_BASE_STRUCT_ONLY()
-};
-
-
-//=======================================================================
-// Embedded CriticalHandle <--> Handle. This field really only supports
-// going from managed to unmanaged. In the other direction, we only
-// check that the handle value has not changed.
-//=======================================================================
-class FieldMarshaler_CriticalHandle : public FieldMarshaler
-{
-public:
- static constexpr NStructFieldType s_nft = NFT_CRITICALHANDLE;
-
- VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const;
- VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const;
-
- ELEMENT_SIZE_IMPL(sizeof(LPVOID), sizeof(LPVOID))
- COPY_TO_IMPL_BASE_STRUCT_ONLY()
-};
-
-#ifdef FEATURE_COMINTEROP
-
-//=======================================================================
-// COM IP <--> Interface
-//=======================================================================
-class FieldMarshaler_Interface : public FieldMarshaler
-{
-public:
- static constexpr NStructFieldType s_nft = NFT_INTERFACE;
-
- VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const;
- VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const;
- VOID DestroyNativeImpl(LPVOID pNativeValue) const;
-
- ELEMENT_SIZE_IMPL(sizeof(IUnknown*), sizeof(IUnknown*))
-
- FieldMarshaler_Interface(MethodTable *pClassMT, MethodTable *pItfMT, DWORD dwFlags)
- {
- WRAPPER_NO_CONTRACT;
- m_pClassMT.SetValueMaybeNull(pClassMT);
- m_pItfMT.SetValueMaybeNull(pItfMT);
- m_dwFlags = dwFlags;
- }
-
-#ifdef FEATURE_PREJIT
- void FixupImpl(DataImage *image)
- {
- STANDARD_VM_CONTRACT;
-
- image->FixupMethodTablePointer(this, &m_pClassMT);
- image->FixupMethodTablePointer(this, &m_pItfMT);
-
- FieldMarshaler::FixupImpl(image);
- }
-#endif // FEATURE_PREJIT
-
- void RestoreImpl()
- {
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- RestoreHelper(&m_pClassMT);
- RestoreHelper(&m_pItfMT);
-
- FieldMarshaler::RestoreImpl();
- }
-
- START_COPY_TO_IMPL(FieldMarshaler_Interface)
- {
- pDestFieldMarshaller->m_pClassMT.SetValueMaybeNull(m_pClassMT.GetValueMaybeNull());
- pDestFieldMarshaller->m_pItfMT.SetValueMaybeNull(m_pItfMT.GetValueMaybeNull());
- pDestFieldMarshaller->m_dwFlags = m_dwFlags;
- }
- END_COPY_TO_IMPL(FieldMarshaler_Interface)
-
-#ifdef _DEBUG
- BOOL IsRestored() const
- {
- WRAPPER_NO_CONTRACT;
-
- return (IsRestoredHelper(m_pClassMT) && IsRestoredHelper(m_pItfMT));
- }
-#endif
-
- void GetInterfaceInfo(MethodTable **ppItfMT, DWORD* pdwFlags) const
- {
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(CheckPointer(ppItfMT));
-#ifdef FEATURE_PREJIT
- PRECONDITION(IsRestored());
-#endif
- }
- CONTRACTL_END;
-
- *ppItfMT = m_pItfMT.GetValue();
- *pdwFlags = m_dwFlags;
- }
-
- MethodTable *GetMethodTable() const
- {
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(IsRestored());
- }
- CONTRACTL_END;
-
- return m_pClassMT.GetValueMaybeNull();
- }
-
- MethodTable *GetInterfaceMethodTable() const
- {
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(IsRestored());
- }
- CONTRACTL_END;
-
- return m_pItfMT.GetValueMaybeNull();
- }
-
-private:
- RelativeFixupPointer<PTR_MethodTable> m_pClassMT;
- RelativeFixupPointer<PTR_MethodTable> m_pItfMT;
- DWORD m_dwFlags;
-};
-
-#endif // FEATURE_COMINTEROP
-
-#ifdef FEATURE_COMINTEROP
-// This compile-time assert checks that the above FieldMarshaler is the biggest
-// (or equal-biggest) FieldMasharler we have,
-// i.e. that we haven't set MAXFIELDMARSHALERSIZE to a value that is needlessly big.
-// Corresponding asserts in FieldMarshaler.cpp ensure that we haven't set it to a value that is needlessly
-// big, which would waste a whole lot of memory given the current storage scheme for FMs.
-//
-// If this assert first, it probably means you have successully reduced the size of the above FieldMarshaler.
-// You should now place this assert on the FieldMarshaler that is the biggest, or modify MAXFIELDMARSHALERSIZE
-// to match the new size.
-static_assert_no_msg(sizeof(FieldMarshaler_Interface) == MAXFIELDMARSHALERSIZE);
-
-#endif // FEATURE_COMINTEROP
-
-#ifdef FEATURE_COMINTEROP
-
-//=======================================================================
-// VARIANT <--> Object
-//=======================================================================
-class FieldMarshaler_Variant : public FieldMarshaler
-{
-public:
- static constexpr NStructFieldType s_nft = NFT_VARIANT;
-
- VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const;
- VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const;
- VOID DestroyNativeImpl(LPVOID pNativeValue) const;
-
- ELEMENT_SIZE_IMPL(sizeof(VARIANT), 8)
- COPY_TO_IMPL_BASE_STRUCT_ONLY()
-};
-
-#endif // FEATURE_COMINTEROP
-
-
-//=======================================================================
-// Dummy marshaler
-//=======================================================================
-class FieldMarshaler_Illegal : public FieldMarshaler
-{
-public:
- static constexpr NStructFieldType s_nft = NFT_ILLEGAL;
-
- FieldMarshaler_Illegal(UINT resIDWhy)
- {
- WRAPPER_NO_CONTRACT;
- m_resIDWhy = resIDWhy;
- }
-
- UNUSED_METHOD_IMPL(VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const)
- UNUSED_METHOD_IMPL(VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const)
-
- VOID ScalarUpdateNativeImpl(LPVOID pCLR, LPVOID pNative) const;
- VOID ScalarUpdateCLRImpl(const VOID *pNative, LPVOID pCLR) const;
-
- SCALAR_MARSHALER_IMPL(1, 1)
-
- START_COPY_TO_IMPL(FieldMarshaler_Illegal)
- {
- pDestFieldMarshaller->m_resIDWhy = m_resIDWhy;
- }
- END_COPY_TO_IMPL(FieldMarshaler_Illegal)
-
-private:
- UINT m_resIDWhy;
-};
-
-
-#define FIELD_MARSHALER_COPY
-
-
-class FieldMarshaler_Copy1 : public FieldMarshaler
-{
-public:
- static constexpr NStructFieldType s_nft = NFT_COPY1;
-
- UNUSED_METHOD_IMPL(VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const)
- UNUSED_METHOD_IMPL(VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const)
-
- SCALAR_MARSHALER_IMPL(1, 1)
- COPY_TO_IMPL_BASE_STRUCT_ONLY()
-
- VOID ScalarUpdateNativeImpl(LPVOID pCLR, LPVOID pNative) const
- {
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(CheckPointer(pCLR));
- PRECONDITION(CheckPointer(pNative));
- }
- CONTRACTL_END;
-
- *((U1*)pNative) = *((U1*)pCLR);
- }
-
-
- VOID ScalarUpdateCLRImpl(const VOID *pNative, LPVOID pCLR) const
- {
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(CheckPointer(pCLR));
- PRECONDITION(CheckPointer(pNative));
- }
- CONTRACTL_END;
-
- *((U1*)pCLR) = *((U1*)pNative);
- }
-
-};
-
-
-
-class FieldMarshaler_Copy2 : public FieldMarshaler
-{
-public:
- static constexpr NStructFieldType s_nft = NFT_COPY2;
-
- UNUSED_METHOD_IMPL(VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const)
- UNUSED_METHOD_IMPL(VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const)
-
- SCALAR_MARSHALER_IMPL(2, 2)
- COPY_TO_IMPL_BASE_STRUCT_ONLY()
-
- VOID ScalarUpdateNativeImpl(LPVOID pCLR, LPVOID pNative) const
- {
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(CheckPointer(pCLR));
- PRECONDITION(CheckPointer(pNative));
- }
- CONTRACTL_END;
-
- MAYBE_UNALIGNED_WRITE(pNative, 16, MAYBE_UNALIGNED_READ(pCLR, 16));
- }
-
-
- VOID ScalarUpdateCLRImpl(const VOID *pNative, LPVOID pCLR) const
- {
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(CheckPointer(pCLR));
- PRECONDITION(CheckPointer(pNative));
- }
- CONTRACTL_END;
-
- MAYBE_UNALIGNED_WRITE(pCLR, 16, MAYBE_UNALIGNED_READ(pNative, 16));
- }
-
-};
-
-
-class FieldMarshaler_Copy4 : public FieldMarshaler
-{
-public:
- static constexpr NStructFieldType s_nft = NFT_COPY4;
-
- UNUSED_METHOD_IMPL(VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const)
- UNUSED_METHOD_IMPL(VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const)
-
- SCALAR_MARSHALER_IMPL(4, 4)
- COPY_TO_IMPL_BASE_STRUCT_ONLY()
-
- VOID ScalarUpdateNativeImpl(LPVOID pCLR, LPVOID pNative) const
- {
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(CheckPointer(pCLR));
- PRECONDITION(CheckPointer(pNative));
- }
- CONTRACTL_END;
-
- MAYBE_UNALIGNED_WRITE(pNative, 32, MAYBE_UNALIGNED_READ(pCLR, 32));
- }
-
-
- VOID ScalarUpdateCLRImpl(const VOID *pNative, LPVOID pCLR) const
- {
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(CheckPointer(pCLR));
- PRECONDITION(CheckPointer(pNative));
- }
- CONTRACTL_END;
-
- MAYBE_UNALIGNED_WRITE(pCLR, 32, MAYBE_UNALIGNED_READ(pNative, 32));
- }
-
-};
-
-
-class FieldMarshaler_Copy8 : public FieldMarshaler
-{
-public:
- static constexpr NStructFieldType s_nft = NFT_COPY8;
-
- UNUSED_METHOD_IMPL(VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const)
- UNUSED_METHOD_IMPL(VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const)
-
-#if defined(_TARGET_X86_) && defined(UNIX_X86_ABI)
- // The System V ABI for i386 defines 4-byte alignment for 64-bit types.
- SCALAR_MARSHALER_IMPL(8, 4)
-#else
- SCALAR_MARSHALER_IMPL(8, 8)
-#endif // _TARGET_X86_
-
- COPY_TO_IMPL_BASE_STRUCT_ONLY()
-
- VOID ScalarUpdateNativeImpl(LPVOID pCLR, LPVOID pNative) const
- {
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(CheckPointer(pCLR));
- PRECONDITION(CheckPointer(pNative));
- }
- CONTRACTL_END;
-
- MAYBE_UNALIGNED_WRITE(pNative, 64, MAYBE_UNALIGNED_READ(pCLR, 64));
- }
-
-
- VOID ScalarUpdateCLRImpl(const VOID *pNative, LPVOID pCLR) const
- {
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(CheckPointer(pCLR));
- PRECONDITION(CheckPointer(pNative));
- }
- CONTRACTL_END;
-
- MAYBE_UNALIGNED_WRITE(pCLR, 64, MAYBE_UNALIGNED_READ(pNative, 64));
- }
-
-};
-
-
-
-class FieldMarshaler_Ansi : public FieldMarshaler
-{
-public:
- static constexpr NStructFieldType s_nft = NFT_ANSICHAR;
-
- FieldMarshaler_Ansi(BOOL BestFitMap, BOOL ThrowOnUnmappableChar) :
- m_BestFitMap(!!BestFitMap), m_ThrowOnUnmappableChar(!!ThrowOnUnmappableChar)
- {
- WRAPPER_NO_CONTRACT;
- }
-
- UNUSED_METHOD_IMPL(VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const)
- UNUSED_METHOD_IMPL(VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const)
-
- SCALAR_MARSHALER_IMPL(sizeof(CHAR), sizeof(CHAR))
-
- VOID ScalarUpdateNativeImpl(LPVOID pCLR, LPVOID pNative) const
- {
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- PRECONDITION(CheckPointer(pCLR, NULL_OK));
- PRECONDITION(CheckPointer(pNative));
- }
- CONTRACTL_END;
-
- char c;
- InternalWideToAnsi((LPCWSTR)pCLR,
- 1,
- &c,
- 1,
- m_BestFitMap,
- m_ThrowOnUnmappableChar);
-
- *((char*)pNative) = c;
- }
-
- VOID ScalarUpdateCLRImpl(const VOID *pNative, LPVOID pCLR) const
- {
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(CheckPointer(pCLR));
- PRECONDITION(CheckPointer(pNative));
- }
- CONTRACTL_END;
-
- MultiByteToWideChar(CP_ACP, 0, (char*)pNative, 1, (LPWSTR)pCLR, 1);
- }
-
- BOOL GetBestFit()
- {
- LIMITED_METHOD_CONTRACT;
- return m_BestFitMap;
- }
-
- BOOL GetThrowOnUnmappableChar()
- {
- LIMITED_METHOD_CONTRACT;
- return m_ThrowOnUnmappableChar;
- }
-
- START_COPY_TO_IMPL(FieldMarshaler_Ansi)
- {
- pDestFieldMarshaller->m_BestFitMap = m_BestFitMap;
- pDestFieldMarshaller->m_ThrowOnUnmappableChar = m_ThrowOnUnmappableChar;
- }
- END_COPY_TO_IMPL(FieldMarshaler_Ansi)
-
-private:
- bool m_BestFitMap:1;
- bool m_ThrowOnUnmappableChar:1;
-};
-
-
-
-class FieldMarshaler_WinBool : public FieldMarshaler
-{
-public:
- static constexpr NStructFieldType s_nft = NFT_WINBOOL;
-
- UNUSED_METHOD_IMPL(VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const)
- UNUSED_METHOD_IMPL(VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const)
-
- SCALAR_MARSHALER_IMPL(sizeof(BOOL), sizeof(BOOL))
- COPY_TO_IMPL_BASE_STRUCT_ONLY()
-
- VOID ScalarUpdateNativeImpl(LPVOID pCLR, LPVOID pNative) const
- {
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(CheckPointer(pCLR));
- PRECONDITION(CheckPointer(pNative));
- }
- CONTRACTL_END;
- static_assert_no_msg(sizeof(BOOL) == sizeof(UINT32));
- MAYBE_UNALIGNED_WRITE(pNative, 32, ((*((U1 UNALIGNED*)pCLR)) ? 1 : 0));
- }
-
-
- VOID ScalarUpdateCLRImpl(const VOID *pNative, LPVOID pCLR) const
- {
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(CheckPointer(pCLR));
- PRECONDITION(CheckPointer(pNative));
- }
- CONTRACTL_END;
-
- static_assert_no_msg(sizeof(BOOL) == sizeof(UINT32));
- *((U1*)pCLR) = MAYBE_UNALIGNED_READ(pNative, 32) ? 1 : 0;
- }
-
-};
-
-
-
-#ifdef FEATURE_COMINTEROP
-
-class FieldMarshaler_VariantBool : public FieldMarshaler
-{
-public:
- static constexpr NStructFieldType s_nft = NFT_VARIANTBOOL;
-
- UNUSED_METHOD_IMPL(VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const)
- UNUSED_METHOD_IMPL(VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const)
-
- SCALAR_MARSHALER_IMPL(sizeof(VARIANT_BOOL), sizeof(VARIANT_BOOL))
- COPY_TO_IMPL_BASE_STRUCT_ONLY()
-
- VOID ScalarUpdateNativeImpl(LPVOID pCLR, LPVOID pNative) const
- {
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(CheckPointer(pCLR));
- PRECONDITION(CheckPointer(pNative));
- }
- CONTRACTL_END;
-
- static_assert_no_msg(sizeof(VARIANT_BOOL) == sizeof(BYTE) * 2);
-
- MAYBE_UNALIGNED_WRITE(pNative, 16, (*((U1*)pCLR)) ? VARIANT_TRUE : VARIANT_FALSE);
- }
-
-
- VOID ScalarUpdateCLRImpl(const VOID *pNative, LPVOID pCLR) const
- {
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(CheckPointer(pCLR));
- PRECONDITION(CheckPointer(pNative));
- }
- CONTRACTL_END;
-
- static_assert_no_msg(sizeof(VARIANT_BOOL) == sizeof(BYTE) * 2);
-
- *((U1*)pCLR) = MAYBE_UNALIGNED_READ(pNative, 16) ? 1 : 0;
- }
-
-};
-
-#endif // FEATURE_COMINTEROP
-
-
-
-class FieldMarshaler_CBool : public FieldMarshaler
-{
-public:
- static constexpr NStructFieldType s_nft = NFT_CBOOL;
-
- UNUSED_METHOD_IMPL(VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const)
- UNUSED_METHOD_IMPL(VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const)
-
- SCALAR_MARSHALER_IMPL(1, 1)
- COPY_TO_IMPL_BASE_STRUCT_ONLY()
-
- VOID ScalarUpdateNativeImpl(LPVOID pCLR, LPVOID pNative) const
- {
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(CheckPointer(pCLR));
- PRECONDITION(CheckPointer(pNative));
- }
- CONTRACTL_END;
-
- *((U1*)pNative) = (*((U1*)pCLR)) ? 1 : 0;
- }
-
- VOID ScalarUpdateCLRImpl(const VOID *pNative, LPVOID pCLR) const
- {
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(CheckPointer(pCLR));
- PRECONDITION(CheckPointer(pNative));
- }
- CONTRACTL_END;
-
- *((U1*)pCLR) = (*((U1*)pNative)) ? 1 : 0;
- }
-
-};
-
-
-class FieldMarshaler_Decimal : public FieldMarshaler_NestedType
-{
-public:
- static constexpr NStructFieldType s_nft = NFT_DECIMAL;
-
- UNUSED_METHOD_IMPL(VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const)
- UNUSED_METHOD_IMPL(VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const)
-
- SCALAR_MARSHALER_IMPL(sizeof(DECIMAL), 8);
- COPY_TO_IMPL_BASE_STRUCT_ONLY()
-
- VOID ScalarUpdateNativeImpl(LPVOID pCLR, LPVOID pNative) const
- {
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(CheckPointer(pCLR));
- PRECONDITION(CheckPointer(pNative));
- }
- CONTRACTL_END;
-
- memcpyNoGCRefs(pNative, pCLR, sizeof(DECIMAL));
- }
-
- VOID ScalarUpdateCLRImpl(const VOID *pNative, LPVOID pCLR) const
- {
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(CheckPointer(pCLR));
- PRECONDITION(CheckPointer(pNative));
- }
- CONTRACTL_END;
-
- memcpyNoGCRefs(pCLR, pNative, sizeof(DECIMAL));
- }
-
- MethodTable* GetNestedNativeMethodTableImpl() const
- {
- return MscorlibBinder::GetClass(CLASS__DECIMAL);
- }
-
-};
-
-class FieldMarshaler_Date : public FieldMarshaler
-{
-public:
- static constexpr NStructFieldType s_nft = NFT_DATE;
-
- UNUSED_METHOD_IMPL(VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const)
- UNUSED_METHOD_IMPL(VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const)
-
- SCALAR_MARSHALER_IMPL(sizeof(DATE), sizeof(DATE))
- COPY_TO_IMPL_BASE_STRUCT_ONLY()
-
- VOID ScalarUpdateNativeImpl(LPVOID pCLR, LPVOID pNative) const;
- VOID ScalarUpdateCLRImpl(const VOID *pNative, LPVOID pCLR) const;
-
-};
-
-
-
-#ifdef FEATURE_COMINTEROP
-
-class FieldMarshaler_Currency : public FieldMarshaler
-{
-public:
- static constexpr NStructFieldType s_nft = NFT_CURRENCY;
-
- UNUSED_METHOD_IMPL(VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const)
- UNUSED_METHOD_IMPL(VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const)
-
- SCALAR_MARSHALER_IMPL(sizeof(CURRENCY), sizeof(CURRENCY))
- COPY_TO_IMPL_BASE_STRUCT_ONLY()
-
- VOID ScalarUpdateNativeImpl(LPVOID pCLR, LPVOID pNative) const;
- VOID ScalarUpdateCLRImpl(const VOID *pNative, LPVOID pCLR) const;
-
-};
-
-class FieldMarshaler_DateTimeOffset : public FieldMarshaler
-{
-public:
- static constexpr NStructFieldType s_nft = NFT_DATETIMEOFFSET;
-
- UNUSED_METHOD_IMPL(VOID UpdateNativeImpl(OBJECTREF* pCLRValue, LPVOID pNativeValue, OBJECTREF *ppCleanupWorkListOnStack) const)
- UNUSED_METHOD_IMPL(VOID UpdateCLRImpl(const VOID *pNativeValue, OBJECTREF *ppProtectedCLRValue, OBJECTREF *ppProtectedOldCLRValue) const)
-
- SCALAR_MARSHALER_IMPL(sizeof(INT64), sizeof(INT64))
- COPY_TO_IMPL_BASE_STRUCT_ONLY()
-
- VOID ScalarUpdateNativeImpl(LPVOID pCLR, LPVOID pNative) const;
- VOID ScalarUpdateCLRImpl(const VOID *pNative, LPVOID pCLR) const;
-
-};
-
-#endif // FEATURE_COMINTEROP
-
-
-//========================================================================
-// Used to ensure that native data is properly deleted in exception cases.
-//========================================================================
-class NativeLayoutDestroyer
-{
-public:
- NativeLayoutDestroyer(BYTE* pNativeData, MethodTable* pMT, UINT32 cbSize)
- {
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(CheckPointer(pNativeData));
- PRECONDITION(CheckPointer(pMT));
- }
- CONTRACTL_END;
-
- m_pNativeData = pNativeData;
- m_pMT = pMT;
- m_cbSize = cbSize;
- m_fDestroy = TRUE;
- }
-
- ~NativeLayoutDestroyer()
- {
- WRAPPER_NO_CONTRACT;
-
- if (m_fDestroy)
- {
- LayoutDestroyNative(m_pNativeData, m_pMT);
- FillMemory(m_pNativeData, m_cbSize, 0);
- }
- }
-
- void SuppressRelease()
- {
- m_fDestroy = FALSE;
- }
-
-private:
- NativeLayoutDestroyer()
- {
- LIMITED_METHOD_CONTRACT;
- }
+ // The LayoutKind.Sequential attribute now affects managed layout as well.
+ // So we need to keep a parallel set of layout data for the managed side. The Size and AlignmentReq
+ // is redundant since we can figure it out from the sig but since we're already accessing the sig
+ // in ParseNativeType, we might as well capture it at that time.
+ RawFieldPlacementInfo m_managedPlacement;
- BYTE* m_pNativeData;
- MethodTable* m_pMT;
- UINT32 m_cbSize;
- BOOL m_fDestroy;
+ NativeFieldDescriptor m_nfd;
};
-#endif // DACCESS_COMPILE
-
-
#endif // __FieldMarshaler_h__
// Forward references
class Frame;
-class FieldMarshaler;
class FramedMethodFrame;
typedef VPTR(class FramedMethodFrame) PTR_FramedMethodFrame;
struct HijackArgs;
#define ENREGISTERED_RETURNTYPE_INTEGER_MAXSIZE 4
#define CALLDESCR_ARGREGS 1 // CallDescrWorker has ArgumentRegister parameter
-//=======================================================================
-// IMPORTANT: This value is used to figure out how much to allocate
-// for a fixed array of FieldMarshaler's. That means it must be at least
-// as large as the largest FieldMarshaler subclass. This requirement
-// is guarded by an assert.
-//=======================================================================
-#define MAXFIELDMARSHALERSIZE 24
-
//**********************************************************************
// Parameter size
//**********************************************************************
pslILEmit->EmitCALL(METHOD__MARSHAL__GET_DELEGATE_FOR_FUNCTION_POINTER, 2, 1); // Delegate System.Marshal.GetDelegateForFunctionPointer(IntPtr p, Type t)
EmitStoreManagedValue(pslILEmit);
- pslILEmit->EmitLabel(pNullLabel);
+ if (IsFieldMarshal(m_dwMarshalFlags))
+ {
+ // Field marshalling of delegates supports marshalling back null from native code.
+ // Parameter and return value marshalling does not.
+ ILCodeLabel* pFinishedLabel = pslILEmit->NewCodeLabel();
+ pslILEmit->EmitBR(pFinishedLabel);
+ pslILEmit->EmitLabel(pNullLabel);
+ pslILEmit->EmitLDNULL();
+ EmitStoreManagedValue(pslILEmit);
+ pslILEmit->EmitLabel(pFinishedLabel);
+ }
+ else
+ {
+ pslILEmit->EmitLabel(pNullLabel);
+ }
+
}
// stack: alloc_size_in_bytes
ILCodeLabel *pAllocRejoin = pslILEmit->NewCodeLabel();
- if (IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags))
+ if (IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags) && !IsFieldMarshal(m_dwMarshalFlags))
{
ILCodeLabel *pNoOptimize = pslILEmit->NewCodeLabel();
m_dwLocalBuffer = pslILEmit->NewLocal(ELEMENT_TYPE_I);
// stack: alloc_size_in_bytes
ILCodeLabel *pAllocRejoin = pslILEmit->NewCodeLabel();
- if (IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags))
+ if (IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags) && !IsFieldMarshal(m_dwMarshalFlags))
{
ILCodeLabel *pNoOptimize = pslILEmit->NewCodeLabel();
m_dwLocalBuffer = pslILEmit->NewLocal(ELEMENT_TYPE_I);
// stack: alloc_size_in_bytes
ILCodeLabel *pAllocRejoin = pslILEmit->NewCodeLabel();
- if (IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags))
+ if (IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags) && !IsFieldMarshal(m_dwMarshalFlags))
{
ILCodeLabel *pNoOptimize = pslILEmit->NewCodeLabel();
m_dwLocalBuffer = pslILEmit->NewLocal(ELEMENT_TYPE_I);
{
STANDARD_VM_CONTRACT;
- mdToken managedVCToken = pslILEmit->GetToken(m_pargs->m_pMT);
-
+ MethodDesc* pStructMarshalStub = NDirect::CreateStructMarshalILStub(m_pargs->m_pMT);
+
+ EmitLoadManagedHomeAddr(pslILEmit);
EmitLoadNativeHomeAddr(pslILEmit);
- pslILEmit->EmitLDTOKEN(managedVCToken); // pMT
- pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1);
- pslILEmit->EmitCALL(METHOD__VALUECLASSMARSHALER__CLEAR_NATIVE, 2, 0);
+ pslILEmit->EmitLDC(StructMarshalStubs::MarshalOperation::Cleanup);
+ EmitLoadCleanupWorkList(pslILEmit);
+
+ pslILEmit->EmitCALL(pslILEmit->GetToken(pStructMarshalStub), 4, 0);
}
{
STANDARD_VM_CONTRACT;
- mdToken managedVCToken = pslILEmit->GetToken(m_pargs->m_pMT);
-
- EmitLoadNativeHomeAddr(pslILEmit); // dst
- EmitLoadManagedHomeAddr(pslILEmit); // src
- pslILEmit->EmitLDTOKEN(managedVCToken); // pMT
- pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1); // Convert RTH to IntPtr
+ MethodDesc* pStructMarshalStub = NDirect::CreateStructMarshalILStub(m_pargs->m_pMT);
+ EmitLoadManagedHomeAddr(pslILEmit);
+ EmitLoadNativeHomeAddr(pslILEmit);
+ pslILEmit->EmitLDC(StructMarshalStubs::MarshalOperation::Marshal);
EmitLoadCleanupWorkList(pslILEmit);
- pslILEmit->EmitCALL(METHOD__VALUECLASSMARSHALER__CONVERT_TO_NATIVE, 4, 0); // void ConvertToNative(IntPtr dst, IntPtr src, IntPtr pMT, ref CleanupWorkListElement pCleanupWorkList)
+
+ pslILEmit->EmitCALL(pslILEmit->GetToken(pStructMarshalStub), 4, 0);
}
void ILValueClassMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
{
STANDARD_VM_CONTRACT;
- mdToken managedVCToken = pslILEmit->GetToken(m_pargs->m_pMT);
+ MethodDesc* pStructMarshalStub = NDirect::CreateStructMarshalILStub(m_pargs->m_pMT);
- EmitLoadManagedHomeAddr(pslILEmit); // dst
- EmitLoadNativeHomeAddr(pslILEmit); // src
- pslILEmit->EmitLDTOKEN(managedVCToken); // pMT
- pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1);
- pslILEmit->EmitCALL(METHOD__VALUECLASSMARSHALER__CONVERT_TO_MANAGED, 3, 0); // void ConvertToManaged(IntPtr dst, IntPtr src, IntPtr pMT)
+ EmitLoadManagedHomeAddr(pslILEmit);
+ EmitLoadNativeHomeAddr(pslILEmit);
+ pslILEmit->EmitLDC(StructMarshalStubs::MarshalOperation::Unmarshal);
+ EmitLoadCleanupWorkList(pslILEmit);
+
+ pslILEmit->EmitCALL(pslILEmit->GetToken(pStructMarshalStub), 4, 0);
}
EmitLoadManagedValue(pslILEmit);
- if (IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags))
+ if (IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags) && !IsFieldMarshal(m_dwMarshalFlags))
{
ILCodeLabel *pNoOptimizeLabel = pslILEmit->NewCodeLabel();
m_dwLocalBuffer = pslILEmit->NewLocal(ELEMENT_TYPE_I);
pslILEmit->EmitCALL(METHOD__ANSIBSTRMARSHALER__CLEAR_NATIVE, 1, 0);
}
+void ILFixedWSTRMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
+{
+ STANDARD_VM_CONTRACT;
+
+ ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
+ ILCodeLabel* pFinishedLabel = pslILEmit->NewCodeLabel();
+
+ EmitLoadManagedValue(pslILEmit);
+ EmitLoadNativeHomeAddr(pslILEmit);
+ pslILEmit->EmitLDC(m_pargs->fs.fixedStringLength);
+ pslILEmit->EmitCALL(METHOD__FIXEDWSTRMARSHALER__CONVERT_TO_NATIVE, 3, 0);
+}
+
+void ILFixedWSTRMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
+{
+ STANDARD_VM_CONTRACT;
+
+ EmitLoadNativeHomeAddr(pslILEmit);
+ pslILEmit->EmitDUP();
+ pslILEmit->EmitCALL(METHOD__STRING__WCSLEN, 1, 1);
+ pslILEmit->EmitCALL(METHOD__STUBHELPERS__CHECK_STRING_LENGTH, 1, 0);
+
+ pslILEmit->EmitNEWOBJ(METHOD__STRING__CTOR_CHARPTR, 1);
+ EmitStoreManagedValue(pslILEmit);
+}
+
+void ILFixedCSTRMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
+{
+ STANDARD_VM_CONTRACT;
+
+ DWORD dwAnsiMarshalFlags =
+ (m_pargs->m_pMarshalInfo->GetBestFitMapping() & 0xFF) |
+ (m_pargs->m_pMarshalInfo->GetThrowOnUnmappableChar() << 8);
+
+ // CSTRMarshaler.ConvertFixedToNative dwAnsiMarshalFlags, pManaged, homeAddr, fixedLength
+ pslILEmit->EmitLDC(dwAnsiMarshalFlags);
+ EmitLoadManagedValue(pslILEmit);
+ EmitLoadNativeHomeAddr(pslILEmit);
+ pslILEmit->EmitLDC(m_pargs->fs.fixedStringLength);
+ pslILEmit->EmitCALL(METHOD__CSTRMARSHALER__CONVERT_FIXED_TO_NATIVE, 4, 0);
+}
+
+void ILFixedCSTRMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
+{
+ STANDARD_VM_CONTRACT;
+
+ EmitLoadNativeHomeAddr(pslILEmit);
+ pslILEmit->EmitLDC(m_pargs->fs.fixedStringLength);
+ pslILEmit->EmitCALL(METHOD__CSTRMARSHALER__CONVERT_FIXED_TO_MANAGED, 2, 1);
+ EmitStoreManagedValue(pslILEmit);
+}
+
#ifdef FEATURE_COMINTEROP
LocalDesc ILHSTRINGMarshaler::GetNativeType()
pslILEmit->EmitLDC(uNativeSize);
pslILEmit->EmitINITBLK();
- EmitLoadManagedValue(pslILEmit);
- EmitLoadNativeValue(pslILEmit);
+ MethodDesc* pStructMarshalStub = NDirect::CreateStructMarshalILStub(m_pargs->m_pMT);
+ EmitLoadReferenceToFirstManagedObjectField(pslILEmit);
+ EmitLoadNativeValue(pslILEmit);
+ pslILEmit->EmitLDC(StructMarshalStubs::MarshalOperation::Marshal);
EmitLoadCleanupWorkList(pslILEmit);
- // static void FmtClassUpdateNativeInternal(object obj, byte* pNative, IntPtr pOptionalCleanupList);
-
- pslILEmit->EmitCALL(METHOD__STUBHELPERS__FMT_CLASS_UPDATE_NATIVE_INTERNAL, 3, 0);
+ pslILEmit->EmitCALL(pslILEmit->GetToken(pStructMarshalStub), 4, 0);
pslILEmit->EmitLabel(pNullRefLabel);
}
EmitLoadManagedValue(pslILEmit);
pslILEmit->EmitBRFALSE(pNullRefLabel);
- EmitLoadManagedValue(pslILEmit);
+ MethodDesc* pStructMarshalStub = NDirect::CreateStructMarshalILStub(m_pargs->m_pMT);
+
+ EmitLoadReferenceToFirstManagedObjectField(pslILEmit);
EmitLoadNativeValue(pslILEmit);
+ pslILEmit->EmitLDC(StructMarshalStubs::MarshalOperation::Unmarshal);
+ EmitLoadCleanupWorkList(pslILEmit);
- // static void FmtClassUpdateCLRInternal(object obj, byte* pNative);
- pslILEmit->EmitCALL(METHOD__STUBHELPERS__FMT_CLASS_UPDATE_CLR_INTERNAL, 2, 0);
+ pslILEmit->EmitCALL(pslILEmit->GetToken(pStructMarshalStub), 4, 0);
pslILEmit->EmitLabel(pNullRefLabel);
}
{
STANDARD_VM_CONTRACT;
- int tokManagedType = pslILEmit->GetToken(m_pargs->m_pMT);
-
+ MethodDesc* pStructMarshalStub = NDirect::CreateStructMarshalILStub(m_pargs->m_pMT);
+
+ EmitLoadReferenceToFirstManagedObjectField(pslILEmit);
EmitLoadNativeValue(pslILEmit);
- pslILEmit->EmitLDTOKEN(tokManagedType);
- pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1);
+ pslILEmit->EmitLDC(StructMarshalStubs::MarshalOperation::Cleanup);
+ EmitLoadCleanupWorkList(pslILEmit);
- // static void LayoutDestroyNativeInternal(byte* pNative, IntPtr pMT);
- pslILEmit->EmitCALL(METHOD__STUBHELPERS__LAYOUT_DESTROY_NATIVE_INTERNAL, 2, 0);
+ pslILEmit->EmitCALL(pslILEmit->GetToken(pStructMarshalStub), 4, 0);
}
bool ILBlittablePtrMarshaler::CanUsePinnedLayoutClass()
{
- return IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags);
+ return IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags) && !IsFieldMarshal(m_dwMarshalFlags);
}
void ILBlittablePtrMarshaler::EmitConvertSpaceAndContentsCLRToNativeTemp(ILCodeStream* pslILEmit)
EmitStoreNativeValue(pslILEmit);
}
+void ILLayoutClassMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
+{
+ STANDARD_VM_CONTRACT;
+
+ ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
+ UINT uNativeSize = m_pargs->m_pMT->GetNativeSize();
+ EmitLoadNativeHomeAddr(pslILEmit);
+ pslILEmit->EmitLDC(0);
+ pslILEmit->EmitLDC(uNativeSize);
+ pslILEmit->EmitINITBLK();
+
+ EmitLoadManagedValue(pslILEmit);
+ pslILEmit->EmitBRFALSE(pNullRefLabel);
+
+
+ MethodDesc* pStructMarshalStub = NDirect::CreateStructMarshalILStub(m_pargs->m_pMT);
+
+ EmitLoadReferenceToFirstManagedObjectField(pslILEmit);
+ EmitLoadNativeHomeAddr(pslILEmit);
+ pslILEmit->EmitLDC(StructMarshalStubs::MarshalOperation::Marshal);
+ EmitLoadCleanupWorkList(pslILEmit);
+
+ pslILEmit->EmitCALL(pslILEmit->GetToken(pStructMarshalStub), 4, 0);
+ pslILEmit->EmitLabel(pNullRefLabel);
+}
+
+void ILLayoutClassMarshaler::EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit)
+{
+ pslILEmit->EmitLDTOKEN(pslILEmit->GetToken(m_pargs->m_pMT));
+ pslILEmit->EmitCALL(METHOD__TYPE__GET_TYPE_FROM_HANDLE, 1, 1);
+ pslILEmit->EmitCALL(METHOD__RUNTIME_HELPERS__GET_UNINITIALIZED_OBJECT, 1, 1);
+ EmitStoreManagedValue(pslILEmit);
+}
+
+void ILLayoutClassMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
+{
+ STANDARD_VM_CONTRACT;
+
+ MethodDesc* pStructMarshalStub = NDirect::CreateStructMarshalILStub(m_pargs->m_pMT);
+
+ EmitLoadReferenceToFirstManagedObjectField(pslILEmit);
+ EmitLoadNativeHomeAddr(pslILEmit);
+ pslILEmit->EmitLDC(StructMarshalStubs::MarshalOperation::Unmarshal);
+ EmitLoadCleanupWorkList(pslILEmit);
+
+ pslILEmit->EmitCALL(pslILEmit->GetToken(pStructMarshalStub), 4, 0);
+}
+
+void ILLayoutClassMarshaler::EmitClearNativeContents(ILCodeStream* pslILEmit)
+{
+ STANDARD_VM_CONTRACT;
+
+ MethodDesc* pStructMarshalStub = NDirect::CreateStructMarshalILStub(m_pargs->m_pMT);
+
+ EmitLoadReferenceToFirstManagedObjectField(pslILEmit);
+ EmitLoadNativeHomeAddr(pslILEmit);
+ pslILEmit->EmitLDC(StructMarshalStubs::MarshalOperation::Cleanup);
+ EmitLoadCleanupWorkList(pslILEmit);
+
+ pslILEmit->EmitCALL(pslILEmit->GetToken(pStructMarshalStub), 4, 0);
+}
+
+
+void ILBlittableLayoutClassMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
+{
+ STANDARD_VM_CONTRACT;
+
+ ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
+ UINT uNativeSize = m_pargs->m_pMT->GetNativeSize();
+ int fieldDef = pslILEmit->GetToken(MscorlibBinder::GetField(FIELD__RAW_DATA__DATA));
+
+ EmitLoadNativeHomeAddr(pslILEmit);
+ pslILEmit->EmitLDC(0);
+ pslILEmit->EmitLDC(uNativeSize);
+ pslILEmit->EmitINITBLK();
+
+ EmitLoadManagedValue(pslILEmit);
+ pslILEmit->EmitBRFALSE(pNullRefLabel);
+
+ EmitLoadNativeHomeAddr(pslILEmit); // dest
+
+ EmitLoadManagedValue(pslILEmit);
+ pslILEmit->EmitLDFLDA(fieldDef); // src
+
+ pslILEmit->EmitLDC(uNativeSize); // size
+
+ pslILEmit->EmitCPBLK();
+ pslILEmit->EmitLabel(pNullRefLabel);
+}
+
+void ILBlittableLayoutClassMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
+{
+ STANDARD_VM_CONTRACT;
+
+ UINT uNativeSize = m_pargs->m_pMT->GetNativeSize();
+ int fieldDef = pslILEmit->GetToken(MscorlibBinder::GetField(FIELD__RAW_DATA__DATA));
+
+ pslILEmit->EmitLDTOKEN(pslILEmit->GetToken(m_pargs->m_pMT));
+ pslILEmit->EmitCALL(METHOD__TYPE__GET_TYPE_FROM_HANDLE, 1, 1);
+ pslILEmit->EmitCALL(METHOD__RUNTIME_HELPERS__GET_UNINITIALIZED_OBJECT, 1, 1);
+ EmitStoreManagedValue(pslILEmit);
+
+ EmitLoadManagedValue(pslILEmit);
+ pslILEmit->EmitLDFLDA(fieldDef); // dest
+
+ EmitLoadNativeHomeAddr(pslILEmit); // src
+
+ pslILEmit->EmitLDC(uNativeSize); // size
+
+ pslILEmit->EmitCPBLK();
+}
MarshalerOverrideStatus ILHandleRefMarshaler::ArgumentOverride(NDirectStubLinker* psl,
BOOL byref,
return DISALLOWED;
}
+void ILSafeHandleMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
+{
+ _ASSERTE(IsFieldMarshal(m_dwMarshalFlags));
+
+ EmitLoadManagedValue(pslILEmit);
+ EmitLoadCleanupWorkList(pslILEmit);
+ pslILEmit->EmitLDC(0);
+ pslILEmit->EmitCONV_U();
+ pslILEmit->EmitCEQ();
+ pslILEmit->EmitLDC(0);
+ pslILEmit->EmitCEQ();
+ EmitLoadCleanupWorkList(pslILEmit);
+ pslILEmit->EmitCALL(METHOD__HANDLE_MARSHALER__CONVERT_SAFEHANDLE_TO_NATIVE, 3, 1);
+ EmitStoreNativeValue(pslILEmit);
+}
+
+void ILSafeHandleMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
+{
+ _ASSERTE(IsFieldMarshal(m_dwMarshalFlags));
+
+ ILCodeLabel* successLabel = pslILEmit->NewCodeLabel();
+ ILCodeLabel* failureLabel = pslILEmit->NewCodeLabel();
+
+ EmitLoadManagedValue(pslILEmit);
+ pslILEmit->EmitBRFALSE(failureLabel);
+ EmitLoadManagedValue(pslILEmit);
+ pslILEmit->EmitLDFLD(pslILEmit->GetToken(MscorlibBinder::GetField(FIELD__SAFE_HANDLE__HANDLE)));
+ EmitLoadNativeValue(pslILEmit);
+ pslILEmit->EmitBEQ(successLabel);
+ pslILEmit->EmitLabel(failureLabel);
+ pslILEmit->EmitCALL(METHOD__HANDLE_MARSHALER__THROW_SAFEHANDLE_FIELD_CHANGED, 0, 0);
+ pslILEmit->EmitLabel(successLabel);
+}
+
MarshalerOverrideStatus ILSafeHandleMarshaler::ArgumentOverride(NDirectStubLinker* psl,
BOOL byref,
BOOL fin,
return OVERRIDDEN;
} // ILSafeHandleMarshaler::ReturnOverride
+void ILCriticalHandleMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
+{
+ _ASSERTE(IsFieldMarshal(m_dwMarshalFlags));
+
+ EmitLoadManagedValue(pslILEmit);
+ pslILEmit->EmitLDFLD(pslILEmit->GetToken(MscorlibBinder::GetField(FIELD__CRITICAL_HANDLE__HANDLE)));
+ EmitStoreNativeValue(pslILEmit);
+}
+
+void ILCriticalHandleMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
+{
+ _ASSERTE(IsFieldMarshal(m_dwMarshalFlags));
+
+ ILCodeLabel* successLabel = pslILEmit->NewCodeLabel();
+ ILCodeLabel* failureLabel = pslILEmit->NewCodeLabel();
+
+ EmitLoadManagedValue(pslILEmit);
+ pslILEmit->EmitBRFALSE(failureLabel);
+ EmitLoadManagedValue(pslILEmit);
+ pslILEmit->EmitLDFLD(pslILEmit->GetToken(MscorlibBinder::GetField(FIELD__CRITICAL_HANDLE__HANDLE)));
+ EmitLoadNativeValue(pslILEmit);
+ pslILEmit->EmitBEQ(successLabel);
+ pslILEmit->EmitLabel(failureLabel);
+ pslILEmit->EmitCALL(METHOD__HANDLE_MARSHALER__THROW_CRITICALHANDLE_FIELD_CHANGED, 0, 0);
+ pslILEmit->EmitLabel(successLabel);
+}
//---------------------------------------------------------------------------------------
//
}
pslILEmit->EmitLDC(dwFlags);
+
+ if (mops.elementType == VT_RECORD && !mops.methodTable->IsBlittable())
+ {
+ pslILEmit->EmitLDFTN(pslILEmit->GetToken(NDirect::CreateStructMarshalILStub(mops.methodTable)));
+ }
+ else
+ {
+ pslILEmit->EmitLoadNullPtr();
+ }
- pslILEmit->EmitCALL(METHOD__MNGD_NATIVE_ARRAY_MARSHALER__CREATE_MARSHALER, 3, 0);
+ pslILEmit->EmitCALL(METHOD__MNGD_NATIVE_ARRAY_MARSHALER__CREATE_MARSHALER, 4, 0);
}
bool ILNativeArrayMarshaler::CanMarshalViaPinning()
STANDARD_VM_CONTRACT;
EmitLoadMngdMarshaler(pslILEmit);
+ EmitLoadManagedHomeAddr(pslILEmit);
EmitLoadNativeHomeAddr(pslILEmit);
EmitLoadNativeSize(pslILEmit);
STANDARD_VM_CONTRACT;
EmitLoadMngdMarshaler(pslILEmit);
+ EmitLoadManagedHomeAddr(pslILEmit);
EmitLoadNativeHomeAddr(pslILEmit);
EmitLoadNativeSize(pslILEmit);
#ifndef CROSSGEN_COMPILE
-FCIMPL3(void, MngdNativeArrayMarshaler::CreateMarshaler, MngdNativeArrayMarshaler* pThis, MethodTable* pMT, UINT32 dwFlags)
+FCIMPL4(void, MngdNativeArrayMarshaler::CreateMarshaler, MngdNativeArrayMarshaler* pThis, MethodTable* pMT, UINT32 dwFlags, PCODE pManagedMarshaler)
{
FCALL_CONTRACT;
pThis->m_BestFitMap = (BYTE)(dwFlags >> 16);
pThis->m_ThrowOnUnmappableChar = (BYTE)(dwFlags >> 24);
pThis->m_Array = TypeHandle();
+ pThis->m_pManagedMarshaler = pManagedMarshaler;
}
FCIMPLEND
else
{
pMarshaler->ComToOleArray(pArrayRef, *pNativeHome, pThis->m_pElementMT, pThis->m_BestFitMap,
- pThis->m_ThrowOnUnmappableChar, pThis->m_NativeDataValid, cElements);
+ pThis->m_ThrowOnUnmappableChar, pThis->m_NativeDataValid, cElements, pThis->m_pManagedMarshaler);
}
}
HELPER_METHOD_FRAME_END();
}
else
{
- pMarshaler->OleToComArray(*pNativeHome, pArrayRef, pThis->m_pElementMT);
+ pMarshaler->OleToComArray(*pNativeHome, pArrayRef, pThis->m_pElementMT, pThis->m_pManagedMarshaler);
}
}
}
FCIMPLEND
-FCIMPL3(void, MngdNativeArrayMarshaler::ClearNative, MngdNativeArrayMarshaler* pThis, void** pNativeHome, INT32 cElements)
+FCIMPL4(void, MngdNativeArrayMarshaler::ClearNative, MngdNativeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome, INT32 cElements)
{
FCALL_CONTRACT;
if (*pNativeHome != NULL)
{
- DoClearNativeContents(pThis, pNativeHome, cElements);
+ DoClearNativeContents(pThis, pManagedHome, pNativeHome, cElements);
CoTaskMemFree(*pNativeHome);
}
}
FCIMPLEND
-FCIMPL3(void, MngdNativeArrayMarshaler::ClearNativeContents, MngdNativeArrayMarshaler* pThis, void** pNativeHome, INT32 cElements)
+FCIMPL4(void, MngdNativeArrayMarshaler::ClearNativeContents, MngdNativeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome, INT32 cElements)
{
FCALL_CONTRACT;
HELPER_METHOD_FRAME_BEGIN_0();
- DoClearNativeContents(pThis, pNativeHome, cElements);
+ DoClearNativeContents(pThis, pManagedHome, pNativeHome, cElements);
HELPER_METHOD_FRAME_END();
}
FCIMPLEND
-void MngdNativeArrayMarshaler::DoClearNativeContents(MngdNativeArrayMarshaler* pThis, void** pNativeHome, INT32 cElements)
+void MngdNativeArrayMarshaler::DoClearNativeContents(MngdNativeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome, INT32 cElements)
{
CONTRACTL
{
if (pMarshaler != NULL && pMarshaler->ClearOleArray != NULL)
{
- pMarshaler->ClearOleArray(*pNativeHome, cElements, pThis->m_pElementMT);
+ pMarshaler->ClearOleArray((BASEARRAYREF*)pManagedHome, *pNativeHome, cElements, pThis->m_pElementMT, pThis->m_pManagedMarshaler);
+ }
+ }
+}
+
+#endif // CROSSGEN_COMPILE
+
+
+void ILFixedArrayMarshaler::EmitCreateMngdMarshaler(ILCodeStream* pslILEmit)
+{
+ STANDARD_VM_CONTRACT;
+
+ m_dwMngdMarshalerLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I);
+
+ pslILEmit->EmitLDC(sizeof(MngdFixedArrayMarshaler));
+ pslILEmit->EmitLOCALLOC();
+ pslILEmit->EmitSTLOC(m_dwMngdMarshalerLocalNum);
+
+ CREATE_MARSHALER_CARRAY_OPERANDS mops;
+ m_pargs->m_pMarshalInfo->GetMops(&mops);
+
+ pslILEmit->EmitLDLOC(m_dwMngdMarshalerLocalNum);
+
+ pslILEmit->EmitLDTOKEN(pslILEmit->GetToken(mops.methodTable));
+ pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1);
+
+ DWORD dwFlags = mops.elementType;
+ dwFlags |= (((DWORD)mops.bestfitmapping) << 16);
+ dwFlags |= (((DWORD)mops.throwonunmappablechar) << 24);
+
+ pslILEmit->EmitLDC(dwFlags);
+
+ pslILEmit->EmitLDC(mops.additive);
+
+ if (mops.elementType == VT_RECORD && !mops.methodTable->IsBlittable())
+ {
+ pslILEmit->EmitLDFTN(pslILEmit->GetToken(NDirect::CreateStructMarshalILStub(mops.methodTable)));
+ }
+ else
+ {
+ pslILEmit->EmitLoadNullPtr();
+ }
+
+ pslILEmit->EmitCALL(METHOD__MNGD_FIXED_ARRAY_MARSHALER__CREATE_MARSHALER, 5, 0);
+}
+
+#ifndef CROSSGEN_COMPILE
+
+FCIMPL5(void, MngdFixedArrayMarshaler::CreateMarshaler, MngdFixedArrayMarshaler* pThis, MethodTable* pMT, UINT32 dwFlags, UINT32 cElements, PCODE pManagedElementMarshaler)
+{
+ FCALL_CONTRACT;
+
+ // Don't check whether the input values are negative - passing negative size-controlling
+ // arguments and compensating them with a positive SizeConst has always worked.
+ pThis->m_pElementMT = pMT;
+ pThis->m_vt = (VARTYPE)(dwFlags);
+ pThis->m_NativeDataValid = (BYTE)((dwFlags & FLAG_NATIVE_DATA_VALID) != 0);
+ dwFlags &= ~FLAG_NATIVE_DATA_VALID;
+ pThis->m_BestFitMap = (BYTE)(dwFlags >> 16);
+ pThis->m_ThrowOnUnmappableChar = (BYTE)(dwFlags >> 24);
+ pThis->m_Array = TypeHandle();
+ pThis->m_cElements = cElements;
+ pThis->m_pManagedElementMarshaler = pManagedElementMarshaler;
+}
+FCIMPLEND
+
+FCIMPL3(void, MngdFixedArrayMarshaler::ConvertSpaceToNative, MngdFixedArrayMarshaler* pThis, OBJECTREF* pManagedHome, void* pNativeHome)
+{
+ FCALL_CONTRACT;
+
+ HELPER_METHOD_FRAME_BEGIN_0();
+
+ BASEARRAYREF arrayRef = (BASEARRAYREF)*pManagedHome;
+
+ if (arrayRef != NULL && arrayRef->GetNumComponents() < pThis->m_cElements)
+ {
+ COMPlusThrow(kArgumentException, IDS_WRONGSIZEARRAY_IN_NSTRUCT);
+ }
+
+ HELPER_METHOD_FRAME_END();
+}
+FCIMPLEND
+
+FCIMPL3(void, MngdFixedArrayMarshaler::ConvertContentsToNative, MngdFixedArrayMarshaler* pThis, OBJECTREF* pManagedHome, void* pNativeHome)
+{
+ FCALL_CONTRACT;
+
+ HELPER_METHOD_FRAME_BEGIN_0();
+
+ BASEARRAYREF* pArrayRef = (BASEARRAYREF*)pManagedHome;
+
+ if (pThis->m_vt == VTHACK_ANSICHAR)
+ {
+ SIZE_T nativeSize = sizeof(CHAR) * pThis->m_cElements;
+
+ if (*pArrayRef == NULL)
+ {
+ FillMemory(pNativeHome, nativeSize, 0);
+ }
+ else
+ {
+ InternalWideToAnsi((const WCHAR*)(*pArrayRef)->GetDataPtr(),
+ pThis->m_cElements,
+ (CHAR*)pNativeHome,
+ (int)nativeSize,
+ pThis->m_BestFitMap,
+ pThis->m_ThrowOnUnmappableChar);
+ }
+ }
+ else
+ {
+ SIZE_T cbElement = OleVariant::GetElementSizeForVarType(pThis->m_vt, pThis->m_pElementMT);
+ SIZE_T nativeSize = cbElement * pThis->m_cElements;
+
+ if (*pArrayRef == NULL)
+ {
+ FillMemory(pNativeHome, nativeSize, 0);
+ }
+ else
+ {
+
+ const OleVariant::Marshaler* pMarshaler = OleVariant::GetMarshalerForVarType(pThis->m_vt, TRUE);
+ SIZE_T cElements = (*pArrayRef)->GetNumComponents();
+ if (pMarshaler == NULL || pMarshaler->ComToOleArray == NULL)
+ {
+ _ASSERTE(!GetTypeHandleForCVType(OleVariant::GetCVTypeForVarType(pThis->m_vt)).GetMethodTable()->ContainsPointers());
+ memcpyNoGCRefs(pNativeHome, (*pArrayRef)->GetDataPtr(), nativeSize);
+ }
+ else
+ {
+ pMarshaler->ComToOleArray(pArrayRef, pNativeHome, pThis->m_pElementMT, pThis->m_BestFitMap,
+ pThis->m_ThrowOnUnmappableChar, pThis->m_NativeDataValid, pThis->m_cElements, pThis->m_pManagedElementMarshaler);
+ }
}
}
+
+ HELPER_METHOD_FRAME_END();
}
+FCIMPLEND
+
+FCIMPL3(void, MngdFixedArrayMarshaler::ConvertSpaceToManaged, MngdFixedArrayMarshaler* pThis,
+ OBJECTREF* pManagedHome, void* pNativeHome)
+{
+ FCALL_CONTRACT;
+
+ HELPER_METHOD_FRAME_BEGIN_0();
+
+ // <TODO>@todo: lookup this class before marshal time</TODO>
+ if (pThis->m_Array.IsNull())
+ {
+ // Get proper array class name & type
+ pThis->m_Array = OleVariant::GetArrayForVarType(pThis->m_vt, TypeHandle(pThis->m_pElementMT));
+ if (pThis->m_Array.IsNull())
+ COMPlusThrow(kTypeLoadException);
+ }
+ //
+ // Allocate array
+ //
+ SetObjectReference(pManagedHome, AllocateSzArray(pThis->m_Array, pThis->m_cElements));
+
+ HELPER_METHOD_FRAME_END();
+}
+FCIMPLEND
+
+FCIMPL3(void, MngdFixedArrayMarshaler::ConvertContentsToManaged, MngdFixedArrayMarshaler* pThis, OBJECTREF* pManagedHome, void* pNativeHome)
+{
+ FCALL_CONTRACT;
+
+ HELPER_METHOD_FRAME_BEGIN_0();
+
+ BASEARRAYREF* pArrayRef = (BASEARRAYREF*)pManagedHome;
+
+ if (pThis->m_vt == VTHACK_ANSICHAR)
+ {
+ MultiByteToWideChar(CP_ACP,
+ MB_PRECOMPOSED,
+ (const CHAR*)pNativeHome,
+ pThis->m_cElements * sizeof(CHAR), // size, in bytes, of in buffer
+ (WCHAR*)((*((I2ARRAYREF*)pArrayRef))->GetDirectPointerToNonObjectElements()),
+ pThis->m_cElements); // size, in WCHAR's of outbuffer
+ }
+ else
+ {
+ const OleVariant::Marshaler* pMarshaler = OleVariant::GetMarshalerForVarType(pThis->m_vt, TRUE);
+
+ SIZE_T cbElement = OleVariant::GetElementSizeForVarType(pThis->m_vt, pThis->m_pElementMT);
+ SIZE_T nativeSize = cbElement * pThis->m_cElements;
+
+
+ if (pMarshaler == NULL || pMarshaler->OleToComArray == NULL)
+ {
+ // If we are copying variants, strings, etc, we need to use write barrier
+ _ASSERTE(!GetTypeHandleForCVType(OleVariant::GetCVTypeForVarType(pThis->m_vt)).GetMethodTable()->ContainsPointers());
+ memcpyNoGCRefs((*pArrayRef)->GetDataPtr(), pNativeHome, nativeSize);
+ }
+ else
+ {
+ pMarshaler->OleToComArray(pNativeHome, pArrayRef, pThis->m_pElementMT, pThis->m_pManagedElementMarshaler);
+ }
+ }
+
+ HELPER_METHOD_FRAME_END();
+}
+FCIMPLEND
+
+FCIMPL3(void, MngdFixedArrayMarshaler::ClearNativeContents, MngdFixedArrayMarshaler* pThis, OBJECTREF* pManagedHome, void* pNativeHome)
+{
+ FCALL_CONTRACT;
+
+ HELPER_METHOD_FRAME_BEGIN_0();
+
+ const OleVariant::Marshaler* pMarshaler = OleVariant::GetMarshalerForVarType(pThis->m_vt, FALSE);
+
+ if (pMarshaler != NULL && pMarshaler->ClearOleArray != NULL)
+ {
+ pMarshaler->ClearOleArray((BASEARRAYREF*)pManagedHome, pNativeHome, pThis->m_cElements, pThis->m_pElementMT, pThis->m_pManagedElementMarshaler);
+ }
+
+ HELPER_METHOD_FRAME_END();
+}
+FCIMPLEND
#endif // CROSSGEN_COMPILE
pslILEmit->EmitLDC(m_pargs->m_pMarshalInfo->GetArrayRank());
pslILEmit->EmitLDC(dwFlags);
- pslILEmit->EmitCALL(METHOD__MNGD_SAFE_ARRAY_MARSHALER__CREATE_MARSHALER, 4, 0);
+ if (mops.elementType == VT_RECORD && !mops.methodTable->IsBlittable())
+ {
+ pslILEmit->EmitLDFTN(pslILEmit->GetToken(NDirect::CreateStructMarshalILStub(mops.methodTable)));
+ }
+ else
+ {
+ pslILEmit->EmitLoadNullPtr();
+ }
+
+ pslILEmit->EmitCALL(METHOD__MNGD_SAFE_ARRAY_MARSHALER__CREATE_MARSHALER, 5, 0);
}
void ILSafeArrayMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
#ifndef CROSSGEN_COMPILE
-FCIMPL4(void, MngdSafeArrayMarshaler::CreateMarshaler, MngdSafeArrayMarshaler* pThis, MethodTable* pMT, UINT32 iRank, UINT32 dwFlags)
+FCIMPL5(void, MngdSafeArrayMarshaler::CreateMarshaler, MngdSafeArrayMarshaler* pThis, MethodTable* pMT, UINT32 iRank, UINT32 dwFlags, PCODE pManagedMarshaler)
{
FCALL_CONTRACT;
pThis->m_vt = (VARTYPE)dwFlags;
pThis->m_fStatic = (BYTE)(dwFlags >> 16);
pThis->m_nolowerbounds = (BYTE)(dwFlags >> 24);
+ pThis->m_pManagedMarshaler = pManagedMarshaler;
}
FCIMPLEND
(SAFEARRAY*)*pNativeHome,
pThis->m_vt,
pThis->m_pElementMT,
+ pThis->m_pManagedMarshaler,
(pThis->m_fStatic & SCSF_NativeDataValid));
}
OleVariant::MarshalArrayRefForSafeArray((SAFEARRAY*)*pNativeHome,
(BASEARRAYREF *) pManagedHome,
pThis->m_vt,
+ pThis->m_pManagedMarshaler,
pThis->m_pElementMT);
}
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);
+ if (m_pargs->na.m_vt == VTHACK_NONBLITTABLERECORD)
+ {
+ pslILEmit->EmitLDFTN(pslILEmit->GetToken(NDirect::CreateStructMarshalILStub(pElementMT)));
+ }
+ else
+ {
+ pslILEmit->EmitLoadNullPtr();
+ }
+
+ pslILEmit->EmitCALL(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CREATE_MARSHALER, 5, 0);
}
void ILHiddenLengthArrayMarshaler::EmitMarshalViaPinning(ILCodeStream* pslILEmit)
#ifndef CROSSGEN_COMPILE
-FCIMPL4(void, MngdHiddenLengthArrayMarshaler::CreateMarshaler, MngdHiddenLengthArrayMarshaler* pThis, MethodTable* pMT, SIZE_T cbElementSize, UINT16 vt)
+FCIMPL5(void, MngdHiddenLengthArrayMarshaler::CreateMarshaler, MngdHiddenLengthArrayMarshaler* pThis, MethodTable* pMT, SIZE_T cbElementSize, UINT16 vt, PCODE pManagedMarshaler)
{
FCALL_CONTRACT;
pThis->m_pElementMT = pMT;
pThis->m_cbElementSize = cbElementSize;
pThis->m_vt = (VARTYPE)vt;
+ pThis->m_pManagedMarshaler = pManagedMarshaler;
}
FCIMPLEND
SIZE_T nativeSize = pThis->m_pElementMT->GetNativeSize();
for (SIZE_T i = 0; i < gc.arrayRef->GetNumComponents(); ++i)
{
- LayoutUpdateNative(reinterpret_cast<LPVOID *>(&gc.arrayRef), managedOffset, pThis->m_pElementMT, pNativeStart + nativeOffset, NULL);
+ MarshalStructViaILStubCode(pThis->m_pManagedMarshaler, reinterpret_cast<BYTE*>(&gc.arrayRef) + managedOffset, pNativeStart + nativeOffset, StructMarshalStubs::MarshalOperation::Marshal);
+
managedOffset += managedSize;
nativeOffset += nativeSize;
}
case VTHACK_NONBLITTABLERECORD:
{
- // Defer to the field marshaler to handle structures
- BYTE *pNativeStart = reinterpret_cast<BYTE *>(*pNativeHome);
+ BYTE* pNativeStart = reinterpret_cast<BYTE*>(*pNativeHome);
SIZE_T managedOffset = ArrayBase::GetDataPtrOffset(gc.arrayRef->GetMethodTable());
SIZE_T nativeOffset = 0;
SIZE_T managedSize = gc.arrayRef->GetComponentSize();
SIZE_T nativeSize = pThis->m_pElementMT->GetNativeSize();
for (SIZE_T i = 0; i < gc.arrayRef->GetNumComponents(); ++i)
{
- LayoutUpdateCLR(reinterpret_cast<LPVOID *>(&gc.arrayRef), managedOffset, pThis->m_pElementMT, pNativeStart + nativeOffset);
+ MarshalStructViaILStubCode(pThis->m_pManagedMarshaler, reinterpret_cast<BYTE*>(&gc.arrayRef) + managedOffset, pNativeStart + nativeOffset, StructMarshalStubs::MarshalOperation::Unmarshal);
+
managedOffset += managedSize;
nativeOffset += nativeSize;
}
if (*pNativeHome != NULL)
{
- pThis->DoClearNativeContents(pNativeHome, cElements);
+ pThis->DoClearNativeContents(pThis, pNativeHome, cElements);
}
HELPER_METHOD_FRAME_END();
}
#ifndef CROSSGEN_COMPILE
-void MngdHiddenLengthArrayMarshaler::DoClearNativeContents(void** pNativeHome, INT32 cElements)
+void MngdHiddenLengthArrayMarshaler::DoClearNativeContents(MngdHiddenLengthArrayMarshaler* pThis, void** pNativeHome, INT32 cElements)
{
CONTRACTL
{
case VTHACK_NONBLITTABLERECORD:
{
- SIZE_T cbArray = GetArraySize(cElements);
- BYTE *pNativeCurrent = reinterpret_cast<BYTE *>(*pNativeHome);
- BYTE *pNativeEnd = pNativeCurrent + cbArray;
-
- while (pNativeCurrent < pNativeEnd)
+ BYTE* pNativeStart = reinterpret_cast<BYTE*>(*pNativeHome);
+ SIZE_T nativeOffset = 0;
+ SIZE_T nativeSize = pThis->m_pElementMT->GetNativeSize();
+ for (INT32 i = 0; i < cElements; ++i)
{
- LayoutDestroyNative(pNativeCurrent, m_pElementMT);
- pNativeCurrent += m_pElementMT->GetNativeSize();
+ MarshalStructViaILStubCode(pThis->m_pManagedMarshaler, nullptr, pNativeStart + nativeOffset, StructMarshalStubs::MarshalOperation::Cleanup);
+ nativeOffset += nativeSize;
}
break;
}
class ILStubMarshalHome
{
public:
- typedef enum
+ typedef enum : byte
{
HomeType_Unspecified = 0,
HomeType_ILLocal = 1,
} MarshalHomeType;
private:
- MarshalHomeType m_homeType;
DWORD m_dwHomeIndex;
+ LocalDesc m_locDesc;
+ MarshalHomeType m_homeType;
+ bool m_hasTypeInfo = false;
+ bool m_unalignedIndirectStore;
+
+ void EmitUnalignedPrefixIfNeeded(ILCodeStream* pslILEmit)
+ {
+ if (m_unalignedIndirectStore)
+ {
+ pslILEmit->EmitUNALIGNED(1);
+ }
+ }
public:
- void InitHome(MarshalHomeType homeType, DWORD dwHomeIndex)
+ void InitHome(MarshalHomeType homeType, DWORD dwHomeIndex, LocalDesc* pLocDesc = nullptr, bool unalignedIndirectStore = false)
{
LIMITED_METHOD_CONTRACT;
m_homeType = homeType;
m_dwHomeIndex = dwHomeIndex;
+ if (pLocDesc != nullptr)
+ {
+ m_hasTypeInfo = true;
+ m_locDesc = *pLocDesc;
+ }
+ m_unalignedIndirectStore = unalignedIndirectStore;
}
void EmitLoadHome(ILCodeStream* pslILEmit)
{
case HomeType_ILLocal: pslILEmit->EmitLDLOC(m_dwHomeIndex); break;
case HomeType_ILArgument: pslILEmit->EmitLDARG(m_dwHomeIndex); break;
+ case HomeType_ILByrefLocal:
+ CONSISTENCY_CHECK_MSG(m_hasTypeInfo, "Cannot load or store the value into a ILStub byref home without type information.");
+ pslILEmit->EmitLDLOC(m_dwHomeIndex);
+ EmitUnalignedPrefixIfNeeded(pslILEmit);
+ pslILEmit->EmitLDIND_T(&m_locDesc);
+ break;
+ case HomeType_ILByrefArgument:
+ CONSISTENCY_CHECK_MSG(m_hasTypeInfo, "Cannot load or store the value into a ILStub byref home without type information.");
+ pslILEmit->EmitLDARG(m_dwHomeIndex);
+ EmitUnalignedPrefixIfNeeded(pslILEmit);
+ pslILEmit->EmitLDIND_T(&m_locDesc);
+ break;
default:
UNREACHABLE_MSG("unexpected homeType passed to EmitLoadHome");
{
case HomeType_ILLocal: pslILEmit->EmitSTLOC(m_dwHomeIndex); break;
case HomeType_ILArgument: pslILEmit->EmitSTARG(m_dwHomeIndex); break;
+ case HomeType_ILByrefLocal:
+ {
+ CONSISTENCY_CHECK_MSG(m_hasTypeInfo, "Cannot load or store the value into a ILStub byref home without type information.");
+ DWORD swapLocal = pslILEmit->NewLocal(m_locDesc);
+ pslILEmit->EmitSTLOC(swapLocal);
+ pslILEmit->EmitLDLOC(m_dwHomeIndex);
+ pslILEmit->EmitLDLOC(swapLocal);
+ EmitUnalignedPrefixIfNeeded(pslILEmit);
+ pslILEmit->EmitSTIND_T(&m_locDesc);
+ break;
+ }
+ case HomeType_ILByrefArgument:
+ {
+ CONSISTENCY_CHECK_MSG(m_hasTypeInfo, "Cannot load or store the value into a ILStub byref home without type information.");
+ DWORD swapLocal = pslILEmit->NewLocal(m_locDesc);
+ pslILEmit->EmitSTLOC(swapLocal);
+ pslILEmit->EmitLDARG(m_dwHomeIndex);
+ pslILEmit->EmitLDLOC(swapLocal);
+ EmitUnalignedPrefixIfNeeded(pslILEmit);
+ pslILEmit->EmitSTIND_T(&m_locDesc);
+ break;
+ }
+
default:
UNREACHABLE_MSG("unexpected homeType passed to EmitStoreHome");
else
{
pslILEmit->EmitLDARG(argidx);
+ EmitUnalignedPrefixIfNeeded(pslILEmit);
pslILEmit->EmitLDIND_T(pManagedType);
EmitStoreHome(pslILEmit);
}
{
pslILEmit->EmitLDARG(argidx);
EmitLoadHome(pslILEmit);
+ EmitUnalignedPrefixIfNeeded(pslILEmit);
pslILEmit->EmitSTIND_T(pManagedType);
}
}
return (0 != (dwMarshalFlags & MARSHAL_FLAG_HIDDENLENPARAM));
}
+ static inline bool IsFieldMarshal(DWORD dwMarshalFlags)
+ {
+ LIMITED_METHOD_CONTRACT;
+ return (0 != (dwMarshalFlags & MARSHAL_FLAG_FIELD));
+ }
+
void EmitLoadManagedValue(ILCodeStream* pslILEmit)
{
WRAPPER_NO_CONTRACT;
return true;
}
+ virtual bool SupportsFieldMarshal(UINT* pErrorResID)
+ {
+ LIMITED_METHOD_CONTRACT;
+ return true;
+ }
+
// True if marshaling creates data that could need cleanup.
bool NeedsMarshalCleanupIndex()
{
return (NeedsClearNative() && !IsCLRToNative(m_dwMarshalFlags));
}
+ void EmitMarshalField(
+ ILCodeStream* pcsMarshal,
+ ILCodeStream* pcsUnmarshal,
+ UINT argidx,
+ UINT32 managedOffset,
+ UINT32 nativeOffset,
+ OverrideProcArgs* pargs)
+ {
+ STANDARD_VM_CONTRACT;
+
+ // Struct marshaling stubs are always in, and out
+ // since we generate a single stub for all three operations (managed->native, native->managed, cleanup)
+ // we set the clr-to-native flag so the marshal phase is CLR->Native and the unmarshal phase is Native->CLR
+ Init(pcsMarshal, pcsUnmarshal, argidx, MARSHAL_FLAG_IN | MARSHAL_FLAG_OUT | MARSHAL_FLAG_CLR_TO_NATIVE | MARSHAL_FLAG_FIELD, pargs);
+
+ EmitCreateMngdMarshaler(m_pslNDirect->GetSetupCodeStream());
+
+ EmitSetupArgumentForMarshalling(m_pslNDirect->GetSetupCodeStream());
+
+ EmitSetupDefaultHomesForField(
+ m_pslNDirect->GetSetupCodeStream(),
+ managedOffset,
+ nativeOffset);
+
+ EmitMarshalFieldSpaceAndContents();
+ }
+
void EmitMarshalArgument(
ILCodeStream* pcsMarshal,
ILCodeStream* pcsUnmarshal,
}
}
-
protected:
virtual void EmitCreateMngdMarshaler(ILCodeStream* pslILEmit)
m_nativeHome.InitHome(ILStubMarshalHome::HomeType_ILArgument, m_argidx);
}
+ void EmitSetupDefaultHomesForField(ILCodeStream* pcsSetup, UINT32 managedOffset, UINT32 nativeOffset)
+ {
+ LocalDesc managedType(GetManagedType());
+ LocalDesc managedFieldTypeByRef(GetManagedType());
+ managedFieldTypeByRef.MakeByRef();
+
+ m_managedHome.InitHome(ILStubMarshalHome::HomeType_ILByrefLocal, pcsSetup->NewLocal(managedFieldTypeByRef), &managedType, /* unalignedIndirectStore */ true);
+
+ LocalDesc nativeType(GetNativeType());
+ LocalDesc nativeFieldTypeByRef(GetNativeType());
+ nativeFieldTypeByRef.MakeByRef();
+
+ m_nativeHome.InitHome(ILStubMarshalHome::HomeType_ILByrefLocal, pcsSetup->NewLocal(nativeFieldTypeByRef), &nativeType, /* unalignedIndirectStore */ true);
+
+ pcsSetup->EmitNOP("// field setup {");
+ pcsSetup->EmitNOP("// managed field setup {");
+ pcsSetup->EmitLDARG(StructMarshalStubs::MANAGED_STRUCT_ARGIDX);
+ pcsSetup->EmitLDC(managedOffset);
+ pcsSetup->EmitADD();
+ EmitStoreManagedHomeAddr(pcsSetup);
+ pcsSetup->EmitNOP("// } managed field setup");
+ pcsSetup->EmitNOP("// native field setup {");
+
+ pcsSetup->EmitLDARG(StructMarshalStubs::NATIVE_STRUCT_ARGIDX);
+ pcsSetup->EmitLDC(nativeOffset);
+ pcsSetup->EmitADD();
+ EmitStoreNativeHomeAddr(pcsSetup);
+ pcsSetup->EmitNOP("// } native field setup");
+ pcsSetup->EmitNOP("// } field setup");
+ }
+
+ virtual void EmitMarshalFieldSpaceAndContents()
+ {
+ STANDARD_VM_CONTRACT;
+
+ EmitConvertSpaceAndContentsCLRToNative(m_pcsMarshal);
+ EmitConvertSpaceAndContentsNativeToCLR(m_pcsUnmarshal);
+ if (NeedsClearNative())
+ {
+ ILCodeStream* pcsCleanup = m_pslNDirect->GetCleanupCodeStream();
+ EmitClearNative(pcsCleanup);
+ }
+ }
+
void EmitCleanupNativeToCLR()
{
STANDARD_VM_CONTRACT;
{
// Don't use the cleanup work list to avoid any extra allocations.
m_pslNDirect->SetCleanupNeeded();
+
ILCodeStream* pslILEmit = m_pslNDirect->GetCleanupCodeStream();
+
+ ILCodeLabel* pNoManagedValueLabel = nullptr;
+ if (IsFieldMarshal(m_dwMarshalFlags))
+ {
+ pNoManagedValueLabel = pslILEmit->NewCodeLabel();
+ pslILEmit->EmitLDARG(StructMarshalStubs::MANAGED_STRUCT_ARGIDX);
+ pslILEmit->EmitBRFALSE(pNoManagedValueLabel);
+ }
+
EmitLoadValueToKeepAlive(pslILEmit);
pslILEmit->EmitCALL(METHOD__GC__KEEP_ALIVE, 1, 0);
+
+ if (IsFieldMarshal(m_dwMarshalFlags))
+ {
+ pslILEmit->EmitLabel(pNoManagedValueLabel);
+ }
}
public:
#if defined(_TARGET_AMD64_)
// If the argument is passed by value,
- if (!IsByref(m_dwMarshalFlags) && !IsRetval(m_dwMarshalFlags))
+ if (!IsByref(m_dwMarshalFlags) && !IsRetval(m_dwMarshalFlags) && !IsFieldMarshal(m_dwMarshalFlags))
{
// and it is an I4 or an U4,
if ( (ELEMENT_TYPE == ELEMENT_TYPE_I4) ||
return LocalDesc();
}
+ virtual bool SupportsFieldMarshal(UINT* pErrorResID)
+ {
+ LIMITED_METHOD_CONTRACT;
+ return false;
+ }
+
static MarshalerOverrideStatus ArgumentOverride(NDirectStubLinker* psl,
BOOL byref,
BOOL fin,
LocalDesc GetManagedType() override
{
LIMITED_METHOD_CONTRACT;
- return LocalDesc();
+ return LocalDesc(MscorlibBinder::GetClass(CLASS__SAFE_HANDLE));
}
LocalDesc GetNativeType() override
{
LIMITED_METHOD_CONTRACT;
- return LocalDesc();
+ return LocalDesc(ELEMENT_TYPE_I);
}
+ void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override;
+ void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override;
+
static MarshalerOverrideStatus ArgumentOverride(NDirectStubLinker* psl,
BOOL byref,
BOOL fin,
LocalDesc GetManagedType() override
{
LIMITED_METHOD_CONTRACT;
- return LocalDesc();
+ return LocalDesc(MscorlibBinder::GetClass(CLASS__CRITICAL_HANDLE));
}
-
+
LocalDesc GetNativeType() override
{
LIMITED_METHOD_CONTRACT;
- return LocalDesc();
+ return LocalDesc(ELEMENT_TYPE_I);
}
+
+ void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override;
+ void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override;
static MarshalerOverrideStatus ArgumentOverride(NDirectStubLinker* psl,
BOOL byref,
UINT *pResID);
};
-
class ILValueClassMarshaler : public ILMarshaler
{
public:
c_CLRSize = sizeof(ELEMENT),
};
+ bool SupportsFieldMarshal(UINT* pErrorResID) override
+ {
+ LIMITED_METHOD_CONTRACT;
+ return false;
+ }
+
protected:
LocalDesc GetNativeType() override
{
void EmitClearNative(ILCodeStream* pslILEmit) override;
};
-class ILLayoutClassPtrMarshalerBase : public ILMarshaler
+class ILFixedWSTRMarshaler : public ILMarshaler
+{
+public:
+ enum
+ {
+ c_fInOnly = FALSE,
+ c_nativeSize = VARIABLESIZE,
+ c_CLRSize = sizeof(OBJECTREF)
+ };
+
+ bool SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID) override
+ {
+ LIMITED_METHOD_CONTRACT;
+ return false;
+ }
+
+ bool SupportsReturnMarshal(DWORD dwMarshalFlags, UINT* pErrorResID) override
+ {
+ LIMITED_METHOD_CONTRACT;
+ return false;
+ }
+
+protected:
+ LocalDesc GetNativeType() override
+ {
+ return LocalDesc(ELEMENT_TYPE_I2);
+ }
+
+ LocalDesc GetManagedType() override
+ {
+ return LocalDesc(ELEMENT_TYPE_STRING);
+ }
+
+ void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override;
+ void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override;
+};
+
+class ILFixedCSTRMarshaler : public ILMarshaler
+{
+public:
+ enum
+ {
+ c_fInOnly = FALSE,
+ c_nativeSize = VARIABLESIZE,
+ c_CLRSize = sizeof(OBJECTREF)
+ };
+
+ bool SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID) override
+ {
+ LIMITED_METHOD_CONTRACT;
+ return false;
+ }
+
+ bool SupportsReturnMarshal(DWORD dwMarshalFlags, UINT* pErrorResID) override
+ {
+ LIMITED_METHOD_CONTRACT;
+ return false;
+ }
+
+protected:
+ LocalDesc GetNativeType() override
+ {
+ return LocalDesc(ELEMENT_TYPE_I1);
+ }
+
+ LocalDesc GetManagedType() override
+ {
+ return LocalDesc(ELEMENT_TYPE_STRING);
+ }
+
+ void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override;
+ void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override;
+};
+
+class ILLayoutClassMarshalerBase : public ILMarshaler
+{
+protected:
+ void EmitLoadReferenceToFirstManagedObjectField(ILCodeStream* pslILEmit)
+ {
+ LocalDesc byteByref(ELEMENT_TYPE_I1);
+ byteByref.MakeByRef();
+
+ DWORD managedObjectFieldLocal = pslILEmit->NewLocal(byteByref);
+
+ // Get "ref byte" value that points to first field in the managed object.
+ EmitLoadManagedValue(pslILEmit);
+ pslILEmit->EmitSTLOC(managedObjectFieldLocal);
+ pslILEmit->EmitLDLOC(managedObjectFieldLocal);
+ pslILEmit->EmitLDC(Object::GetOffsetOfFirstField());
+ pslILEmit->EmitADD();
+ }
+};
+
+class ILLayoutClassPtrMarshalerBase : public ILLayoutClassMarshalerBase
{
public:
enum
public:
enum
{
- c_fInOnly = FALSE,
+ c_fInOnly = FALSE,
};
-
-protected:
+
+protected:
void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override;
void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override;
- void EmitClearNativeContents(ILCodeStream * pslILEmit) override;
+ void EmitClearNativeContents(ILCodeStream* pslILEmit) override;
};
class ILBlittablePtrMarshaler : public ILLayoutClassPtrMarshalerBase
public:
enum
{
- c_fInOnly = FALSE,
+ c_fInOnly = FALSE,
};
-
+
protected:
void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override;
void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override;
bool CanUsePinnedLayoutClass();
};
+class ILLayoutClassMarshaler : public ILLayoutClassMarshalerBase
+{
+public:
+ enum
+ {
+ c_fInOnly = FALSE,
+ c_nativeSize = VARIABLESIZE,
+ c_CLRSize = sizeof(OBJECTREF),
+ };
+
+ LocalDesc GetNativeType() override
+ {
+ return LocalDesc(ELEMENT_TYPE_I);
+ }
+
+ LocalDesc GetManagedType() override
+ {
+ return LocalDesc(m_pargs->m_pMT);
+ }
+
+protected:
+ void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override;
+ void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit) override;
+ void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override;
+ void EmitClearNativeContents(ILCodeStream* pslILEmit) override;
+ void EmitClearNative(ILCodeStream* pslILEmit) override
+ {
+ EmitClearNativeContents(pslILEmit);
+ }
+};
+
+class ILBlittableLayoutClassMarshaler : public ILMarshaler
+{
+public:
+ enum
+ {
+ c_fInOnly = FALSE,
+ c_nativeSize = VARIABLESIZE,
+ c_CLRSize = sizeof(OBJECTREF),
+ };
+
+ LocalDesc GetNativeType() override
+ {
+ return LocalDesc(ELEMENT_TYPE_I);
+ }
+
+ LocalDesc GetManagedType() override
+ {
+ return LocalDesc(m_pargs->m_pMT);
+ }
+
+protected:
+ void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override;
+ void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override;
+};
+
class ILBlittableValueClassWithCopyCtorMarshaler : public ILMarshaler
{
public:
return true;
}
+ bool SupportsFieldMarshal(UINT* pErrorResID) override
+ {
+ LIMITED_METHOD_CONTRACT;
+ return false;
+ }
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
void EmitClearNative(ILCodeStream* pslILEmit) override;
void EmitClearNativeContents(ILCodeStream* pslILEmit) override;
+ bool SupportsFieldMarshal(UINT* pErrorResID) override
+ {
+ LIMITED_METHOD_CONTRACT;
+ return false;
+ }
protected:
BOOL CheckSizeParamIndexArg(const CREATE_MARSHALER_CARRAY_OPERANDS &mops, CorElementType *pElementType);
class MngdNativeArrayMarshaler
{
public:
- static FCDECL3(void, CreateMarshaler, MngdNativeArrayMarshaler* pThis, MethodTable* pMT, UINT32 dwFlags);
+ static FCDECL4(void, CreateMarshaler, MngdNativeArrayMarshaler* pThis, MethodTable* pMT, UINT32 dwFlags, PCODE pManagedMarshaler);
static FCDECL3(void, ConvertSpaceToNative, MngdNativeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
static FCDECL3(void, ConvertContentsToNative, MngdNativeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
static FCDECL4(void, ConvertSpaceToManaged, MngdNativeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome, INT32 cElements);
static FCDECL3(void, ConvertContentsToManaged, MngdNativeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
- static FCDECL3(void, ClearNative, MngdNativeArrayMarshaler* pThis, void** pNativeHome, INT32 cElements);
- static FCDECL3(void, ClearNativeContents, MngdNativeArrayMarshaler* pThis, void** pNativeHome, INT32 cElements);
+ static FCDECL4(void, ClearNative, MngdNativeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome, INT32 cElements);
+ static FCDECL4(void, ClearNativeContents, MngdNativeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome, INT32 cElements);
- static void DoClearNativeContents(MngdNativeArrayMarshaler* pThis, void** pNativeHome, INT32 cElements);
-
+ static void DoClearNativeContents(MngdNativeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome, INT32 cElements);
enum
{
FLAG_NATIVE_DATA_VALID = 0x40000000
MethodTable* m_pElementMT;
TypeHandle m_Array;
+ PCODE m_pManagedMarshaler;
BOOL m_NativeDataValid;
BOOL m_BestFitMap;
BOOL m_ThrowOnUnmappableChar;
VARTYPE m_vt;
};
+class ILFixedArrayMarshaler : public ILMngdMarshaler
+{
+public:
+ enum
+ {
+ c_nativeSize = VARIABLESIZE,
+ c_fInOnly = FALSE
+ };
+
+ ILFixedArrayMarshaler() :
+ ILMngdMarshaler(
+ METHOD__MNGD_FIXED_ARRAY_MARSHALER__CONVERT_SPACE_TO_MANAGED,
+ METHOD__MNGD_FIXED_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_MANAGED,
+ METHOD__MNGD_FIXED_ARRAY_MARSHALER__CONVERT_SPACE_TO_NATIVE,
+ METHOD__MNGD_FIXED_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_NATIVE,
+ METHOD__MNGD_FIXED_ARRAY_MARSHALER__CLEAR_NATIVE_CONTENTS,
+ METHOD__MNGD_FIXED_ARRAY_MARSHALER__CLEAR_NATIVE_CONTENTS,
+ METHOD__NIL
+ )
+ {
+ LIMITED_METHOD_CONTRACT;
+ }
+
+ bool SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID) override
+ {
+ LIMITED_METHOD_CONTRACT;
+ return false;
+ }
+
+ bool SupportsReturnMarshal(DWORD dwMarshalFlags, UINT* pErrorResID) override
+ {
+ LIMITED_METHOD_CONTRACT;
+ return false;
+ }
+
+protected:
+
+ void EmitCreateMngdMarshaler(ILCodeStream* pslILEmit) override;
+};
+
+class MngdFixedArrayMarshaler
+{
+public:
+ static FCDECL5(void, CreateMarshaler, MngdFixedArrayMarshaler* pThis, MethodTable* pMT, UINT32 dwFlags, UINT32 cElements, PCODE pManagedElementMarshaler);
+ static FCDECL3(void, ConvertSpaceToNative, MngdFixedArrayMarshaler* pThis, OBJECTREF* pManagedHome, void* pNativeHome);
+ static FCDECL3(void, ConvertContentsToNative, MngdFixedArrayMarshaler* pThis, OBJECTREF* pManagedHome, void* pNativeHome);
+ static FCDECL3(void, ConvertSpaceToManaged, MngdFixedArrayMarshaler* pThis, OBJECTREF* pManagedHome, void* pNativeHome);
+ static FCDECL3(void, ConvertContentsToManaged, MngdFixedArrayMarshaler* pThis, OBJECTREF* pManagedHome, void* pNativeHome);
+ static FCDECL3(void, ClearNativeContents, MngdFixedArrayMarshaler* pThis, OBJECTREF* pManagedHome, void* pNativeHome);
+
+ enum
+ {
+ FLAG_NATIVE_DATA_VALID = 0x40000000
+ };
+
+ MethodTable* m_pElementMT;
+ PCODE m_pManagedElementMarshaler;
+ TypeHandle m_Array;
+ BOOL m_NativeDataValid;
+ BOOL m_BestFitMap;
+ BOOL m_ThrowOnUnmappableChar;
+ VARTYPE m_vt;
+ UINT32 m_cElements;
+};
#ifdef FEATURE_COMINTEROP
class ILSafeArrayMarshaler : public ILMngdMarshaler
class MngdSafeArrayMarshaler
{
public:
- static FCDECL4(void, CreateMarshaler, MngdSafeArrayMarshaler* pThis, MethodTable* pMT, UINT32 iRank, UINT32 dwFlags);
+ static FCDECL5(void, CreateMarshaler, MngdSafeArrayMarshaler* pThis, MethodTable* pMT, UINT32 iRank, UINT32 dwFlags, PCODE pManagedMarshaler);
static FCDECL3(void, ConvertSpaceToNative, MngdSafeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
static FCDECL4(void, ConvertContentsToNative, MngdSafeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome, Object* pOriginalManagedUNSAFE);
static FCDECL3(void, ConvertSpaceToManaged, MngdSafeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
};
MethodTable* m_pElementMT;
+ PCODE m_pManagedMarshaler;
int m_iRank;
VARTYPE m_vt;
BYTE m_fStatic; // StaticCheckStateFlags
class MngdHiddenLengthArrayMarshaler
{
public:
- static FCDECL4(void, CreateMarshaler, MngdHiddenLengthArrayMarshaler* pThis, MethodTable* pMT, SIZE_T cbElement, UINT16 vt);
+ static FCDECL5(void, CreateMarshaler, MngdHiddenLengthArrayMarshaler* pThis, MethodTable* pMT, SIZE_T cbElement, UINT16 vt, PCODE pManagedMarshaler);
static FCDECL3(void, ConvertSpaceToNative, MngdHiddenLengthArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
static FCDECL3(void, ConvertContentsToNative, MngdHiddenLengthArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
static FCDECL4(void, ConvertSpaceToManaged, MngdHiddenLengthArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome, INT32 cElements);
private:
SIZE_T GetArraySize(SIZE_T elements);
- void DoClearNativeContents(void** pNativeHome, INT32 cElements);
+ void DoClearNativeContents(MngdHiddenLengthArrayMarshaler* pThis, void** pNativeHome, INT32 cElements);
private:
- MethodTable *m_pElementMT;
- SIZE_T m_cbElementSize;
- VARTYPE m_vt;
+ MethodTable* m_pElementMT;
+ PCODE m_pManagedMarshaler;
+ SIZE_T m_cbElementSize;
+ VARTYPE m_vt;
};
#endif // FEATURE_COMINTEROP
memset((void*)pMD->m_pResolver, 0xCC, sizeof(ILStubResolver));
#endif // _DEBUG
pMD->m_pResolver = new (pMD->m_pResolver) ILStubResolver();
+ pMD->GetILStubResolver()->SetLoaderHeap(pCreationHeap);
#ifdef FEATURE_ARRAYSTUB_AS_IL
if (SF_IsArrayOpStub(dwStubFlags))
}
else
#endif
+ if (SF_IsStructMarshalStub(dwStubFlags))
+ {
+ pMD->m_dwExtendedFlags |= DynamicMethodDesc::nomdStructMarshalStub;
+ pMD->GetILStubResolver()->SetStubType(ILStubResolver::StructMarshalInteropStub);
+ }
+ else
{
// mark certain types of stub MDs with random flags so ILStubManager recognizes them
if (SF_IsReverseStub(dwStubFlags))
case NativeToCLRInteropStub: return "IL_STUB_ReversePInvoke";
case COMToCLRInteropStub: return "IL_STUB_COMtoCLR";
case WinRTToCLRInteropStub: return "IL_STUB_WinRTtoCLR";
+ case StructMarshalInteropStub: return "IL_STUB_StructMarshal";
#ifdef FEATURE_ARRAYSTUB_AS_IL
case ArrayOpStub: return "IL_STUB_Array";
#endif
m_pStubMD(dac_cast<PTR_MethodDesc>(nullptr)),
m_pStubTargetMD(dac_cast<PTR_MethodDesc>(nullptr)),
m_type(Unassigned),
- m_jitFlags()
+ m_jitFlags(),
+ m_loaderHeap(dac_cast<PTR_LoaderHeap>(nullptr))
{
LIMITED_METHOD_CONTRACT;
}
+void ILStubResolver::SetLoaderHeap(PTR_LoaderHeap pLoaderHeap)
+{
+ m_loaderHeap = pLoaderHeap;
+}
+
+void ILStubResolver::CreateILHeader(COR_ILMETHOD_DECODER* pILHeader, size_t cbCode, UINT maxStack, BYTE* pNewILCodeBuffer, BYTE* pNewLocalSig, DWORD cbLocalSig)
+{
+ pILHeader->Flags = 0;
+ pILHeader->CodeSize = (DWORD)cbCode;
+ pILHeader->MaxStack = maxStack;
+ pILHeader->EH = 0;
+ pILHeader->Sect = 0;
+ pILHeader->Code = pNewILCodeBuffer;
+ pILHeader->LocalVarSig = pNewLocalSig;
+ pILHeader->cbLocalVarSig = cbLocalSig;
+}
+
//---------------------------------------------------------------------------------------
//
COR_ILMETHOD_DECODER *
#if !defined(DACCESS_COMPILE)
_ASSERTE(0 != cbCode);
- NewArrayHolder<BYTE> pNewILCodeBuffer = NULL;
- NewArrayHolder<BYTE> pNewLocalSig = NULL;
- NewArrayHolder<CompileTimeState> pNewCompileTimeState = NULL;
+ if (!UseLoaderHeap())
+ {
+ NewArrayHolder<BYTE> pNewILCodeBuffer = new BYTE[cbCode];
+ NewArrayHolder<CompileTimeState> pNewCompileTimeState = (CompileTimeState*)new BYTE[sizeof(CompileTimeState)];
+ memset(pNewCompileTimeState, 0, sizeof(CompileTimeState));
+ NewArrayHolder<BYTE> pNewLocalSig = NULL;
+
+ if (0 != cbLocalSig)
+ {
+ pNewLocalSig = new BYTE[cbLocalSig];
+ }
- pNewCompileTimeState = (CompileTimeState *)new BYTE[sizeof(CompileTimeState)];
- memset(pNewCompileTimeState, 0, sizeof(CompileTimeState));
+ COR_ILMETHOD_DECODER* pILHeader = &pNewCompileTimeState->m_ILHeader;
- pNewILCodeBuffer = new BYTE[cbCode];
+ CreateILHeader(pILHeader, cbCode, maxStack, pNewILCodeBuffer, pNewLocalSig, cbLocalSig);
- if (0 != cbLocalSig)
- {
- pNewLocalSig = new BYTE[cbLocalSig];
+#ifdef _DEBUG
+ LPVOID pPrevCompileTimeState =
+#endif // _DEBUG
+ FastInterlockExchangePointer(&m_pCompileTimeState, pNewCompileTimeState.GetValue());
+ CONSISTENCY_CHECK(ILNotYetGenerated == (UINT_PTR)pPrevCompileTimeState);
+
+ pNewLocalSig.SuppressRelease();
+ pNewILCodeBuffer.SuppressRelease();
+ pNewCompileTimeState.SuppressRelease();
+ return pILHeader;
}
+ else
+ {
+ CONSISTENCY_CHECK(m_loaderHeap != dac_cast<PTR_LoaderHeap>(nullptr));
- COR_ILMETHOD_DECODER* pILHeader = &pNewCompileTimeState->m_ILHeader;
+ AllocMemHolder<BYTE> pNewILCodeBuffer(m_loaderHeap->AllocMem(S_SIZE_T(cbCode)));
+ AllocMemHolder<CompileTimeState> pNewCompileTimeState(m_loaderHeap->AllocMem(S_SIZE_T(sizeof(CompileTimeState))));
+ memset(pNewCompileTimeState, 0, sizeof(CompileTimeState));
+ AllocMemHolder<BYTE> pNewLocalSig;
- pILHeader->Flags = 0;
- pILHeader->CodeSize = (DWORD)cbCode;
- pILHeader->MaxStack = maxStack;
- pILHeader->EH = 0;
- pILHeader->Sect = 0;
- pILHeader->Code = pNewILCodeBuffer;
- pILHeader->LocalVarSig = pNewLocalSig;
- pILHeader->cbLocalVarSig = cbLocalSig;
+ if (0 != cbLocalSig)
+ {
+ pNewLocalSig = m_loaderHeap->AllocMem(S_SIZE_T(cbLocalSig));
+ }
-#ifdef _DEBUG
- LPVOID pPrevCompileTimeState =
-#endif // _DEBUG
- FastInterlockExchangePointer(&m_pCompileTimeState, pNewCompileTimeState.GetValue());
- CONSISTENCY_CHECK(ILNotYetGenerated == (UINT_PTR)pPrevCompileTimeState);
+ COR_ILMETHOD_DECODER* pILHeader = &pNewCompileTimeState->m_ILHeader;
- pNewLocalSig.SuppressRelease();
- pNewILCodeBuffer.SuppressRelease();
- pNewCompileTimeState.SuppressRelease();
+ CreateILHeader(pILHeader, cbCode, maxStack, pNewILCodeBuffer, pNewLocalSig, cbLocalSig);
- return pILHeader;
+#ifdef _DEBUG
+ LPVOID pPrevCompileTimeState =
+#endif // _DEBUG
+ FastInterlockExchangePointer(&m_pCompileTimeState, (CompileTimeState*)pNewCompileTimeState);
+ CONSISTENCY_CHECK(ILNotYetGenerated == (UINT_PTR)pPrevCompileTimeState);
+
+ pNewLocalSig.SuppressRelease();
+ pNewILCodeBuffer.SuppressRelease();
+ pNewCompileTimeState.SuppressRelease();
+ return pILHeader;
+ }
#else // DACCESS_COMPILE
DacNotImpl();
}
}
+bool ILStubResolver::UseLoaderHeap()
+{
+ // Struct marshal stub MethodDescs might be directly called from `call` IL instructions
+ // so we want to keep their compile time data alive as long as the LoaderAllocator in case they're used again.
+ return m_type == StructMarshalInteropStub;
+}
+
void ILStubResolver::FreeCompileTimeState()
{
CONTRACTL
return;
}
- ClearCompileTimeState(ILGeneratedAndFreed);
+ if (!UseLoaderHeap())
+ {
+ ClearCompileTimeState(ILGeneratedAndFreed);
+ }
+
}
//---------------------------------------------------------------------------------------
NOTHROW;
GC_NOTRIGGER;
MODE_ANY;
+ PRECONDITION(!UseLoaderHeap());
}
CONTRACTL_END;
void SetStubTargetMethodSig(PCCOR_SIGNATURE pStubTargetMethodSig, DWORD cbStubTargetSigLength);
void SetStubMethodDesc(MethodDesc* pStubMD);
+ void CreateILHeader(COR_ILMETHOD_DECODER* pILHeader, size_t cbCode, UINT maxStack, BYTE* pNewILCodeBuffer, BYTE* pNewLocalSig, DWORD cbLocalSig);
+
COR_ILMETHOD_DECODER * AllocGeneratedIL(size_t cbCode, DWORD cbLocalSig, UINT maxStack);
COR_ILMETHOD_DECODER * GetILHeader();
COR_ILMETHOD_SECT_EH* AllocEHSect(size_t nClauses);
void SetJitFlags(CORJIT_FLAGS jitFlags);
CORJIT_FLAGS GetJitFlags();
+ void SetLoaderHeap(PTR_LoaderHeap pLoaderHeap);
+
static void StubGenFailed(ILStubResolver* pResolver);
protected:
NativeToCLRInteropStub,
COMToCLRInteropStub,
WinRTToCLRInteropStub,
+ StructMarshalInteropStub,
#ifdef FEATURE_ARRAYSTUB_AS_IL
ArrayOpStub,
#endif
void ClearCompileTimeState(CompileTimeStatePtrSpecialValues newState);
void SetStubType(ILStubType stubType);
+ bool UseLoaderHeap();
//
// This stuff is only needed during JIT
PTR_MethodDesc m_pStubTargetMD;
ILStubType m_type;
CORJIT_FLAGS m_jitFlags;
+ PTR_LoaderHeap m_loaderHeap;
};
typedef Holder<ILStubResolver*, DoNothing<ILStubResolver*>, ILStubResolver::StubGenFailed, NULL> ILStubGenHolder;
}
else if (pMT->HasLayout())
{
+ MethodDesc* structMarshalStub;
+
+ {
+ GCX_PREEMP();
+ structMarshalStub = NDirect::CreateStructMarshalILStub(pMT);
+ }
+
if (fDeleteOld)
- LayoutDestroyNative(ptr, pMT);
+ {
+ MarshalStructViaILStub(structMarshalStub, pObj->GetData(), ptr, StructMarshalStubs::MarshalOperation::Cleanup);
+ }
- FmtClassUpdateNative( &(pObj), (LPBYTE)(ptr), NULL );
+ MarshalStructViaILStub(structMarshalStub, pObj->GetData(), ptr, StructMarshalStubs::MarshalOperation::Marshal);
}
else
{
}
else if (pMT->HasLayout())
{
- LayoutUpdateCLR((LPVOID*) &(pObj), Object::GetOffsetOfFirstField(), pMT, (LPBYTE)(ptr));
+ MethodDesc* structMarshalStub;
+
+ {
+ GCX_PREEMP();
+ structMarshalStub = NDirect::CreateStructMarshalILStub(pMT);
+ }
+
+ MarshalStructViaILStub(structMarshalStub, pObj->GetData(), ptr, StructMarshalStubs::MarshalOperation::Unmarshal);
}
else
{
}
else if (th.HasLayout())
{
- LayoutDestroyNative(ptr, th.GetMethodTable());
+ MethodDesc* structMarshalStub;
+
+ {
+ GCX_PREEMP();
+ structMarshalStub = NDirect::CreateStructMarshalILStub(th.GetMethodTable());
+ }
+
+ MarshalStructViaILStub(structMarshalStub, nullptr, ptr, StructMarshalStubs::MarshalOperation::Cleanup);
}
else
{
HELPER_METHOD_FRAME_END();
}
- FieldMarshaler *pFM = th.GetMethodTable()->GetLayoutInfo()->GetFieldMarshalers();
+ NativeFieldDescriptor *pNFD = th.GetMethodTable()->GetLayoutInfo()->GetNativeFieldDescriptors();
UINT numReferenceFields = th.GetMethodTable()->GetLayoutInfo()->GetNumCTMFields();
while (numReferenceFields--)
{
- if (pFM->GetFieldDesc() == pField)
+ if (pNFD->GetFieldDesc() == pField)
{
- return pFM->GetExternalOffset();
+ return pNFD->GetExternalOffset();
}
- ((BYTE*&)pFM) += MAXFIELDMARSHALERSIZE;
+ pNFD++;
}
UNREACHABLE_MSG("We should never hit this point since we already verified that the requested field was present from managed code");
DEFINE_METASIG(SM(IntPtr_IntPtr_Obj_RetIntPtr, I I j, I))
DEFINE_METASIG(SM(IntPtr_IntPtr_Int_Obj_RetIntPtr, I I i j, I))
DEFINE_METASIG(SM(IntPtr_IntPtr_IntPtr_RetVoid, I I I, v))
-DEFINE_METASIG(SM(IntPtr_IntPtr_IntPtr_UShrt_RetVoid, I I I H, v))
+DEFINE_METASIG(SM(IntPtr_IntPtr_IntPtr_UShrt_IntPtr_RetVoid, I I I H I, v))
DEFINE_METASIG(SM(IntPtr_Int_IntPtr_RetIntPtr, I i I, I))
DEFINE_METASIG(SM(IntPtr_IntPtr_Int_IntPtr_RetVoid, I I i I, v))
DEFINE_METASIG(SM(IntPtr_IntPtr_Obj_RetVoid, I I j, v))
DEFINE_METASIG(SM(RetBool, _, F))
DEFINE_METASIG(SM(IntPtr_RetStr, I, s))
DEFINE_METASIG(SM(IntPtr_RetBool, I, F))
-DEFINE_METASIG(SM(IntPtrIntPtrIntPtr_RetVoid, I I I, v))
-DEFINE_METASIG_T(SM(IntPtrIntPtrIntPtr_RefCleanupWorkListElement_RetVoid, I I I r(C(CLEANUP_WORK_LIST_ELEMENT)), v))
DEFINE_METASIG_T(SM(RuntimeType_RuntimeMethodHandleInternal_RetMethodBase, C(CLASS) g(METHOD_HANDLE_INTERNAL), C(METHOD_BASE) ))
DEFINE_METASIG_T(SM(RuntimeType_IRuntimeFieldInfo_RetFieldInfo, C(CLASS) C(I_RT_FIELD_INFO), C(FIELD_INFO) ))
DEFINE_METASIG_T(SM(RuntimeType_Int_RetPropertyInfo, C(CLASS) i, C(PROPERTY_INFO) ))
DEFINE_METASIG(SM(Str_Bool_Bool_RefInt_RetIntPtr, s F F r(i), I))
DEFINE_METASIG(SM(IntPtr_Int_RetStr, I i, s))
DEFINE_METASIG_T(SM(Obj_PtrByte_RefCleanupWorkListElement_RetVoid, j P(b) r(C(CLEANUP_WORK_LIST_ELEMENT)), v))
+DEFINE_METASIG_T(SM(SafeHandle_Bool_RefCleanupWorkListElement_RetIntPtr, C(SAFE_HANDLE) F r(C(CLEANUP_WORK_LIST_ELEMENT)), I))
DEFINE_METASIG(SM(Obj_PtrByte_RetVoid, j P(b), v))
DEFINE_METASIG(SM(PtrByte_IntPtr_RetVoid, P(b) I, v))
DEFINE_METASIG(SM(Str_Bool_Bool_RefInt_RetArrByte, s F F r(i), a(b) ))
DEFINE_METASIG(SM(IntPtr_RefObj_IntPtr_RetVoid, I r(j) I, v))
DEFINE_METASIG(SM(IntPtr_RefObj_IntPtr_Int_RetVoid, I r(j) I i,v))
DEFINE_METASIG(SM(IntPtr_Int_IntPtr_Int_Int_Int_RetVoid, I i I i i i, v))
-DEFINE_METASIG(SM(IntPtr_IntPtr_Int_Int_RetVoid, I I i i, v))
+DEFINE_METASIG(SM(IntPtr_IntPtr_Int_Int_IntPtr_RetVoid, I I i i I, v))
DEFINE_METASIG(SM(IntPtr_RefObj_IntPtr_Obj_RetVoid, I r(j) I j, v))
DEFINE_METASIG(SM(Obj_Int_RetVoid, j i,v))
DEFINE_METASIG_T(SM(Str_RetICustomMarshaler, s, C(ICUSTOM_MARSHALER)))
DEFINE_METASIG(SM(Int_Str_RetIntPtr, i s, I))
DEFINE_METASIG(SM(Int_Str_IntPtr_RetIntPtr, i s I, I))
+DEFINE_METASIG(SM(Int_Str_IntPtr_Int_RetVoid, i s I i, v))
DEFINE_METASIG(SM(Str_IntPtr_RetIntPtr, s I, I))
DEFINE_METASIG(SM(Str_Bool_Int_RetV, s F i, v))
// mdStatic = 0x0010,
nomdCALLIStub = 0x0020,
nomdDelegateStub = 0x0040,
- // unused = 0x0080
+ nomdStructMarshalStub = 0x0080,
nomdUnbreakable = 0x0100,
nomdDelegateCOMStub = 0x0200, // CLR->COM or COM->CLR call via a delegate (WinRT specific)
nomdSignatureNeedsRestore = 0x0400,
bool IsReverseStub() { LIMITED_METHOD_DAC_CONTRACT; _ASSERTE(IsILStub()); return (0 != (m_dwExtendedFlags & nomdReverseStub)); }
bool IsCALLIStub() { LIMITED_METHOD_DAC_CONTRACT; _ASSERTE(IsILStub()); return (0 != (m_dwExtendedFlags & nomdCALLIStub)); }
bool IsDelegateStub() { LIMITED_METHOD_DAC_CONTRACT; _ASSERTE(IsILStub()); return (0 != (m_dwExtendedFlags & nomdDelegateStub)); }
- bool IsCLRToCOMStub() { LIMITED_METHOD_CONTRACT; _ASSERTE(IsILStub()); return ((0 == (m_dwExtendedFlags & mdStatic)) && !IsReverseStub() && !IsDelegateStub()); }
+ bool IsCLRToCOMStub() { LIMITED_METHOD_CONTRACT; _ASSERTE(IsILStub()); return ((0 == (m_dwExtendedFlags & mdStatic)) && !IsReverseStub() && !IsDelegateStub() && !IsStructMarshalStub()); }
bool IsCOMToCLRStub() { LIMITED_METHOD_CONTRACT; _ASSERTE(IsILStub()); return ((0 == (m_dwExtendedFlags & mdStatic)) && IsReverseStub()); }
- bool IsPInvokeStub() { LIMITED_METHOD_CONTRACT; _ASSERTE(IsILStub()); return ((0 != (m_dwExtendedFlags & mdStatic)) && !IsReverseStub() && !IsCALLIStub()); }
+ bool IsPInvokeStub() { LIMITED_METHOD_CONTRACT; _ASSERTE(IsILStub()); return ((0 != (m_dwExtendedFlags & mdStatic)) && !IsReverseStub() && !IsCALLIStub() && !IsStructMarshalStub()); }
bool IsUnbreakable() { LIMITED_METHOD_CONTRACT; _ASSERTE(IsILStub()); return (0 != (m_dwExtendedFlags & nomdUnbreakable)); }
bool IsDelegateCOMStub() { LIMITED_METHOD_CONTRACT; _ASSERTE(IsILStub()); return (0 != (m_dwExtendedFlags & nomdDelegateCOMStub)); }
bool IsSignatureNeedsRestore() { LIMITED_METHOD_CONTRACT; _ASSERTE(IsILStub()); return (0 != (m_dwExtendedFlags & nomdSignatureNeedsRestore)); }
bool IsStubNeedsCOMStarted() { LIMITED_METHOD_CONTRACT; _ASSERTE(IsILStub()); return (0 != (m_dwExtendedFlags & nomdStubNeedsCOMStarted)); }
+ bool IsStructMarshalStub() { LIMITED_METHOD_CONTRACT; _ASSERTE(IsILStub()); return (0 != (m_dwExtendedFlags & nomdStructMarshalStub)); }
#ifdef FEATURE_MULTICASTSTUB_AS_IL
bool IsMulticastStub() {
LIMITED_METHOD_DAC_CONTRACT;
return ClassifyEightBytesWithManagedLayout(helperPtr, nestingLevel, startOffsetOfStruct, useNativeLayout);
}
- const FieldMarshaler *pFieldMarshalers = GetLayoutInfo()->GetFieldMarshalers();
+ const NativeFieldDescriptor *pNativeFieldDescs = GetLayoutInfo()->GetNativeFieldDescriptors();
UINT numIntroducedFields = GetLayoutInfo()->GetNumCTMFields();
// No fields.
// instead of adding additional padding at the end of a one-field structure.
// We do this check here to save looking up the FixedBufferAttribute when loading the field
// from metadata.
- CorElementType firstFieldElementType = pFieldMarshalers->GetFieldDesc()->GetFieldType();
+ CorElementType firstFieldElementType = pNativeFieldDescs->GetFieldDesc()->GetFieldType();
bool isFixedBuffer = numIntroducedFields == 1
&& ( CorTypeInfo::IsPrimitiveType_NoThrow(firstFieldElementType)
|| firstFieldElementType == ELEMENT_TYPE_VALUETYPE)
- && (pFieldMarshalers->GetExternalOffset() == 0)
+ && (pNativeFieldDescs->GetExternalOffset() == 0)
&& IsValueType()
- && (GetLayoutInfo()->GetNativeSize() % pFieldMarshalers->NativeSize() == 0);
+ && (GetLayoutInfo()->GetNativeSize() % pNativeFieldDescs->NativeSize() == 0);
if (isFixedBuffer)
{
- numIntroducedFields = GetNativeSize() / pFieldMarshalers->NativeSize();
+ numIntroducedFields = GetNativeSize() / pNativeFieldDescs->NativeSize();
}
// The SIMD Intrinsic types are meant to be handled specially and should not be passed as struct registers
for (unsigned int fieldIndex = 0; fieldIndex < numIntroducedFields; fieldIndex++)
{
- const FieldMarshaler* pFieldMarshaler;
+ const NativeFieldDescriptor* pNFD;
if (isFixedBuffer)
{
// Reuse the first field marshaler for all fields if a fixed buffer.
- pFieldMarshaler = pFieldMarshalers;
+ pNFD = pNativeFieldDescs;
}
else
{
- pFieldMarshaler = (FieldMarshaler*)(((BYTE*)pFieldMarshalers) + MAXFIELDMARSHALERSIZE * fieldIndex);
+ pNFD = &pNativeFieldDescs[fieldIndex];
}
- FieldDesc *pField = pFieldMarshaler->GetFieldDesc();
+ FieldDesc *pField = pNFD->GetFieldDesc();
CorElementType fieldType = pField->GetFieldType();
// Invalid field type.
return false;
}
- unsigned int fieldNativeSize = pFieldMarshaler->NativeSize();
- DWORD fieldOffset = pFieldMarshaler->GetExternalOffset();
+ unsigned int fieldNativeSize = pNFD->NativeSize();
+ DWORD fieldOffset = pNFD->GetExternalOffset();
if (isFixedBuffer)
{
- // Since we reuse the FieldMarshaler for fixed buffers, we need to adjust the offset.
+ // Since we reuse the NativeFieldDescriptor for fixed buffers, we need to adjust the offset.
fieldOffset += fieldIndex * fieldNativeSize;
}
pField->GetName_NoThrow(&fieldName);
#endif // _DEBUG
- NativeFieldFlags nfc = pFieldMarshaler->GetNativeFieldFlags();
+ NativeFieldFlags nfc = pNFD->GetNativeFieldFlags();
#ifdef FEATURE_COMINTEROP
if (nfc & NATIVE_FIELD_SUBCATEGORY_COM_ONLY)
#endif // FEATURE_COMINTEROP
if (nfc & NATIVE_FIELD_SUBCATEGORY_NESTED)
{
- FieldMarshaler_NestedType* pNestedMarshaler = (FieldMarshaler_NestedType*)pFieldMarshaler;
- unsigned int numElements = pNestedMarshaler->GetNumElements();
+ unsigned int numElements = pNFD->GetNumElements();
unsigned int nestedElementOffset = normalizedFieldOffset;
- MethodTable* pFieldMT = pNestedMarshaler->GetNestedNativeMethodTable();
+ MethodTable* pFieldMT = pNFD->GetNestedNativeMethodTable();
if (pFieldMT == nullptr)
{
UNREACHABLE_MSG("Invalid native field subcategory.");
}
- if ((normalizedFieldOffset % pFieldMarshaler->AlignmentRequirement()) != 0)
+ if ((normalizedFieldOffset % pNFD->AlignmentRequirement()) != 0)
{
// The spec requires that struct values on the stack from register passed fields expects
// those fields to be at their natural alignment.
LOG((LF_JIT, LL_EVERYTHING, " %*sxxxx Native Field %d %s: offset %d (normalized %d), required alignment %d not at natural alignment; not enregistering struct\n",
- nestingLevel * 5, "", fieldIndex, fieldName, fieldOffset, normalizedFieldOffset, pFieldMarshaler->AlignmentRequirement()));
+ nestingLevel * 5, "", fieldIndex, fieldName, fieldOffset, normalizedFieldOffset, pNFD->AlignmentRequirement()));
return false;
}
// Fully load the types of fields associated with a field marshaler when ngenning
if (HasLayout() && GetAppDomain()->IsCompilationDomain() && !IsZapped())
{
- FieldMarshaler* pFM = this->GetLayoutInfo()->GetFieldMarshalers();
- UINT numReferenceFields = this->GetLayoutInfo()->GetNumCTMFields();
+ NativeFieldDescriptor* pNativeFieldDescriptors = this->GetLayoutInfo()->GetNativeFieldDescriptors();
+ UINT numReferenceFields = this->GetLayoutInfo()->GetNumCTMFields();
- while (numReferenceFields--)
+ for (UINT i = 0; i < numReferenceFields; ++i)
{
-
+ NativeFieldDescriptor* pFM = &pNativeFieldDescriptors[i];
FieldDesc *pMarshalerField = pFM->GetFieldDesc();
// If the fielddesc pointer here is a token tagged pointer, then the field marshaler that we are
th.DoFullyLoad(&locals.newVisited, level, pPending, &locals.fBailed, pInstContext);
}
- // The accessibility check is not used here to prevent functional differences between ngen and non-ngen scenarios.
- ((BYTE*&)pFM) += MAXFIELDMARSHALERSIZE;
}
}
#endif //FEATURE_NATIVE_IMAGE_GENERATION
DWORD i;
IMDInternalImport * pInternalImport = GetMDImport(); // to avoid multiple dereferencings
- FieldMarshaler * pNextFieldMarshaler = NULL;
+ NativeFieldDescriptor * pNextNativeFieldDescriptor = NULL;
if (HasLayout())
{
- pNextFieldMarshaler = (FieldMarshaler*)(GetLayoutInfo()->GetFieldMarshalers());
+ pNextNativeFieldDescriptor = GetLayoutInfo()->GetNativeFieldDescriptors();
}
{
pLayoutFieldInfo = pwalk;
- const FieldMarshaler *pSrcFieldMarshaler = (const FieldMarshaler *) &pwalk->m_FieldMarshaler;
+ const NativeFieldDescriptor *pSrcFieldDescriptor = &pwalk->m_nfd;
- pSrcFieldMarshaler->CopyTo(pNextFieldMarshaler, MAXFIELDMARSHALERSIZE);
+ *pNextNativeFieldDescriptor = *pSrcFieldDescriptor;
- pNextFieldMarshaler->SetFieldDesc(pFD);
- pNextFieldMarshaler->SetExternalOffset(pwalk->m_nativePlacement.m_offset);
+ pNextNativeFieldDescriptor->SetFieldDesc(pFD);
+ pNextNativeFieldDescriptor->SetExternalOffset(pwalk->m_nativePlacement.m_offset);
- ((BYTE*&)pNextFieldMarshaler) += MAXFIELDMARSHALERSIZE;
+ pNextNativeFieldDescriptor++;
break;
}
pwalk++;
PCCOR_SIGNATURE pvNativeType;
ULONG cbNativeType;
- if (token == mdParamDefNil || pScope->GetFieldMarshal(token, &pvNativeType, &cbNativeType) != S_OK)
+ if (token == mdParamDefNil || token == mdFieldDefNil || pScope->GetFieldMarshal(token, &pvNativeType, &cbNativeType) != S_OK)
return TRUE;
return ParseNativeTypeInfo(pParamInfo, pvNativeType, cbNativeType);
COMPlusThrow(kMarshalDirectiveException, IDS_EE_BADMARSHAL_ERROR_MSG, paramString.GetUnicode(), errorString.GetUnicode());
}
+#ifdef _DEBUG
+BOOL IsFixedBuffer(mdFieldDef field, IMDInternalImport* pInternalImport)
+{
+ HRESULT hr = pInternalImport->GetCustomAttributeByName(field, g_FixedBufferAttribute, NULL, NULL);
+
+ return hr == S_OK ? TRUE : FALSE;
+}
+#endif
+
+
//===============================================================
// Collects paraminfo's in an indexed array so that:
//
BOOL fEmitsIL,
BOOL onInstanceMethod,
MethodDesc* pMD,
- BOOL fLoadCustomMarshal
+ BOOL fLoadCustomMarshal,
+ BOOL fCalculatingFieldMetadata
#ifdef _DEBUG
,
LPCUTF8 pDebugName,
m_BestFit = BestFit;
m_ThrowOnUnmappableChar = ThrowOnUnmappableChar;
m_ms = ms;
- m_fAnsi = (ms == MARSHAL_SCENARIO_NDIRECT) && (nlType == nltAnsi);
- m_managedArgSize = 0;
+ m_fAnsi = (ms == MARSHAL_SCENARIO_NDIRECT || ms == MARSHAL_SCENARIO_FIELD) && (nlType == nltAnsi);
m_nativeArgSize = 0;
m_pCMHelper = NULL;
m_CMVt = VT_EMPTY;
m_args.m_pMarshalInfo = this;
m_args.m_pMT = NULL;
m_pModule = pModule;
+ m_token = token;
CorElementType mtype = ELEMENT_TYPE_END;
CorElementType corElemType = ELEMENT_TYPE_END;
m_pMT = NULL;
}
#endif // FEATURE_COMINTEROP
- SigPointer sigtmp = sig;
- IfFailGoto(sigtmp.GetElemType(NULL), lFail);
-
- // Peek closed elem type here to prevent ELEMENT_TYPE_VALUETYPE turning into a primitive.
- CorElementType mtype2 = sigtmp.PeekElemTypeClosed(pModule, pTypeContext);
-
- if (mtype2 == ELEMENT_TYPE_VALUETYPE)
+ if (!fCalculatingFieldMetadata) // When calculating field metadata, we don't need to check the subtype of the pointer.
{
+ SigPointer sigtmp = sig;
+ IfFailGoto(sigtmp.GetElemType(NULL), lFail);
- TypeHandle th = sigtmp.GetTypeHandleThrowing(pModule, pTypeContext);
- _ASSERTE(!th.IsNull());
+ // Peek closed elem type here to prevent ELEMENT_TYPE_VALUETYPE turning into a primitive.
+ CorElementType mtype2 = sigtmp.PeekElemTypeClosed(pModule, pTypeContext);
- // We want to leave out enums as they surely don't have copy constructors
- // plus they are not marked as blittable.
- if (!th.IsEnum())
+ if (mtype2 == ELEMENT_TYPE_VALUETYPE)
{
- // It should be blittable
- if (!th.IsBlittable())
- {
- m_resID = IDS_EE_BADMARSHAL_PTRNONBLITTABLE;
- IfFailGoto(E_FAIL, lFail);
- }
+ TypeHandle th = sigtmp.GetTypeHandleThrowing(pModule, pTypeContext);
+ _ASSERTE(!th.IsNull());
- // Check for Copy Constructor Modifier
- if (sigtmp.HasCustomModifier(pModule, "Microsoft.VisualC.NeedsCopyConstructorModifier", ELEMENT_TYPE_CMOD_REQD) ||
- sigtmp.HasCustomModifier(pModule, "System.Runtime.CompilerServices.IsCopyConstructed", ELEMENT_TYPE_CMOD_REQD) )
+ // We want to leave out enums as they surely don't have copy constructors
+ // plus they are not marked as blittable.
+ if (!th.IsEnum())
{
- mtype = mtype2;
+ // It should be blittable
+ if (!th.IsBlittable())
+ {
+ m_resID = IDS_EE_BADMARSHAL_PTRNONBLITTABLE;
+ IfFailGoto(E_FAIL, lFail);
+ }
- // Keep the sig pointer in sync with mtype (skip ELEMENT_TYPE_PTR) because for the rest
- // of this method we are pretending that the parameter is a value type passed by-value.
- IfFailGoto(sig.GetElemType(NULL), lFail);
+ // Check for Copy Constructor Modifier
+ if (sigtmp.HasCustomModifier(pModule, "Microsoft.VisualC.NeedsCopyConstructorModifier", ELEMENT_TYPE_CMOD_REQD) ||
+ sigtmp.HasCustomModifier(pModule, "System.Runtime.CompilerServices.IsCopyConstructed", ELEMENT_TYPE_CMOD_REQD) )
+ {
+ mtype = mtype2;
+
+ // Keep the sig pointer in sync with mtype (skip ELEMENT_TYPE_PTR) because for the rest
+ // of this method we are pretending that the parameter is a value type passed by-value.
+ IfFailGoto(sig.GetElemType(NULL), lFail);
- fNeedsCopyCtor = TRUE;
- m_byref = FALSE;
+ fNeedsCopyCtor = TRUE;
+ m_byref = FALSE;
+ }
}
}
- }
- else
- {
- if (!(mtype2 != ELEMENT_TYPE_CLASS &&
- mtype2 != ELEMENT_TYPE_STRING &&
- mtype2 != ELEMENT_TYPE_OBJECT &&
- mtype2 != ELEMENT_TYPE_SZARRAY))
+ else
{
- m_resID = IDS_EE_BADMARSHAL_PTRSUBTYPE;
- IfFailGoto(E_FAIL, lFail);
+ if (!(mtype2 != ELEMENT_TYPE_CLASS &&
+ mtype2 != ELEMENT_TYPE_STRING &&
+ mtype2 != ELEMENT_TYPE_OBJECT &&
+ mtype2 != ELEMENT_TYPE_SZARRAY))
+ {
+ m_resID = IDS_EE_BADMARSHAL_PTRSUBTYPE;
+ IfFailGoto(E_FAIL, lFail);
+ }
}
}
}
-
// System primitive types (System.Int32, et.al.) will be marshaled as expected
// because the mtype CorElementType is normalized (e.g. ELEMENT_TYPE_I4).
#ifdef _TARGET_X86_
if (nativeType == NATIVE_TYPE_CUSTOMMARSHALER)
{
+ if (IsFieldScenario())
+ {
+ m_resID = IDS_EE_BADMARSHALFIELD_NOCUSTOMMARSH;
+ IfFailGoto(E_FAIL, lFail);
+ }
+
switch (mtype)
{
case ELEMENT_TYPE_VAR:
// 2-byte COM VARIANT_BOOL
m_type = MARSHAL_TYPE_VTBOOL;
}
- else if (m_ms == MARSHAL_SCENARIO_WINRT)
+ else if (IsWinRTScenario())
{
// 1-byte WinRT bool
m_type = MARSHAL_TYPE_CBOOL;
#endif // FEATURE_COMINTEROP
{
// 4-byte Windows BOOL
- _ASSERTE(m_ms == MARSHAL_SCENARIO_NDIRECT);
+ _ASSERTE(m_ms == MARSHAL_SCENARIO_NDIRECT || m_ms == MARSHAL_SCENARIO_FIELD);
m_type = MARSHAL_TYPE_WINBOOL;
}
break;
break;
case NATIVE_TYPE_DEFAULT:
- m_type = ( (m_ms == MARSHAL_SCENARIO_NDIRECT && m_fAnsi) ? MARSHAL_TYPE_ANSICHAR : MARSHAL_TYPE_GENERIC_U2 );
+ m_type = ( ((m_ms == MARSHAL_SCENARIO_NDIRECT || m_ms == MARSHAL_SCENARIO_FIELD) && m_fAnsi) ? MARSHAL_TYPE_ANSICHAR : MARSHAL_TYPE_GENERIC_U2 );
break;
default:
case NATIVE_TYPE_DEFAULT:
break;
-#ifdef FEATURE_COMINTEROP
case NATIVE_TYPE_ERROR:
+#ifdef FEATURE_COMINTEROP
m_fErrorNativeType = TRUE;
- break;
#endif // FEATURE_COMINTEROP
+ break;
default:
m_resID = IDS_EE_BADMARSHAL_I4;
case NATIVE_TYPE_DEFAULT:
break;
-#ifdef FEATURE_COMINTEROP
case NATIVE_TYPE_ERROR:
+#ifdef FEATURE_COMINTEROP
m_fErrorNativeType = TRUE;
- break;
#endif // FEATURE_COMINTEROP
+ break;
default:
m_resID = IDS_EE_BADMARSHAL_I4;
IfFailGoto(E_FAIL, lFail);
}
- m_type = MARSHAL_TYPE_GENERIC_4;
+ m_type = MARSHAL_TYPE_GENERIC_U4;
break;
case ELEMENT_TYPE_I8:
m_resID = IDS_EE_BADMARSHAL_I;
IfFailGoto(E_FAIL, lFail);
}
- m_type = (sizeof(LPVOID) == 4 ? MARSHAL_TYPE_GENERIC_4 : MARSHAL_TYPE_GENERIC_8);
+#ifdef _TARGET_64BIT_
+ m_type = MARSHAL_TYPE_GENERIC_8;
+#else
+ m_type = MARSHAL_TYPE_GENERIC_4;
+#endif
break;
case ELEMENT_TYPE_U:
m_resID = IDS_EE_BADMARSHAL_I;
IfFailGoto(E_FAIL, lFail);
}
- m_type = (sizeof(LPVOID) == 4 ? MARSHAL_TYPE_GENERIC_4 : MARSHAL_TYPE_GENERIC_8);
+#ifdef _TARGET_64BIT_
+ m_type = MARSHAL_TYPE_GENERIC_8;
+#else
+ m_type = MARSHAL_TYPE_GENERIC_4;
+#endif
break;
m_resID = IDS_EE_BADMARSHAL_PTR;
IfFailGoto(E_FAIL, lFail);
}
- m_type = ( (sizeof(void*)==4) ? MARSHAL_TYPE_GENERIC_4 : MARSHAL_TYPE_GENERIC_8 );
+#ifdef _TARGET_64BIT_
+ m_type = MARSHAL_TYPE_GENERIC_8;
+#else
+ m_type = MARSHAL_TYPE_GENERIC_4;
+#endif
break;
case ELEMENT_TYPE_FNPTR:
m_resID = IDS_EE_BADMARSHAL_FNPTR;
IfFailGoto(E_FAIL, lFail);
}
- m_type = ( (sizeof(void*)==4) ? MARSHAL_TYPE_GENERIC_4 : MARSHAL_TYPE_GENERIC_8 );
+#ifdef _TARGET_64BIT_
+ m_type = MARSHAL_TYPE_GENERIC_8;
+#else
+ m_type = MARSHAL_TYPE_GENERIC_4;
+#endif
break;
case ELEMENT_TYPE_OBJECT:
case ELEMENT_TYPE_STRING:
case ELEMENT_TYPE_CLASS:
case ELEMENT_TYPE_VAR:
- {
- TypeHandle sigTH = sig.GetTypeHandleThrowing(pModule, pTypeContext);
+ {
+ TypeHandle sigTH = sig.GetTypeHandleThrowing(
+ pModule,
+ pTypeContext,
+ ClassLoader::LoadTypes,
+ fCalculatingFieldMetadata ? CLASS_LOAD_APPROXPARENTS : CLASS_LOADED,
+ fCalculatingFieldMetadata ? TRUE : FALSE);
// Disallow marshaling generic types except for WinRT interfaces.
if (sigTH.HasInstantiation())
// whatever...
if (sig.IsStringType(pModule, pTypeContext))
{
- m_resID = IDS_EE_BADMARSHALPARAM_STRING;
+ m_resID = IsFieldScenario() ? IDS_EE_BADMARSHALFIELD_STRING : IDS_EE_BADMARSHALPARAM_STRING;
IfFailGoto(E_FAIL, lFail);
}
if (COMDelegate::IsDelegate(m_pMT))
{
- if (m_ms == MARSHAL_SCENARIO_WINRT)
+ if (IsWinRTScenario())
{
// In WinRT scenarios delegates must be WinRT delegates
if (!m_pMT->IsProjectedFromWinRT() && !WinRTTypeNameConverter::IsRedirectedType(m_pMT))
|| sig.IsClassThrowing(pModule, g_StringBufferClassName, pTypeContext)
)
{
+ if (builder && m_ms == MARSHAL_SCENARIO_FIELD)
+ {
+ m_resID = IDS_EE_BADMARSHALFIELD_NOSTRINGBUILDER;
+ IfFailGoto(E_FAIL, lFail);
+ }
+
switch ( nativeType )
{
case NATIVE_TYPE_LPWSTR:
case NATIVE_TYPE_LPTSTR:
{
#ifdef FEATURE_COMINTEROP
- if (m_ms != MARSHAL_SCENARIO_NDIRECT)
+ if (m_ms != MARSHAL_SCENARIO_NDIRECT && m_ms != MARSHAL_SCENARIO_FIELD)
{
_ASSERTE(m_ms == MARSHAL_SCENARIO_COMINTEROP);
// We disallow NATIVE_TYPE_LPTSTR for COM.
m_type = MARSHAL_TYPE_HSTRING;
break;
}
-#endif // FEATURE_COMINTEROP
+#endif // FEATURE_COMINTEROP
+ case NATIVE_TYPE_FIXEDSYSSTRING:
+ {
+ if (m_ms == MARSHAL_SCENARIO_FIELD)
+ {
+ if (ParamInfo.m_Additive == 0)
+ {
+ m_resID = IDS_EE_BADMARSHALFIELD_ZEROLENGTHFIXEDSTRING;
+ IfFailGoto(E_FAIL, lFail);
+ }
+
+ m_args.fs.fixedStringLength = ParamInfo.m_Additive;
+
+ m_type = m_fAnsi ? MARSHAL_TYPE_FIXED_CSTR : MARSHAL_TYPE_FIXED_WSTR;
+ }
+ break;
+ }
case NATIVE_TYPE_DEFAULT:
{
#ifdef FEATURE_COMINTEROP
- if (m_ms == MARSHAL_SCENARIO_WINRT)
+ if (IsWinRTScenario())
{
if (builder)
{
m_type = MARSHAL_TYPE_HSTRING;
}
- else if (m_ms != MARSHAL_SCENARIO_NDIRECT)
+ else if (m_ms == MARSHAL_SCENARIO_COMINTEROP)
{
- _ASSERTE(m_ms == MARSHAL_SCENARIO_COMINTEROP);
m_type = builder ? MARSHAL_TYPE_LPWSTR_BUFFER : MARSHAL_TYPE_BSTR;
}
else
}
default:
- m_resID = builder ? IDS_EE_BADMARSHALPARAM_STRINGBUILDER : IDS_EE_BADMARSHALPARAM_STRING;
+ if (IsFieldScenario())
+ {
+ m_resID = IDS_EE_BADMARSHALFIELD_STRING;
+ }
+ else if (builder)
+ {
+ m_resID = IDS_EE_BADMARSHALPARAM_STRINGBUILDER;
+ }
+ else
+ {
+ m_resID = IDS_EE_BADMARSHALPARAM_STRING;
+ }
+
IfFailGoto(E_FAIL, lFail);
break;
}
}
#ifdef FEATURE_COMINTEROP
else if (sig.IsClassThrowing(pModule, g_CollectionsEnumeratorClassName, pTypeContext) &&
- nativeType == NATIVE_TYPE_DEFAULT)
+ nativeType == NATIVE_TYPE_DEFAULT &&
+ !IsFieldScenario())
{
m_CMVt = VT_UNKNOWN;
m_type = MARSHAL_TYPE_REFERENCECUSTOMMARSHALER;
}
m_type = MARSHAL_TYPE_INTERFACE;
- if (m_ms == MARSHAL_SCENARIO_WINRT)
+ if (IsWinRTScenario())
{
// all interfaces marshaled in WinRT scenarios are IInspectable-based
m_fInspItf = TRUE;
}
}
// Check for Windows.Foundation.HResult <-> Exception
- else if (m_ms == MARSHAL_SCENARIO_WINRT && MscorlibBinder::IsClass(m_pMT, CLASS__EXCEPTION))
+ else if (IsWinRTScenario() && MscorlibBinder::IsClass(m_pMT, CLASS__EXCEPTION))
{
m_args.m_pMT = m_pMT;
m_type = MARSHAL_TYPE_EXCEPTION;
{
m_args.m_pMT = m_pMT;
#ifdef FEATURE_COMINTEROP
- if (m_ms == MARSHAL_SCENARIO_WINRT)
+ if (IsWinRTScenario())
{
// Delegates must be imported from WinRT and marshaled as Interface
if (!m_pMT->IsProjectedFromWinRT() && !WinRTTypeNameConverter::IsRedirectedType(m_pMT))
case NATIVE_TYPE_DEFAULT:
#ifdef FEATURE_COMINTEROP
- if (m_ms == MARSHAL_SCENARIO_WINRT || m_pMT->IsProjectedFromWinRT() || WinRTTypeNameConverter::IsRedirectedType(m_pMT))
+ if (IsWinRTScenario() || m_pMT->IsProjectedFromWinRT() || WinRTTypeNameConverter::IsRedirectedType(m_pMT))
{
m_type = MARSHAL_TYPE_INTERFACE;
}
}
else if (m_pMT->IsBlittable())
{
- if (!(nativeType == NATIVE_TYPE_DEFAULT || nativeType == NATIVE_TYPE_LPSTRUCT))
+ if (!(nativeType == NATIVE_TYPE_DEFAULT || nativeType == (IsFieldScenario() ? NATIVE_TYPE_STRUCT : NATIVE_TYPE_LPSTRUCT)))
{
- m_resID = IDS_EE_BADMARSHAL_CLASS;
+ m_resID = IsFieldScenario() ? IDS_EE_BADMARSHALFIELD_LAYOUTCLASS : IDS_EE_BADMARSHAL_CLASS;
IfFailGoto(E_FAIL, lFail);
}
- m_type = MARSHAL_TYPE_BLITTABLEPTR;
+ m_type = IsFieldScenario() ? MARSHAL_TYPE_BLITTABLE_LAYOUTCLASS : MARSHAL_TYPE_BLITTABLEPTR;
m_args.m_pMT = m_pMT;
}
else if (m_pMT->HasLayout())
{
- if (!(nativeType == NATIVE_TYPE_DEFAULT || nativeType == NATIVE_TYPE_LPSTRUCT))
+ if (!(nativeType == NATIVE_TYPE_DEFAULT || nativeType == (IsFieldScenario() ? NATIVE_TYPE_STRUCT : NATIVE_TYPE_LPSTRUCT)))
{
- m_resID = IDS_EE_BADMARSHAL_CLASS;
+ m_resID = IsFieldScenario() ? IDS_EE_BADMARSHALFIELD_LAYOUTCLASS : IDS_EE_BADMARSHAL_CLASS;
IfFailGoto(E_FAIL, lFail);
}
- m_type = MARSHAL_TYPE_LAYOUTCLASSPTR;
+ m_type = IsFieldScenario() ? MARSHAL_TYPE_LAYOUTCLASS : MARSHAL_TYPE_LAYOUTCLASSPTR;
m_args.m_pMT = m_pMT;
}
#ifdef FEATURE_COMINTEROP
- else if (m_ms == MARSHAL_SCENARIO_WINRT && sig.IsClassThrowing(pModule, g_SystemUriClassName, pTypeContext))
+ else if (IsWinRTScenario() && !IsFieldScenario() && sig.IsClassThrowing(pModule, g_SystemUriClassName, pTypeContext))
{
m_type = MARSHAL_TYPE_URI;
}
- else if (m_ms == MARSHAL_SCENARIO_WINRT && sig.IsClassThrowing(pModule, g_NotifyCollectionChangedEventArgsName, pTypeContext))
+ else if (IsWinRTScenario() && !IsFieldScenario() && sig.IsClassThrowing(pModule, g_NotifyCollectionChangedEventArgsName, pTypeContext))
{
m_type = MARSHAL_TYPE_NCCEVENTARGS;
}
- else if (m_ms == MARSHAL_SCENARIO_WINRT && sig.IsClassThrowing(pModule, g_PropertyChangedEventArgsName, pTypeContext))
+ else if (IsWinRTScenario() && !IsFieldScenario() && sig.IsClassThrowing(pModule, g_PropertyChangedEventArgsName, pTypeContext))
{
m_type = MARSHAL_TYPE_PCEVENTARGS;
}
{
#ifdef FEATURE_COMINTEROP
case NATIVE_TYPE_DEFAULT:
- if (ms == MARSHAL_SCENARIO_WINRT)
+ if (IsWinRTScenario())
{
m_fInspItf = TRUE;
m_type = MARSHAL_TYPE_INTERFACE;
break;
}
+ else if (ms == MARSHAL_SCENARIO_FIELD)
+ {
+ m_type = MARSHAL_TYPE_INTERFACE;
+ break;
+ }
// fall through
case NATIVE_TYPE_STRUCT:
m_type = MARSHAL_TYPE_OBJECT;
break;
default:
- m_resID = IDS_EE_BADMARSHAL_OBJECT;
+ m_resID = IsFieldScenario() ? IDS_EE_BADMARSHALFIELD_OBJECT : IDS_EE_BADMARSHAL_OBJECT;
IfFailGoto(E_FAIL, lFail);
}
}
ParamInfo.m_SafeArrayElementVT = VT_VARIANT;
}
- IfFailGoto(HandleArrayElemType(&ParamInfo, thElement, -1, FALSE, isParam, pAssembly), lFail);
+ IfFailGoto(HandleArrayElemType(&ParamInfo, thElement, -1, FALSE, isParam, pAssembly, TRUE), lFail);
break;
}
_ASSERTE(!"This invalid signature should never be hit!");
IfFailGoto(E_FAIL, lFail);
}
- else if ((m_ms == MARSHAL_SCENARIO_WINRT) && sig.IsClassThrowing(pModule, g_TypeClassName, pTypeContext))
+ else if ((IsWinRTScenario()) && sig.IsClassThrowing(pModule, g_TypeClassName, pTypeContext))
{
m_type = MARSHAL_TYPE_SYSTEMTYPE;
}
break;
case NATIVE_TYPE_LPSTRUCT:
+ if (IsFieldScenario())
+ {
+ m_resID = IDS_EE_BADMARSHALFIELD_DECIMAL;
+ IfFailGoto(E_FAIL, lFail);
+ }
m_type = MARSHAL_TYPE_DECIMAL_PTR;
break;
break;
default:
- m_resID = IDS_EE_BADMARSHALPARAM_DECIMAL;
+ m_resID = IsFieldScenario() ? IDS_EE_BADMARSHALFIELD_DECIMAL : IDS_EE_BADMARSHALPARAM_DECIMAL;
IfFailGoto(E_FAIL, lFail);
}
}
break;
case NATIVE_TYPE_LPSTRUCT:
+ if (IsFieldScenario())
+ {
+ m_resID = IDS_EE_BADMARSHAL_GUID;
+ IfFailGoto(E_FAIL, lFail);
+ }
m_type = MARSHAL_TYPE_GUID_PTR;
break;
}
else if (sig.IsClassThrowing(pModule, "System.Runtime.InteropServices.ArrayWithOffset", pTypeContext))
{
+ if (m_ms == MARSHAL_SCENARIO_FIELD)
+ {
+ IfFailGoto(E_FAIL, lFail);
+ }
if (!(nativeType == NATIVE_TYPE_DEFAULT))
{
IfFailGoto(E_FAIL, lFail);
}
else if (sig.IsClassThrowing(pModule, "System.Runtime.InteropServices.HandleRef", pTypeContext))
{
+ if (m_ms == MARSHAL_SCENARIO_FIELD)
+ {
+ IfFailGoto(E_FAIL, lFail);
+ }
if (!(nativeType == NATIVE_TYPE_DEFAULT))
{
IfFailGoto(E_FAIL, lFail);
}
else if (sig.IsClassThrowing(pModule, "System.ArgIterator", pTypeContext))
{
+ if (m_ms == MARSHAL_SCENARIO_FIELD)
+ {
+ IfFailGoto(E_FAIL, lFail);
+ }
if (!(nativeType == NATIVE_TYPE_DEFAULT))
{
IfFailGoto(E_FAIL, lFail);
#endif // FEATURE_COMINTEROP
else if (sig.IsClassThrowing(pModule, g_RuntimeTypeHandleClassName, pTypeContext))
{
- if (nativeType != NATIVE_TYPE_DEFAULT)
+ if (nativeType != NATIVE_TYPE_DEFAULT || IsFieldScenario())
{
IfFailGoto(E_FAIL, lFail);
}
}
else if (sig.IsClassThrowing(pModule, g_RuntimeFieldHandleClassName, pTypeContext))
{
- if (nativeType != NATIVE_TYPE_DEFAULT)
+ if (nativeType != NATIVE_TYPE_DEFAULT || IsFieldScenario())
{
IfFailGoto(E_FAIL, lFail);
}
}
else if (sig.IsClassThrowing(pModule, g_RuntimeMethodHandleClassName, pTypeContext))
{
- if (nativeType != NATIVE_TYPE_DEFAULT)
+ if (nativeType != NATIVE_TYPE_DEFAULT || IsFieldScenario())
{
IfFailGoto(E_FAIL, lFail);
}
}
else
{
- m_pMT = sig.GetTypeHandleThrowing(pModule, pTypeContext).GetMethodTable();
+ m_pMT = sig.GetTypeHandleThrowing(
+ pModule,
+ pTypeContext,
+ ClassLoader::LoadTypes,
+ fCalculatingFieldMetadata ? CLASS_LOAD_APPROXPARENTS : CLASS_LOADED,
+ fCalculatingFieldMetadata ? TRUE : FALSE).GetMethodTable();
if (m_pMT == NULL)
break;
#ifdef FEATURE_COMINTEROP
// Handle Nullable<T> and KeyValuePair<K, V> for WinRT
- if (m_ms == MARSHAL_SCENARIO_WINRT)
+ if (IsWinRTScenario())
{
if (m_pMT->HasSameTypeDefAs(g_pNullableClass))
{
if (m_pMT->HasSameTypeDefAs(MscorlibBinder::GetClass(CLASS__KEYVALUEPAIRGENERIC)))
{
+ if (IsFieldScenario())
+ {
+ m_resID = IDS_EE_BADMARSHAL_WINRT_ILLEGAL_TYPE;
+ IfFailGoto(E_FAIL, lFail);
+ }
m_type = MARSHAL_TYPE_KEYVALUEPAIR;
m_args.m_pMT = m_pMT;
break;
IfFailGoto(E_FAIL, lFail);
}
- if (m_byref && !isParam)
+ if (m_byref && !isParam && !IsFieldScenario())
{
// Override the prohibition on byref returns so that IJW works
m_byref = FALSE;
}
else
{
- if (fNeedsCopyCtor)
+ if (fNeedsCopyCtor && !IsFieldScenario()) // We don't support automatically discovering copy constructors for fields.
{
#ifdef FEATURE_COMINTEROP
- if (m_ms == MARSHAL_SCENARIO_WINRT)
+ if (IsWinRTScenario())
{
// our WinRT-optimized GetCOMIPFromRCW helpers don't support copy
// constructor stubs so make sure that this marshaler will not be used
&& CorIsPrimitiveType(m_pMT->GetInternalCorElementType())
&& !IsUnmanagedValueTypeReturnedByRef(nativeSize)
&& managedSize <= sizeof(void*)
- && nativeSize <= sizeof(void*))
+ && nativeSize <= sizeof(void*)
+ && !IsFieldScenario())
{
m_type = MARSHAL_TYPE_GENERIC_4;
m_args.m_pMT = m_pMT;
m_resID = IDS_EE_BADMARSHAL_VALUETYPE;
IfFailGoto(E_FAIL, lFail);
}
-
+#ifdef _DEBUG
+ if (ms == MARSHAL_SCENARIO_FIELD && fEmitsIL)
+ {
+ _ASSERTE_MSG(!IsFixedBuffer(token, pModule->GetMDImport()), "Cannot correctly marshal fixed buffers of non-blittable types");
+ }
+#endif
m_args.m_pMT = m_pMT;
m_type = MARSHAL_TYPE_VALUECLASS;
}
case ELEMENT_TYPE_ARRAY:
{
// Get class info from array.
- TypeHandle arrayTypeHnd = sig.GetTypeHandleThrowing(pModule, pTypeContext);
+ TypeHandle arrayTypeHnd = sig.GetTypeHandleThrowing(
+ pModule,
+ pTypeContext,
+ ClassLoader::LoadTypes,
+ fCalculatingFieldMetadata ? CLASS_LOAD_APPROXPARENTS : CLASS_LOADED,
+ fCalculatingFieldMetadata ? TRUE : FALSE);
_ASSERTE(!arrayTypeHnd.IsNull());
ArrayTypeDesc* asArray = arrayTypeHnd.AsArray();
#ifdef FEATURE_COMINTEROP
// If this is not forward COM interop, throw the exception right away. We rely on this
// for example in code:ComPreStubWorker when we fire the InvalidMemberDeclaration MDA.
- if ((m_ms == MARSHAL_SCENARIO_COMINTEROP || m_ms == MARSHAL_SCENARIO_WINRT) && fMngToNative)
+ if ((m_ms == MARSHAL_SCENARIO_COMINTEROP || IsWinRTScenario()) && fMngToNative && !IsFieldScenario())
{
psl->SetInteropParamExceptionInfo(resID, paramIdx);
return;
ThrowInteropParamException(resID, paramIdx);
}
+void MarshalInfo::ThrowTypeLoadExceptionForInvalidFieldMarshal(FieldDesc* pFieldDesc, UINT resID)
+{
+ DefineFullyQualifiedNameForClassW();
+
+ StackSString ssFieldName(SString::Utf8, pFieldDesc->GetName());
+
+ StackSString errorString(W("Unknown error."));
+ errorString.LoadResource(CCompRC::Error, resID);
+
+ COMPlusThrow(kTypeLoadException, IDS_EE_BADMARSHALFIELD_ERROR_MSG,
+ GetFullyQualifiedNameForClassW(pFieldDesc->GetEnclosingMethodTable()),
+ ssFieldName.GetUnicode(), errorString.GetUnicode());
+}
+
-HRESULT MarshalInfo::HandleArrayElemType(NativeTypeParamInfo *pParamInfo, TypeHandle thElement, int iRank, BOOL fNoLowerBounds, BOOL isParam, Assembly *pAssembly)
+HRESULT MarshalInfo::HandleArrayElemType(NativeTypeParamInfo *pParamInfo, TypeHandle thElement, int iRank, BOOL fNoLowerBounds, BOOL isParam, Assembly *pAssembly, BOOL isArrayClass /* = FALSE */)
{
CONTRACTL
{
//
#ifdef FEATURE_COMINTEROP
- if (m_ms == MARSHAL_SCENARIO_WINRT)
+ if (IsWinRTScenario())
{
m_type = MARSHAL_TYPE_HIDDENLENGTHARRAY;
}
}
else if (pParamInfo->m_NativeType == NATIVE_TYPE_DEFAULT)
{
+ if (m_ms == MARSHAL_SCENARIO_FIELD)
+ {
+#ifdef FEATURE_CLASSIC_COMINTEROP
+ m_type = MARSHAL_TYPE_SAFEARRAY;
+#else
+ m_resID = IDS_EE_BADMARSHALFIELD_ARRAY;
+ return E_FAIL;
+#endif
+ }
+ else
#ifdef FEATURE_COMINTEROP
if (m_ms != MARSHAL_SCENARIO_NDIRECT)
{
m_type = MARSHAL_TYPE_NATIVEARRAY;
}
}
+ else if (pParamInfo->m_NativeType == NATIVE_TYPE_FIXEDARRAY && m_ms == MARSHAL_SCENARIO_FIELD)
+ {
+ m_type = MARSHAL_TYPE_FIXED_ARRAY;
+ }
else
{
- m_resID = IDS_EE_BADMARSHAL_ARRAY;
+ m_resID = IsFieldScenario() ? IDS_EE_BADMARSHALFIELD_ARRAY : IDS_EE_BADMARSHAL_ARRAY;
return E_FAIL;
}
}
else
#endif // FEATURE_COMINTEROP
+ if (m_type == MARSHAL_TYPE_FIXED_ARRAY)
+ {
+ arrayMarshalInfo.InitForFixedArray(thElement, pParamInfo->m_ArrayElementType, m_fAnsi);
+ }
+ else
{
_ASSERTE(m_type == MARSHAL_TYPE_NATIVEARRAY);
arrayMarshalInfo.InitForNativeArray(m_ms, thElement, pParamInfo->m_ArrayElementType, m_fAnsi);
m_hndArrayElemType = arrayMarshalInfo.GetElementTypeHandle();
m_arrayElementType = arrayMarshalInfo.GetElementVT();
- if (m_type == MARSHAL_TYPE_NATIVEARRAY)
+ if (m_type == MARSHAL_TYPE_NATIVEARRAY || m_type == MARSHAL_TYPE_FIXED_ARRAY)
{
// Retrieve the extra information associated with the native array marshaling.
m_args.na.m_vt = m_arrayElementType;
m_countParamIdx = pParamInfo->m_CountParamIdx;
m_multiplier = pParamInfo->m_Multiplier;
m_additive = pParamInfo->m_Additive;
+
+ if (m_type == MARSHAL_TYPE_FIXED_ARRAY)
+ {
+ if (m_additive == 0)
+ {
+ m_resID = IDS_EE_BADMARSHALFIELD_FIXEDARRAY_ZEROSIZE;
+ return E_FAIL;
+ }
+
+ if (isArrayClass == TRUE)
+ {
+ // Compat: FixedArrays of System.Arrays map to fixed arrays of BSTRs.
+ m_arrayElementType = VT_BSTR;
+ m_args.na.m_vt = VT_BSTR;
+ m_hndArrayElemType = g_pStringClass;
+ }
+ }
}
#ifdef FEATURE_COMINTEROP
else if (m_type == MARSHAL_TYPE_HIDDENLENGTHARRAY)
}
void MarshalInfo::GenerateReturnIL(NDirectStubLinker* psl,
- int argOffset,
- BOOL fMngToNative,
- BOOL fieldGetter,
- BOOL retval)
+ int argOffset,
+ BOOL fMngToNative,
+ BOOL fieldGetter,
+ BOOL retval)
{
CONTRACTL
{
PRECONDITION(CheckPointer(psl));
}
CONTRACTL_END;
-
+
MarshalerOverrideStatus amostat;
UINT resID = IDS_EE_BADMARSHAL_RESTRICTION;
else
{
amostat = (GetReturnOverrideProc(m_type)) (psl,
- fMngToNative,
- retval,
- &m_args,
- &resID);
+ fMngToNative,
+ retval,
+ &m_args,
+ &resID);
}
if (amostat == DISALLOWED)
EmitOrThrowInteropParamException(psl, fMngToNative, resID, 0);
return;
}
-
+
if (amostat == HANDLEASNORMAL)
{
// Historically we have always allowed reading fields that are marshaled as C arrays.
EmitOrThrowInteropParamException(psl, fMngToNative, m_resID, 0);
return;
}
-
+
NewHolder<ILMarshaler> pMarshaler = CreateILMarshaler(m_type, psl);
DWORD dwMarshalFlags = CalculateReturnMarshalFlags(retval, fMngToNative);
return;
}
- ILCodeStream* pcsMarshal = psl->GetMarshalCodeStream();
- ILCodeStream* pcsUnmarshal = psl->GetReturnUnmarshalCodeStream();
- ILCodeStream* pcsDispatch = psl->GetDispatchCodeStream();
-
+ ILCodeStream* pcsMarshal = psl->GetMarshalCodeStream();
+ ILCodeStream* pcsUnmarshal = psl->GetReturnUnmarshalCodeStream();
+ ILCodeStream* pcsDispatch = psl->GetDispatchCodeStream();
+
pcsMarshal->EmitNOP("// return { ");
pcsUnmarshal->EmitNOP("// return { ");
-
- UINT16 wNativeSize = GetNativeSize(m_type, m_ms);
+
+ UINT16 wNativeSize = GetNativeSize(m_type);
// The following statement behaviour has existed for a long time. By aligning the size of the return
// value up to stack slot size, we prevent EmitMarshalReturnValue from distinguishing between, say, 3-byte
}
}
-void MarshalInfo::SetupArgumentSizes()
+void MarshalInfo::GenerateFieldIL(NDirectStubLinker* psl,
+ UINT32 managedOffset,
+ UINT32 nativeOffset,
+ FieldDesc* pFieldDesc)
{
CONTRACTL
{
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
+ STANDARD_VM_CHECK;
+ PRECONDITION(CheckPointer(psl));
+ PRECONDITION(IsFieldScenario());
}
CONTRACTL_END;
- if (m_byref)
+ if (m_type == MARSHAL_TYPE_UNKNOWN)
{
- m_managedArgSize = StackElemSize(sizeof(void*));
- m_nativeArgSize = StackElemSize(sizeof(void*));
+ ThrowTypeLoadExceptionForInvalidFieldMarshal(pFieldDesc, m_resID);
+ return;
}
- else
+
+ UINT resID = IDS_EE_BADMARSHAL_RESTRICTION;
+ NewHolder<ILMarshaler> pMarshaler = CreateILMarshaler(m_type, psl);
+
+ if (!pMarshaler->SupportsFieldMarshal(&resID))
{
- m_managedArgSize = StackElemSize(GetManagedSize(m_type, m_ms));
- m_nativeArgSize = StackElemSize(GetNativeSize(m_type, m_ms));
+ ThrowTypeLoadExceptionForInvalidFieldMarshal(pFieldDesc, resID);
+ return;
}
-#ifdef ENREGISTERED_PARAMTYPE_MAXSIZE
- if (m_managedArgSize > ENREGISTERED_PARAMTYPE_MAXSIZE)
- m_managedArgSize = StackElemSize(sizeof(void*));
+ ILCodeStream* pcsMarshal = psl->GetMarshalCodeStream();
+ ILCodeStream* pcsUnmarshal = psl->GetUnmarshalCodeStream();
- if (m_nativeArgSize > ENREGISTERED_PARAMTYPE_MAXSIZE)
- m_nativeArgSize = StackElemSize(sizeof(void*));
-#endif // ENREGISTERED_PARAMTYPE_MAXSIZE
+ pcsMarshal->EmitNOP("// field { ");
+ pcsUnmarshal->EmitNOP("// field { ");
+
+ pMarshaler->EmitMarshalField(pcsMarshal, pcsUnmarshal, m_paramidx, managedOffset, nativeOffset, &m_args);
+
+ pcsMarshal->EmitNOP("// } field");
+ pcsUnmarshal->EmitNOP("// } field");
+
+ return;
}
-UINT16 MarshalInfo::GetManagedSize(MarshalType mtype, MarshalScenario ms)
+void MarshalInfo::SetupArgumentSizes()
{
CONTRACTL
{
MODE_ANY;
}
CONTRACTL_END;
-
- static const BYTE managedSizes[]=
- {
- #define DEFINE_MARSHALER_TYPE(mt, mclass, fWinRTSupported) IL##mclass::c_CLRSize,
- #include "mtypes.h"
- };
-
- _ASSERTE((SIZE_T)mtype < COUNTOF(managedSizes));
- BYTE managedSize = managedSizes[mtype];
- if (managedSize == VARIABLESIZE)
+ if (m_byref)
{
- switch (mtype)
- {
-
- case MARSHAL_TYPE_BLITTABLEVALUECLASS:
- case MARSHAL_TYPE_VALUECLASS:
-#ifdef FEATURE_COMINTEROP
- case MARSHAL_TYPE_DATETIME:
- case MARSHAL_TYPE_NULLABLE:
- case MARSHAL_TYPE_KEYVALUEPAIR:
-#endif // FEATURE_COMINTEROP
- return (UINT16) m_pMT->GetAlignedNumInstanceFieldBytes();
- break;
-
- default:
- _ASSERTE(0);
- }
+ m_nativeArgSize = StackElemSize(sizeof(void*));
+ }
+ else
+ {
+ m_nativeArgSize = StackElemSize(GetNativeSize(m_type));
}
- return managedSize;
+#ifdef ENREGISTERED_PARAMTYPE_MAXSIZE
+ if (m_nativeArgSize > ENREGISTERED_PARAMTYPE_MAXSIZE)
+ m_nativeArgSize = StackElemSize(sizeof(void*));
+#endif // ENREGISTERED_PARAMTYPE_MAXSIZE
}
-UINT16 MarshalInfo::GetNativeSize(MarshalType mtype, MarshalScenario ms)
+UINT16 MarshalInfo::GetNativeSize(MarshalType mtype)
{
CONTRACTL
{
// store the pre-redirection interface type as thNativeItf
pInfo->thNativeItf = pInfo->thItf;
- if (ms == MARSHAL_SCENARIO_WINRT)
+ if (ms == MarshalInfo::MARSHAL_SCENARIO_WINRT || ms == MarshalInfo::MARSHAL_SCENARIO_WINRT_FIELD)
{
// Use the "class is hint" flag so GetObjectRefFromComIP doesn't verify that the
// WinRT object really supports IInspectable - note that we'll do the verification
UINT16 MarshalInfo::GetHiddenLengthParamStackSize()
{
LIMITED_METHOD_CONTRACT;
- return StackElemSize(GetNativeSize(GetHiddenLengthParamMarshalType(), m_ms));
+ return StackElemSize(GetNativeSize(GetHiddenLengthParamMarshalType()));
}
void MarshalInfo::MarshalHiddenLengthArgument(NDirectStubLinker *psl, BOOL managedToNative, BOOL isForReturnArray)
MARSHAL_FLAG_HRESULT_SWAP = 0x10,
MARSHAL_FLAG_RETVAL = 0x20,
MARSHAL_FLAG_HIDDENLENPARAM = 0x40,
+ MARSHAL_FLAG_FIELD = 0x80
};
#include <pshpack1.h>
void* m_hndManagedType; // TypeHandle cannot be a union member
} rcm; // MARSHAL_TYPE_REFERENCECUSTOMMARSHALER
+ struct
+ {
+ UINT32 fixedStringLength;
+ } fs;
};
};
CorElementType * pManagedElemType,
CorNativeType * pNativeType);
+#ifdef _DEBUG
+BOOL IsFixedBuffer(mdFieldDef field, IMDInternalImport* pInternalImport);
+#endif
+
#ifdef FEATURE_COMINTEROP
class EventArgsMarshalingInfo
#ifdef FEATURE_COMINTEROP
MARSHAL_SCENARIO_COMINTEROP,
MARSHAL_SCENARIO_WINRT,
+ MARSHAL_SCENARIO_WINRT_FIELD,
#endif // FEATURE_COMINTEROP
MARSHAL_SCENARIO_FIELD
};
BOOL fEmitsIL,
BOOL onInstanceMethod,
MethodDesc* pMD = NULL,
- BOOL fUseCustomMarshal = TRUE
+ BOOL fUseCustomMarshal = TRUE,
+ BOOL fCalculatingFieldMetadata = FALSE // Calculating metadata for fields on type load.
#ifdef _DEBUG
,
LPCUTF8 pDebugName = NULL,
VOID EmitOrThrowInteropParamException(NDirectStubLinker* psl, BOOL fMngToNative, UINT resID, UINT paramIdx);
+ void ThrowTypeLoadExceptionForInvalidFieldMarshal(FieldDesc* pFieldDesc, UINT resID);
+
// These methods retrieve the information for different element types.
HRESULT HandleArrayElemType(NativeTypeParamInfo *pParamInfo,
TypeHandle elemTypeHnd,
int iRank,
BOOL fNoLowerBounds,
BOOL isParam,
- Assembly *pAssembly);
+ Assembly *pAssembly,
+ BOOL isArrayClass = FALSE);
void GenerateArgumentIL(NDirectStubLinker* psl,
int argOffset, // the argument's index is m_paramidx + argOffset
BOOL fMngToNative,
BOOL fieldGetter,
BOOL retval);
+
+ void GenerateFieldIL(NDirectStubLinker* psl,
+ UINT32 managedOffset, // the field's byte offset into the managed object
+ UINT32 nativeOffset, // the field's byte offset into the native object
+ FieldDesc* pFieldDesc); // The field descriptor for reporting errors
+
+ OverrideProcArgs const* GetOverrideProcArgs()
+ {
+ LIMITED_METHOD_CONTRACT;
+ return &m_args;
+ }
void SetupArgumentSizes();
{
LIMITED_METHOD_CONTRACT;
- return m_ms == MarshalInfo::MARSHAL_SCENARIO_WINRT;
+ return m_ms == MarshalInfo::MARSHAL_SCENARIO_WINRT || m_ms == MarshalInfo::MARSHAL_SCENARIO_WINRT_FIELD;
}
#endif // FEATURE_COMINTEROP
+ BOOL IsFieldScenario()
+ {
+ LIMITED_METHOD_CONTRACT;
+#ifdef FEATURE_COMINTEROP
+ return m_ms == MarshalInfo::MARSHAL_SCENARIO_FIELD || m_ms == MarshalInfo::MARSHAL_SCENARIO_WINRT_FIELD;
+#else
+ return m_ms == MarshalInfo::MARSHAL_SCENARIO_FIELD;
+#endif
+ }
+
private:
- UINT16 GetManagedSize(MarshalType mtype, MarshalScenario ms);
- UINT16 GetNativeSize(MarshalType mtype, MarshalScenario ms);
+ UINT16 GetNativeSize(MarshalType mtype);
static bool IsInOnly(MarshalType mtype);
static bool IsSupportedForWinRT(MarshalType mtype);
#endif // FEATURE_COMINTEROP
UINT16 m_nativeArgSize;
- UINT16 m_managedArgSize;
MarshalScenario m_ms;
BOOL m_fAnsi;
#endif
Module* m_pModule;
+ mdToken m_token;
};
{
// for the purpose of marshaling, we don't care about the inner
// type - we just marshal pointer-sized values
- return (sizeof(LPVOID) == 4 ? VT_I4 : VT_I8);
+#ifdef _TARGET_64BIT_
+ return VT_I8;
+#else
+ return VT_I4;
+#endif
}
else
{
{
LIMITED_METHOD_CONTRACT;
- return sizeof(LPVOID);
+#ifdef _TARGET_64BIT_
+ return 8;
+#else
+ return 4;
+#endif
}
protected:
DEFINE_METHOD(RUNTIME_HELPERS, IS_BITWISE_EQUATABLE, IsBitwiseEquatable, NoSig)
DEFINE_METHOD(RUNTIME_HELPERS, GET_RAW_SZ_ARRAY_DATA, GetRawSzArrayData, NoSig)
DEFINE_METHOD(RUNTIME_HELPERS, GET_RAW_ARRAY_DATA, GetRawArrayData, NoSig)
+DEFINE_METHOD(RUNTIME_HELPERS, GET_UNINITIALIZED_OBJECT, GetUninitializedObject, NoSig)
DEFINE_CLASS(JIT_HELPERS, CompilerServices, JitHelpers)
DEFINE_METHOD(JIT_HELPERS, ENUM_EQUALS, EnumEquals, NoSig)
DEFINE_CLASS(FIRSTCHANCE_EVENTARGS, ExceptionServices, FirstChanceExceptionEventArgs)
DEFINE_METHOD(FIRSTCHANCE_EVENTARGS, CTOR, .ctor, IM_Exception_RetVoid)
+DEFINE_CLASS(EXCEPTION_DISPATCH_INFO, ExceptionServices, ExceptionDispatchInfo)
+DEFINE_METHOD(EXCEPTION_DISPATCH_INFO, CAPTURE, Capture, NoSig)
+DEFINE_METHOD(EXCEPTION_DISPATCH_INFO, THROW, Throw, IM_RetVoid)
+
DEFINE_CLASS_U(Loader, AssemblyLoadContext, AssemblyLoadContextBaseObject)
DEFINE_FIELD_U(_unloadLock, AssemblyLoadContextBaseObject, _unloadLock)
DEFINE_FIELD_U(_resolvingUnmanagedDll, AssemblyLoadContextBaseObject, _resovlingUnmanagedDll)
DEFINE_METHOD(STUBHELPERS, FMT_CLASS_UPDATE_NATIVE_INTERNAL, FmtClassUpdateNativeInternal, SM_Obj_PtrByte_RefCleanupWorkListElement_RetVoid)
DEFINE_METHOD(STUBHELPERS, FMT_CLASS_UPDATE_CLR_INTERNAL, FmtClassUpdateCLRInternal, SM_Obj_PtrByte_RetVoid)
-DEFINE_METHOD(STUBHELPERS, LAYOUT_DESTROY_NATIVE_INTERNAL, LayoutDestroyNativeInternal, SM_PtrByte_IntPtr_RetVoid)
+DEFINE_METHOD(STUBHELPERS, LAYOUT_DESTROY_NATIVE_INTERNAL, LayoutDestroyNativeInternal, SM_Obj_PtrByte_RetVoid)
DEFINE_METHOD(STUBHELPERS, ALLOCATE_INTERNAL, AllocateInternal, SM_IntPtr_RetObj)
DEFINE_METHOD(STUBHELPERS, MARSHAL_TO_MANAGED_VA_LIST_INTERNAL,MarshalToManagedVaListInternal, SM_IntPtr_IntPtr_RetVoid)
DEFINE_METHOD(STUBHELPERS, MARSHAL_TO_UNMANAGED_VA_LIST_INTERNAL,MarshalToUnmanagedVaListInternal,SM_IntPtr_UInt_IntPtr_RetVoid)
DEFINE_CLASS(CSTRMARSHALER, StubHelpers, CSTRMarshaler)
DEFINE_METHOD(CSTRMARSHALER, CONVERT_TO_NATIVE, ConvertToNative, SM_Int_Str_IntPtr_RetIntPtr)
+DEFINE_METHOD(CSTRMARSHALER, CONVERT_FIXED_TO_NATIVE,ConvertFixedToNative, SM_Int_Str_IntPtr_Int_RetVoid)
DEFINE_METHOD(CSTRMARSHALER, CONVERT_TO_MANAGED, ConvertToManaged, SM_IntPtr_RetStr)
+DEFINE_METHOD(CSTRMARSHALER, CONVERT_FIXED_TO_MANAGED,ConvertFixedToManaged, SM_IntPtr_Int_RetStr)
DEFINE_METHOD(CSTRMARSHALER, CLEAR_NATIVE, ClearNative, SM_IntPtr_RetVoid)
-DEFINE_CLASS(WSTRBUFFERMARSHALER, StubHelpers, WSTRBufferMarshaler)
-DEFINE_METHOD(WSTRBUFFERMARSHALER, CONVERT_TO_NATIVE, ConvertToNative, SM_Str_RetIntPtr)
-DEFINE_METHOD(WSTRBUFFERMARSHALER, CONVERT_TO_MANAGED, ConvertToManaged, SM_IntPtr_RetStr)
-DEFINE_METHOD(WSTRBUFFERMARSHALER, CLEAR_NATIVE, ClearNative, SM_IntPtr_RetVoid)
+DEFINE_CLASS(FIXEDWSTRMARSHALER, StubHelpers, FixedWSTRMarshaler)
+DEFINE_METHOD(FIXEDWSTRMARSHALER, CONVERT_TO_NATIVE, ConvertToNative, SM_Str_IntPtr_Int_RetVoid)
DEFINE_CLASS(BSTRMARSHALER, StubHelpers, BSTRMarshaler)
DEFINE_METHOD(BSTRMARSHALER, CONVERT_TO_NATIVE, ConvertToNative, SM_Str_IntPtr_RetIntPtr)
DEFINE_CLASS(MNGD_SAFE_ARRAY_MARSHALER, StubHelpers, MngdSafeArrayMarshaler)
-DEFINE_METHOD(MNGD_SAFE_ARRAY_MARSHALER, CREATE_MARSHALER, CreateMarshaler, SM_IntPtr_IntPtr_Int_Int_RetVoid)
+DEFINE_METHOD(MNGD_SAFE_ARRAY_MARSHALER, CREATE_MARSHALER, CreateMarshaler, SM_IntPtr_IntPtr_Int_Int_IntPtr_RetVoid)
DEFINE_METHOD(MNGD_SAFE_ARRAY_MARSHALER, CONVERT_SPACE_TO_NATIVE, ConvertSpaceToNative, SM_IntPtr_RefObj_IntPtr_RetVoid)
DEFINE_METHOD(MNGD_SAFE_ARRAY_MARSHALER, CONVERT_CONTENTS_TO_NATIVE, ConvertContentsToNative, SM_IntPtr_RefObj_IntPtr_Obj_RetVoid)
DEFINE_METHOD(MNGD_SAFE_ARRAY_MARSHALER, CONVERT_SPACE_TO_MANAGED, ConvertSpaceToManaged, SM_IntPtr_RefObj_IntPtr_RetVoid)
DEFINE_METHOD(MNGD_SAFE_ARRAY_MARSHALER, CLEAR_NATIVE, ClearNative, SM_IntPtr_RefObj_IntPtr_RetVoid)
DEFINE_CLASS(MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER, StubHelpers, MngdHiddenLengthArrayMarshaler)
-DEFINE_METHOD(MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER, CREATE_MARSHALER, CreateMarshaler, SM_IntPtr_IntPtr_IntPtr_UShrt_RetVoid)
+DEFINE_METHOD(MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER, CREATE_MARSHALER, CreateMarshaler, SM_IntPtr_IntPtr_IntPtr_UShrt_IntPtr_RetVoid)
DEFINE_METHOD(MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER, CONVERT_SPACE_TO_MANAGED, ConvertSpaceToManaged, SM_IntPtr_RefObj_IntPtr_Int_RetVoid)
DEFINE_METHOD(MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER, CONVERT_CONTENTS_TO_MANAGED, ConvertContentsToManaged, SM_IntPtr_RefObj_IntPtr_RetVoid)
DEFINE_METHOD(MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER, CONVERT_SPACE_TO_NATIVE, ConvertSpaceToNative, SM_IntPtr_RefObj_IntPtr_RetVoid)
#endif // FEATURE_COMINTEROP
-DEFINE_CLASS(VALUECLASSMARSHALER, StubHelpers, ValueClassMarshaler)
-DEFINE_METHOD(VALUECLASSMARSHALER, CONVERT_TO_NATIVE, ConvertToNative, SM_IntPtrIntPtrIntPtr_RefCleanupWorkListElement_RetVoid)
-DEFINE_METHOD(VALUECLASSMARSHALER, CONVERT_TO_MANAGED, ConvertToManaged, SM_IntPtrIntPtrIntPtr_RetVoid)
-DEFINE_METHOD(VALUECLASSMARSHALER, CLEAR_NATIVE, ClearNative, SM_IntPtr_IntPtr_RetVoid)
-
DEFINE_CLASS(DATEMARSHALER, StubHelpers, DateMarshaler)
DEFINE_METHOD(DATEMARSHALER, CONVERT_TO_NATIVE, ConvertToNative, SM_DateTime_RetDbl)
DEFINE_METHOD(DATEMARSHALER, CONVERT_TO_MANAGED, ConvertToManaged, SM_Dbl_RetLong)
DEFINE_METHOD(VBBYVALSTRMARSHALER, CLEAR_NATIVE, ClearNative, SM_IntPtr_RetVoid)
DEFINE_CLASS(MNGD_NATIVE_ARRAY_MARSHALER, StubHelpers, MngdNativeArrayMarshaler)
-DEFINE_METHOD(MNGD_NATIVE_ARRAY_MARSHALER, CREATE_MARSHALER, CreateMarshaler, SM_IntPtr_IntPtr_Int_RetVoid)
+DEFINE_METHOD(MNGD_NATIVE_ARRAY_MARSHALER, CREATE_MARSHALER, CreateMarshaler, SM_IntPtr_IntPtr_Int_IntPtr_RetVoid)
DEFINE_METHOD(MNGD_NATIVE_ARRAY_MARSHALER, CONVERT_SPACE_TO_NATIVE, ConvertSpaceToNative, SM_IntPtr_RefObj_IntPtr_RetVoid)
DEFINE_METHOD(MNGD_NATIVE_ARRAY_MARSHALER, CONVERT_CONTENTS_TO_NATIVE, ConvertContentsToNative, SM_IntPtr_RefObj_IntPtr_RetVoid)
DEFINE_METHOD(MNGD_NATIVE_ARRAY_MARSHALER, CONVERT_SPACE_TO_MANAGED, ConvertSpaceToManaged, SM_IntPtr_RefObj_IntPtr_Int_RetVoid)
DEFINE_METHOD(MNGD_NATIVE_ARRAY_MARSHALER, CONVERT_CONTENTS_TO_MANAGED, ConvertContentsToManaged, SM_IntPtr_RefObj_IntPtr_RetVoid)
-DEFINE_METHOD(MNGD_NATIVE_ARRAY_MARSHALER, CLEAR_NATIVE, ClearNative, SM_IntPtr_IntPtr_Int_RetVoid)
-DEFINE_METHOD(MNGD_NATIVE_ARRAY_MARSHALER, CLEAR_NATIVE_CONTENTS, ClearNativeContents, SM_IntPtr_IntPtr_Int_RetVoid)
+DEFINE_METHOD(MNGD_NATIVE_ARRAY_MARSHALER, CLEAR_NATIVE, ClearNative, SM_IntPtr_RefObj_IntPtr_Int_RetVoid)
+DEFINE_METHOD(MNGD_NATIVE_ARRAY_MARSHALER, CLEAR_NATIVE_CONTENTS, ClearNativeContents, SM_IntPtr_RefObj_IntPtr_Int_RetVoid)
+
+DEFINE_CLASS(MNGD_FIXED_ARRAY_MARSHALER, StubHelpers, MngdFixedArrayMarshaler)
+DEFINE_METHOD(MNGD_FIXED_ARRAY_MARSHALER, CREATE_MARSHALER, CreateMarshaler, SM_IntPtr_IntPtr_Int_Int_IntPtr_RetVoid)
+DEFINE_METHOD(MNGD_FIXED_ARRAY_MARSHALER, CONVERT_SPACE_TO_NATIVE, ConvertSpaceToNative, SM_IntPtr_RefObj_IntPtr_RetVoid)
+DEFINE_METHOD(MNGD_FIXED_ARRAY_MARSHALER, CONVERT_CONTENTS_TO_NATIVE, ConvertContentsToNative, SM_IntPtr_RefObj_IntPtr_RetVoid)
+DEFINE_METHOD(MNGD_FIXED_ARRAY_MARSHALER, CONVERT_SPACE_TO_MANAGED, ConvertSpaceToManaged, SM_IntPtr_RefObj_IntPtr_RetVoid)
+DEFINE_METHOD(MNGD_FIXED_ARRAY_MARSHALER, CONVERT_CONTENTS_TO_MANAGED, ConvertContentsToManaged, SM_IntPtr_RefObj_IntPtr_RetVoid)
+DEFINE_METHOD(MNGD_FIXED_ARRAY_MARSHALER, CLEAR_NATIVE_CONTENTS, ClearNativeContents, SM_IntPtr_RefObj_IntPtr_RetVoid)
DEFINE_CLASS(MNGD_REF_CUSTOM_MARSHALER, StubHelpers, MngdRefCustomMarshaler)
DEFINE_METHOD(MNGD_REF_CUSTOM_MARSHALER, CREATE_MARSHALER, CreateMarshaler, SM_IntPtr_IntPtr_RetVoid)
DEFINE_METHOD(ASANY_MARSHALER, CONVERT_TO_MANAGED, ConvertToManaged, IM_Obj_IntPtr_RetVoid)
DEFINE_METHOD(ASANY_MARSHALER, CLEAR_NATIVE, ClearNative, IM_IntPtr_RetVoid)
+DEFINE_CLASS(HANDLE_MARSHALER, StubHelpers, HandleMarshaler)
+DEFINE_METHOD(HANDLE_MARSHALER, CONVERT_SAFEHANDLE_TO_NATIVE,ConvertSafeHandleToNative, SM_SafeHandle_Bool_RefCleanupWorkListElement_RetIntPtr)
+DEFINE_METHOD(HANDLE_MARSHALER, THROW_SAFEHANDLE_FIELD_CHANGED, ThrowSafeHandleFieldChanged, SM_RetVoid)
+DEFINE_METHOD(HANDLE_MARSHALER, THROW_CRITICALHANDLE_FIELD_CHANGED, ThrowCriticalHandleFieldChanged, SM_RetVoid)
+
DEFINE_CLASS(NATIVEVARIANT, StubHelpers, NativeVariant)
+DEFINE_CLASS(NATIVEDECIMAL, StubHelpers, NativeDecimal)
#ifdef FEATURE_COMINTEROP
DEFINE_CLASS(IITERABLE, WinRT, IIterable`1)
DEFINE_MARSHALER_TYPE(MARSHAL_TYPE_KEYVALUEPAIR, KeyValuePairMarshaler, true)
DEFINE_MARSHALER_TYPE(MARSHAL_TYPE_EXCEPTION, HResultExceptionMarshaler, true) // For WinRT, marshal exceptions as Windows.Foundation.HResult
#endif // FEATURE_COMINTEROP
+
+DEFINE_MARSHALER_TYPE(MARSHAL_TYPE_FIXED_ARRAY, FixedArrayMarshaler, false)
+DEFINE_MARSHALER_TYPE(MARSHAL_TYPE_FIXED_WSTR, FixedWSTRMarshaler, false)
+DEFINE_MARSHALER_TYPE(MARSHAL_TYPE_FIXED_CSTR, FixedCSTRMarshaler, false)
+DEFINE_MARSHALER_TYPE(MARSHAL_TYPE_BLITTABLE_LAYOUTCLASS, BlittableLayoutClassMarshaler, false)
+DEFINE_MARSHALER_TYPE(MARSHAL_TYPE_LAYOUTCLASS, LayoutClassMarshaler, false)
#undef DEFINE_MARSHALER_TYPE
enum NativeFieldFlags : short
{
// The field may be blittable. The other subcategories determine if the field is blittable.
- NATIVE_FIELD_SUBCATEGORY_MAYBE_BLITTABLE = 1 << 7,
+ NATIVE_FIELD_SUBCATEGORY_BLITTABLE = 1 << 7,
// The native representation of the field is a floating point field.
NATIVE_FIELD_SUBCATEGORY_FLOAT = 1 << 8,
// The field has a nested MethodTable* (i.e. a field of a struct, class, or array)
// This subcategory is used for well-known runtime types that aren't specially marshalled in ABIs and fields that cannot be marshalled.
NATIVE_FIELD_SUBCATEGORY_OTHER = 1 << 14,
// The field is a 4-byte floating point.
- NATIVE_FIELD_CATEGORY_R4 = NATIVE_FIELD_SUBCATEGORY_FLOAT | NATIVE_FIELD_SUBCATEGORY_MAYBE_BLITTABLE,
+ NATIVE_FIELD_CATEGORY_R4 = NATIVE_FIELD_SUBCATEGORY_FLOAT | NATIVE_FIELD_SUBCATEGORY_BLITTABLE,
// The field is an 8-byte floating point
- NATIVE_FIELD_CATEGORY_R8 = NATIVE_FIELD_SUBCATEGORY_FLOAT | NATIVE_FIELD_SUBCATEGORY_MAYBE_BLITTABLE | 0x1,
+ NATIVE_FIELD_CATEGORY_R8 = NATIVE_FIELD_SUBCATEGORY_FLOAT | NATIVE_FIELD_SUBCATEGORY_BLITTABLE | 0x1,
// The field is a type with a nested method table but is never blittable (ex. a class with non-auto layout or an array).
NATIVE_FIELD_CATEGORY_NESTED = NATIVE_FIELD_SUBCATEGORY_NESTED,
- // The field is a value class type
- NATIVE_FIELD_CATEGORY_NESTED_VALUE_CLASS = NATIVE_FIELD_SUBCATEGORY_NESTED | NATIVE_FIELD_SUBCATEGORY_MAYBE_BLITTABLE,
+ // The field is a nested type that may be blittable, such as a value class (C# struct).
+ NATIVE_FIELD_CATEGORY_NESTED_BLITTABLE = NATIVE_FIELD_SUBCATEGORY_NESTED | NATIVE_FIELD_SUBCATEGORY_BLITTABLE,
// The field is a System.DateTime (marshals to a Windows DATE type, which is a typedef of double)
NATIVE_FIELD_CATEGORY_DATE = NATIVE_FIELD_SUBCATEGORY_FLOAT,
// The field should be treated like an integer for the purposes of ABIs.
NATIVE_FIELD_CATEGORY_INTEGER_LIKE = NATIVE_FIELD_SUBCATEGORY_INTEGER,
// The field is a blittable integer type.
- NATIVE_FIELD_CATEGORY_BLITTABLE_INTEGER = NATIVE_FIELD_SUBCATEGORY_INTEGER | NATIVE_FIELD_SUBCATEGORY_MAYBE_BLITTABLE,
+ NATIVE_FIELD_CATEGORY_BLITTABLE_INTEGER = NATIVE_FIELD_SUBCATEGORY_INTEGER | NATIVE_FIELD_SUBCATEGORY_BLITTABLE,
// The field is being marshaled to a COM interface pointer.
NATIVE_FIELD_CATEGORY_INTERFACE_TYPE = NATIVE_FIELD_SUBCATEGORY_INTEGER | NATIVE_FIELD_SUBCATEGORY_COM_ONLY,
// The field is a structure that is only valid in COM scenarios.
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-// NSENUMS.H -
-//
-
-//
-// Defines NStruct-related enums
-//
-
-// NStruct Field Type's
-//
-// Columns:
-// Name - name of enum
-// Size - the native size (in bytes) of the field.
-// for some fields, this value cannot be computed
-// without more information. if so, put a zero here
-// and make sure CollectNStructFieldMetadata()
-// has code to compute the size.
-// WinRTSupported - true if the field type is supported in WinRT
-// scenarios.
-//
-// PS - Append new entries only at the end of the enum to avoid phone versioning break.
-// Name (COM+ - Native) Size
-
-DEFINE_NFT(NFT_NONE, 0, false)
-
-DEFINE_NFT(NFT_STRINGUNI, sizeof(LPVOID), false)
-DEFINE_NFT(NFT_STRINGANSI, sizeof(LPVOID), false)
-DEFINE_NFT(NFT_FIXEDSTRINGUNI, 0, false)
-DEFINE_NFT(NFT_FIXEDSTRINGANSI, 0, false)
-
-DEFINE_NFT(NFT_FIXEDCHARARRAYANSI, 0, false)
-DEFINE_NFT(NFT_FIXEDARRAY, 0, false)
-
-DEFINE_NFT(NFT_DELEGATE, sizeof(LPVOID), false)
-
-DEFINE_NFT(NFT_COPY1, 1, true)
-DEFINE_NFT(NFT_COPY2, 2, true)
-DEFINE_NFT(NFT_COPY4, 4, true)
-DEFINE_NFT(NFT_COPY8, 8, true)
-
-DEFINE_NFT(NFT_ANSICHAR, 1, false)
-DEFINE_NFT(NFT_WINBOOL, sizeof(BOOL), false)
-
-DEFINE_NFT(NFT_NESTEDLAYOUTCLASS, 0, false)
-DEFINE_NFT(NFT_NESTEDVALUECLASS, 0, true)
-
-DEFINE_NFT(NFT_CBOOL, 1, true)
-
-DEFINE_NFT(NFT_DATE, sizeof(DATE), false)
-DEFINE_NFT(NFT_DECIMAL, sizeof(DECIMAL), false)
-DEFINE_NFT(NFT_INTERFACE, sizeof(IUnknown*), false)
-
-DEFINE_NFT(NFT_SAFEHANDLE, sizeof(LPVOID), false)
-DEFINE_NFT(NFT_CRITICALHANDLE, sizeof(LPVOID), false)
-DEFINE_NFT(NFT_BSTR, sizeof(BSTR), false)
-
-#ifdef FEATURE_COMINTEROP
-DEFINE_NFT(NFT_SAFEARRAY, 0, false)
-DEFINE_NFT(NFT_HSTRING, sizeof(HSTRING), true)
-DEFINE_NFT(NFT_VARIANT, sizeof(VARIANT), false)
-DEFINE_NFT(NFT_VARIANTBOOL, sizeof(VARIANT_BOOL), false)
-DEFINE_NFT(NFT_CURRENCY, sizeof(CURRENCY), false)
-DEFINE_NFT(NFT_DATETIMEOFFSET, sizeof(INT64), true)
-DEFINE_NFT(NFT_SYSTEMTYPE, sizeof(TypeNameNative), true) // System.Type -> Windows.UI.Xaml.Interop.TypeName
-DEFINE_NFT(NFT_WINDOWSFOUNDATIONHRESULT, sizeof(int), true) // Windows.Foundation.HResult is marshaled to System.Exception.
-#endif // FEATURE_COMINTEROP
-DEFINE_NFT(NFT_STRINGUTF8, sizeof(LPVOID), false)
-DEFINE_NFT(NFT_ILLEGAL, 1, true)
-
-#ifdef FEATURE_COMINTEROP
-DEFINE_NFT(NFT_WINDOWSFOUNDATIONIREFERENCE, sizeof(IUnknown*), true) // Windows.Foundation.IReference`1 is marshaled to System.Nullable`1.
-#endif // FEATURE_COMINTEROP
-
-// Append new entries only at the end of the enum to avoid phone versioning break.
#include "olevariant.h"
#include "comdatetime.h"
#include "fieldmarshaler.h"
+#include "dllimport.h"
/* ------------------------------------------------------------------------- *
* Local constants
// System.Char is 1 byte instead of 2. So here we explicitly return System.UInt16's
// MethodTable to ensure the correct size.
return MscorlibBinder::GetClass(CLASS__UINT16);
+ case VT_DECIMAL:
+ return MscorlibBinder::GetClass(CLASS__NATIVEDECIMAL);
default:
PREFIX_ASSUME(pManagedMT != NULL);
return pManagedMT;
#endif // FEATURE_COMINTEROP
void OleVariant::MarshalBoolArrayOleToCom(void *oleArray, BASEARRAYREF *pComArray,
- MethodTable *pInterfaceMT)
+ MethodTable *pInterfaceMT, PCODE pManagedMarshalerCode)
{
CONTRACTL
{
void OleVariant::MarshalBoolArrayComToOle(BASEARRAYREF *pComArray, void *oleArray,
MethodTable *pInterfaceMT, BOOL fBestFitMapping,
BOOL fThrowOnUnmappableChar,
- BOOL fOleArrayIsValid, SIZE_T cElements)
+ BOOL fOleArrayIsValid, SIZE_T cElements,
+ PCODE pManagedMarshalerCode)
{
CONTRACTL
{
#endif // FEATURE_COMINTEROP
void OleVariant::MarshalWinBoolArrayOleToCom(void *oleArray, BASEARRAYREF *pComArray,
- MethodTable *pInterfaceMT)
+ MethodTable *pInterfaceMT, PCODE pManagedMarshalerCode)
{
CONTRACTL
{
void OleVariant::MarshalWinBoolArrayComToOle(BASEARRAYREF *pComArray, void *oleArray,
MethodTable *pInterfaceMT, BOOL fBestFitMapping,
BOOL fThrowOnUnmappableChar,
- BOOL fOleArrayIsValid, SIZE_T cElements)
+ BOOL fOleArrayIsValid, SIZE_T cElements,
+ PCODE pManagedMarshalerCode)
{
CONTRACTL
{
#endif // FEATURE_COMINTEROP
void OleVariant::MarshalCBoolArrayOleToCom(void* oleArray, BASEARRAYREF* pComArray,
- MethodTable* pInterfaceMT)
+ MethodTable* pInterfaceMT, PCODE pManagedMarshalerCode)
{
LIMITED_METHOD_CONTRACT;
void OleVariant::MarshalCBoolArrayComToOle(BASEARRAYREF* pComArray, void* oleArray,
MethodTable* pInterfaceMT, BOOL fBestFitMapping,
BOOL fThrowOnUnmappableChar, BOOL fOleArrayIsValid,
- SIZE_T cElements)
+ SIZE_T cElements,
+ PCODE pManagedMarshalerCode)
{
LIMITED_METHOD_CONTRACT;
#endif // FEATURE_COMINTEROP
void OleVariant::MarshalAnsiCharArrayOleToCom(void *oleArray, BASEARRAYREF *pComArray,
- MethodTable *pInterfaceMT)
+ MethodTable *pInterfaceMT, PCODE pManagedMarshalerCode)
{
CONTRACTL
{
void OleVariant::MarshalAnsiCharArrayComToOle(BASEARRAYREF *pComArray, void *oleArray,
MethodTable *pInterfaceMT, BOOL fBestFitMapping,
BOOL fThrowOnUnmappableChar, BOOL fOleArrayIsValid,
- SIZE_T cElements)
+ SIZE_T cElements, PCODE pManagedMarshalerCode)
{
CONTRACTL
{
}
void OleVariant::MarshalInterfaceArrayOleToCom(void *oleArray, BASEARRAYREF *pComArray,
- MethodTable *pElementMT)
+ MethodTable *pElementMT, PCODE pManagedMarshalerCode)
{
CONTRACTL
{
void OleVariant::MarshalIUnknownArrayComToOle(BASEARRAYREF *pComArray, void *oleArray,
MethodTable *pElementMT, BOOL fBestFitMapping,
BOOL fThrowOnUnmappableChar,
- BOOL fOleArrayIsValid, SIZE_T cElements)
+ BOOL fOleArrayIsValid, SIZE_T cElements, PCODE pManagedMarshalerCode)
{
WRAPPER_NO_CONTRACT;
MarshalInterfaceArrayComToOleHelper(pComArray, oleArray, pElementMT, FALSE, cElements);
}
-void OleVariant::ClearInterfaceArray(void *oleArray, SIZE_T cElements, MethodTable *pInterfaceMT)
+void OleVariant::ClearInterfaceArray(BASEARRAYREF* pComArray, void *oleArray, SIZE_T cElements, MethodTable *pInterfaceMT, PCODE pManagedMarshalerCode)
{
CONTRACTL
{
}
void OleVariant::MarshalBSTRArrayOleToCom(void *oleArray, BASEARRAYREF *pComArray,
- MethodTable *pInterfaceMT)
+ MethodTable *pInterfaceMT, PCODE pManagedMarshalerCode)
{
CONTRACTL
{
void OleVariant::MarshalBSTRArrayComToOle(BASEARRAYREF *pComArray, void *oleArray,
MethodTable *pInterfaceMT, BOOL fBestFitMapping,
BOOL fThrowOnUnmappableChar,
- BOOL fOleArrayIsValid, SIZE_T cElements)
+ BOOL fOleArrayIsValid, SIZE_T cElements, PCODE pManagedMarshalerCode)
{
CONTRACTL
{
GCPROTECT_END();
}
-void OleVariant::ClearBSTRArray(void *oleArray, SIZE_T cElements, MethodTable *pInterfaceMT)
+void OleVariant::ClearBSTRArray(BASEARRAYREF* pComArray, void *oleArray, SIZE_T cElements, MethodTable *pInterfaceMT, PCODE pManagedMarshalerCode)
{
CONTRACTL
{
* Structure marshaling routines
* ------------------------------------------------------------------------- */
void OleVariant::MarshalNonBlittableRecordArrayOleToCom(void *oleArray, BASEARRAYREF *pComArray,
- MethodTable *pInterfaceMT)
+ MethodTable *pInterfaceMT, PCODE pManagedMarshalerCode)
{
CONTRACTL
{
CONTRACTL_END;
ASSERT_PROTECTED(pComArray);
+
SIZE_T elementCount = (*pComArray)->GetNumComponents();
SIZE_T elemSize = pInterfaceMT->GetNativeSize();
SIZE_T dstofs = ArrayBase::GetDataPtrOffset( (*pComArray)->GetMethodTable() );
while (pOle < pOleEnd)
{
- LayoutUpdateCLR( (LPVOID*)pComArray, dstofs, pInterfaceMT, pOle );
+ BYTE* managedData = (BYTE*)(*(LPVOID*)pComArray) + dstofs;
+
+ MarshalStructViaILStubCode(pManagedMarshalerCode, managedData, pOle, StructMarshalStubs::MarshalOperation::Unmarshal);
+
dstofs += (*pComArray)->GetComponentSize();
pOle += elemSize;
}
void OleVariant::MarshalNonBlittableRecordArrayComToOle(BASEARRAYREF *pComArray, void *oleArray,
MethodTable *pInterfaceMT, BOOL fBestFitMapping,
BOOL fThrowOnUnmappableChar,
- BOOL fOleArrayIsValid, SIZE_T cElements)
+ BOOL fOleArrayIsValid, SIZE_T cElements, PCODE pManagedMarshalerCode)
{
CONTRACTL
{
SIZE_T srcofs = ArrayBase::GetDataPtrOffset( (*pComArray)->GetMethodTable() );
while (pOle < pOleEnd)
{
- LayoutUpdateNative( (LPVOID*)pComArray, srcofs, pInterfaceMT, pOle, NULL );
+ BYTE* managedData = (BYTE*)(*(LPVOID*)pComArray) + srcofs;
+ MarshalStructViaILStubCode(pManagedMarshalerCode, managedData, pOle, StructMarshalStubs::MarshalOperation::Marshal);
+
pOle += elemSize;
srcofs += (*pComArray)->GetComponentSize();
}
}
-void OleVariant::ClearNonBlittableRecordArray(void *oleArray, SIZE_T cElements, MethodTable *pInterfaceMT)
+void OleVariant::ClearNonBlittableRecordArray(BASEARRAYREF* pComArray, void *oleArray, SIZE_T cElements, MethodTable *pInterfaceMT, PCODE pManagedMarshalerCode)
{
CONTRACTL
{
- NOTHROW;
+ THROWS;
GC_TRIGGERS;
MODE_ANY;
PRECONDITION(CheckPointer(oleArray));
PRECONDITION(CheckPointer(pInterfaceMT));
}
CONTRACTL_END;
-
+
+ ASSERT_PROTECTED(pComArray);
+
SIZE_T elemSize = pInterfaceMT->GetNativeSize();
BYTE *pOle = (BYTE *) oleArray;
BYTE *pOleEnd = pOle + elemSize * cElements;
+ SIZE_T srcofs = ArrayBase::GetDataPtrOffset((*pComArray)->GetMethodTable());
while (pOle < pOleEnd)
{
- LayoutDestroyNative(pOle, pInterfaceMT);
+ BYTE* managedData = (BYTE*)(*(LPVOID*)pComArray) + srcofs;
+
+ MarshalStructViaILStubCode(pManagedMarshalerCode, managedData, pOle, StructMarshalStubs::MarshalOperation::Cleanup);
+
pOle += elemSize;
+ srcofs += (*pComArray)->GetComponentSize();
}
}
* ------------------------------------------------------------------------- */
void OleVariant::MarshalLPWSTRArrayOleToCom(void *oleArray, BASEARRAYREF *pComArray,
- MethodTable *pInterfaceMT)
+ MethodTable *pInterfaceMT, PCODE pManagedMarshalerCode)
{
CONTRACTL
{
void OleVariant::MarshalLPWSTRRArrayComToOle(BASEARRAYREF *pComArray, void *oleArray,
MethodTable *pInterfaceMT, BOOL fBestFitMapping,
BOOL fThrowOnUnmappableChar,
- BOOL fOleArrayIsValid, SIZE_T cElements)
+ BOOL fOleArrayIsValid, SIZE_T cElements, PCODE pManagedMarshalerCode)
{
CONTRACTL
{
}
}
-void OleVariant::ClearLPWSTRArray(void *oleArray, SIZE_T cElements, MethodTable *pInterfaceMT)
+void OleVariant::ClearLPWSTRArray(BASEARRAYREF* pComArray, void *oleArray, SIZE_T cElements, MethodTable *pInterfaceMT, PCODE pManagedMarshalerCode)
{
CONTRACTL
{
* ------------------------------------------------------------------------- */
void OleVariant::MarshalLPSTRArrayOleToCom(void *oleArray, BASEARRAYREF *pComArray,
- MethodTable *pInterfaceMT)
+ MethodTable *pInterfaceMT, PCODE pManagedMarshalerCode)
{
CONTRACTL
{
void OleVariant::MarshalLPSTRRArrayComToOle(BASEARRAYREF *pComArray, void *oleArray,
MethodTable *pInterfaceMT, BOOL fBestFitMapping,
BOOL fThrowOnUnmappableChar,
- BOOL fOleArrayIsValid, SIZE_T cElements)
+ BOOL fOleArrayIsValid, SIZE_T cElements, PCODE pManagedMarshalerCode)
{
CONTRACTL
{
}
}
-void OleVariant::ClearLPSTRArray(void *oleArray, SIZE_T cElements, MethodTable *pInterfaceMT)
+void OleVariant::ClearLPSTRArray(BASEARRAYREF* pComArray, void *oleArray, SIZE_T cElements, MethodTable *pInterfaceMT, PCODE pManagedMarshalerCode)
{
CONTRACTL
{
#endif // FEATURE_COMINTEROP
void OleVariant::MarshalDateArrayOleToCom(void *oleArray, BASEARRAYREF *pComArray,
- MethodTable *pInterfaceMT)
+ MethodTable *pInterfaceMT, PCODE pManagedMarshalerCode)
{
CONTRACTL
{
void OleVariant::MarshalDateArrayComToOle(BASEARRAYREF *pComArray, void *oleArray,
MethodTable *pInterfaceMT, BOOL fBestFitMapping,
BOOL fThrowOnUnmappableChar,
- BOOL fOleArrayIsValid, SIZE_T cElements)
+ BOOL fOleArrayIsValid, SIZE_T cElements, PCODE pManagedMarshalerCode)
{
CONTRACTL
{
// Now that we have the value class, allocate an instance of the
// boxed value class and copy the contents of the record into it.
BoxedValueClass = AllocateObject(pValueClass);
- FmtClassUpdateCLR(&BoxedValueClass, (BYTE*)pvRecord);
+
+ MethodDesc* pStructMarshalStub;
+ {
+ GCX_PREEMP();
+
+ pStructMarshalStub = NDirect::CreateStructMarshalILStub(pValueClass);
+ }
+
+ MarshalStructViaILStub(pStructMarshalStub, BoxedValueClass->GetData(), pvRecord, StructMarshalStubs::MarshalOperation::Unmarshal);
}
pComVariant->SetObjRef(BoxedValueClass);
#endif // FEATURE_CLASSIC_COMINTEROP
void OleVariant::MarshalRecordArrayOleToCom(void *oleArray, BASEARRAYREF *pComArray,
- MethodTable *pElementMT)
+ MethodTable *pElementMT, PCODE pManagedMarshalerCode)
{
CONTRACTL
{
{
// The array is non blittable so we need to marshal the elements.
_ASSERTE(pElementMT->HasLayout());
- MarshalNonBlittableRecordArrayOleToCom(oleArray, pComArray, pElementMT);
+ MarshalNonBlittableRecordArrayOleToCom(oleArray, pComArray, pElementMT, pManagedMarshalerCode);
}
}
void OleVariant::MarshalRecordArrayComToOle(BASEARRAYREF *pComArray, void *oleArray,
MethodTable *pElementMT, BOOL fBestFitMapping,
BOOL fThrowOnUnmappableChar,
- BOOL fOleArrayIsValid, SIZE_T cElements)
+ BOOL fOleArrayIsValid, SIZE_T cElements, PCODE pManagedMarshalerCode)
{
CONTRACTL
{
{
// The array is non blittable so we need to marshal the elements.
_ASSERTE(pElementMT->HasLayout());
- MarshalNonBlittableRecordArrayComToOle(pComArray, oleArray, pElementMT, fBestFitMapping, fThrowOnUnmappableChar, fOleArrayIsValid, cElements);
+ MarshalNonBlittableRecordArrayComToOle(pComArray, oleArray, pElementMT, fBestFitMapping, fThrowOnUnmappableChar, fOleArrayIsValid, cElements, pManagedMarshalerCode);
}
}
-void OleVariant::ClearRecordArray(void *oleArray, SIZE_T cElements, MethodTable *pElementMT)
+void OleVariant::ClearRecordArray(BASEARRAYREF* pComArray, void *oleArray, SIZE_T cElements, MethodTable *pElementMT, PCODE pManagedMarshalerCode)
{
CONTRACTL
{
- NOTHROW;
+ THROWS;
GC_TRIGGERS;
MODE_ANY;
PRECONDITION(CheckPointer(oleArray));
if (!pElementMT->IsBlittable())
{
_ASSERTE(pElementMT->HasLayout());
- ClearNonBlittableRecordArray(oleArray, cElements, pElementMT);
+ ClearNonBlittableRecordArray(pComArray, oleArray, cElements, pElementMT, pManagedMarshalerCode);
}
}
void OleVariant::MarshalIDispatchArrayComToOle(BASEARRAYREF *pComArray, void *oleArray,
MethodTable *pElementMT, BOOL fBestFitMapping,
BOOL fThrowOnUnmappableChar, BOOL fOleArrayIsValid,
- SIZE_T cElements)
+ SIZE_T cElements, PCODE pManagedMarshalerCode)
{
WRAPPER_NO_CONTRACT;
}
void OleVariant::MarshalCurrencyArrayOleToCom(void *oleArray, BASEARRAYREF *pComArray,
- MethodTable *pInterfaceMT)
+ MethodTable *pInterfaceMT, PCODE pManagedMarshalerCode)
{
CONTRACTL
{
void OleVariant::MarshalCurrencyArrayComToOle(BASEARRAYREF *pComArray, void *oleArray,
MethodTable *pInterfaceMT, BOOL fBestFitMapping,
BOOL fThrowOnUnmappableChar,
- BOOL fOleArrayIsValid, SIZE_T cElements)
+ BOOL fOleArrayIsValid, SIZE_T cElements, PCODE pManagedMarshalerCode)
{
CONTRACTL
{
* ------------------------------------------------------------------------- */
void OleVariant::MarshalVariantArrayOleToCom(void *oleArray, BASEARRAYREF *pComArray,
- MethodTable *pInterfaceMT)
+ MethodTable *pInterfaceMT, PCODE pManagedMarshalerCode)
{
CONTRACTL
{
void OleVariant::MarshalVariantArrayComToOle(BASEARRAYREF *pComArray, void *oleArray,
MethodTable *pInterfaceMT, BOOL fBestFitMapping,
BOOL fThrowOnUnmappableChar,
- BOOL fOleArrayIsValid, SIZE_T cElements)
+ BOOL fOleArrayIsValid, SIZE_T cElements, PCODE pManagedMarshalerCode)
{
CONTRACTL
{
GCPROTECT_END();
}
-void OleVariant::ClearVariantArray(void *oleArray, SIZE_T cElements, MethodTable *pInterfaceMT)
+void OleVariant::ClearVariantArray(BASEARRAYREF* pComArray, void *oleArray, SIZE_T cElements, MethodTable *pInterfaceMT, PCODE pManagedMarshalerCode)
{
CONTRACTL
{
if (vt == VT_RECORD)
pElemMT = GetElementTypeForRecordSafeArray(pSafeArray).GetMethodTable();
+ MethodDesc* pStructMarshalStub = nullptr;
+ if (vt == VT_RECORD && !pElemMT->IsBlittable())
+ {
+ GCX_PREEMP();
+
+ pStructMarshalStub = NDirect::CreateStructMarshalILStub(pElemMT);
+ }
+
BASEARRAYREF pArrayRef = CreateArrayRefForSafeArray(pSafeArray, vt, pElemMT);
pComVariant->SetObjRef((OBJECTREF) pArrayRef);
- MarshalArrayRefForSafeArray(pSafeArray, (BASEARRAYREF *) pComVariant->GetObjRefPtr(), vt, pElemMT);
+ MarshalArrayRefForSafeArray(pSafeArray, (BASEARRAYREF *) pComVariant->GetObjRefPtr(), vt, pStructMarshalStub != nullptr ? pStructMarshalStub->GetMultiCallableAddrOfCode() : NULL, pElemMT);
}
else
{
pElemMT = GetArrayElementTypeWrapperAware(pArrayRef).GetMethodTable();
+ MethodDesc* pStructMarshalStub = nullptr;
+ GCPROTECT_BEGIN(*pArrayRef);
+ if (vt == VT_RECORD && !pElemMT->IsBlittable())
+ {
+ GCX_PREEMP();
+
+ pStructMarshalStub = NDirect::CreateStructMarshalILStub(pElemMT);
+ }
+ GCPROTECT_END();
+
if (*pArrayRef != NULL)
{
pSafeArray = CreateSafeArrayForArrayRef(pArrayRef, vt, pElemMT);
- MarshalSafeArrayForArrayRef(pArrayRef, pSafeArray, vt, pElemMT);
+ MarshalSafeArrayForArrayRef(pArrayRef, pSafeArray, vt, pElemMT, pStructMarshalStub != nullptr ? pStructMarshalStub->GetMultiCallableAddrOfCode() : NULL);
}
V_ARRAY(pOleVariant) = pSafeArray;
pSafeArray.SuppressRelease();
if (vt == VT_RECORD)
pElemMT = GetElementTypeForRecordSafeArray(pSafeArray).GetMethodTable();
+ MethodDesc* pStructMarshalStub = nullptr;
+ if (vt == VT_RECORD && !pElemMT->IsBlittable())
+ {
+ GCX_PREEMP();
+
+ pStructMarshalStub = NDirect::CreateStructMarshalILStub(pElemMT);
+ }
+
BASEARRAYREF pArrayRef = CreateArrayRefForSafeArray(pSafeArray, vt, pElemMT);
pComVariant->SetObjRef((OBJECTREF) pArrayRef);
- MarshalArrayRefForSafeArray(pSafeArray, (BASEARRAYREF *) pComVariant->GetObjRefPtr(), vt, pElemMT);
+ MarshalArrayRefForSafeArray(pSafeArray, (BASEARRAYREF *) pComVariant->GetObjRefPtr(), vt, pStructMarshalStub != nullptr ? pStructMarshalStub->GetMultiCallableAddrOfCode() : NULL, pElemMT);
}
else
{
SAFEARRAY *pSafeArray,
VARTYPE vt,
MethodTable *pInterfaceMT,
+ PCODE pManagedMarshalerCode,
BOOL fSafeArrayIsValid /*= TRUE*/)
{
CONTRACTL
// element according to its specific default interface.
pInterfaceMT = NULL;
}
- marshal->ComToOleArray(&Array, pSafeArray->pvData, pInterfaceMT, TRUE, FALSE, fSafeArrayIsValid, dwNumComponents);
+ marshal->ComToOleArray(&Array, pSafeArray->pvData, pInterfaceMT, TRUE, FALSE, fSafeArrayIsValid, dwNumComponents, pManagedMarshalerCode);
}
if (pSafeArray->cDims != 1)
void OleVariant::MarshalArrayRefForSafeArray(SAFEARRAY *pSafeArray,
BASEARRAYREF *pArrayRef,
VARTYPE vt,
+ PCODE pManagedMarshalerCode,
MethodTable *pInterfaceMT)
{
CONTRACTL
PinningHandleHolder handle = GetAppDomain()->CreatePinningHandle((OBJECTREF)*pArrayRef);
- marshal->OleToComArray(pSrcData, pArrayRef, pInterfaceMT);
+ marshal->OleToComArray(pSrcData, pArrayRef, pInterfaceMT, pManagedMarshalerCode);
}
}
COMPlusThrowHR(hr);
}
- // Allocate an instance of the record.
+ // Allocate an instance of the record.
V_RECORD(pRecHolder) = V_RECORDINFO(pRecHolder)->RecordCreate();
IfNullThrow(V_RECORD(pRecHolder));
- // Marshal the contents of the value class into the record.
- FmtClassUpdateNative(pBoxedValueClass, (BYTE*)V_RECORD(pRecHolder), NULL);
+ // Marshal the contents of the value class into the record.
+ MethodDesc* pStructMarshalStub;
+ {
+ GCPROTECT_BEGIN(*pBoxedValueClass);
+ GCX_PREEMP();
+
+ pStructMarshalStub = NDirect::CreateStructMarshalILStub(pValueClassMT);
+ GCPROTECT_END();
+ }
+
+ MarshalStructViaILStub(pStructMarshalStub, (*pBoxedValueClass)->GetData(), (BYTE*)V_RECORD(pRecHolder), StructMarshalStubs::MarshalOperation::Marshal);
pRecHolder.SuppressRelease();
}
SAFEARRAY* pSafeArray,
VARTYPE vt,
MethodTable* pInterfaceMT,
+ PCODE pManagedMarshalerCode,
BOOL fSafeArrayIsValid = TRUE);
static void MarshalArrayRefForSafeArray(SAFEARRAY* pSafeArray,
BASEARRAYREF* pArrayRef,
VARTYPE vt,
+ PCODE pManagedMarshalerCode,
MethodTable* pInterfaceMT);
// Helper function to convert a boxed value class to an OLE variant.
void (*ComToOleVariant)(VariantData* pComVariant, VARIANT* pOleVariant);
void (*OleRefToComVariant)(VARIANT* pOleVariant, VariantData* pComVariant);
#endif // FEATURE_COMINTEROP
- void (*OleToComArray)(void* oleArray, BASEARRAYREF* pComArray, MethodTable* pInterfaceMT);
+ void (*OleToComArray)(void* oleArray, BASEARRAYREF* pComArray, MethodTable* pInterfaceMT, PCODE pManagedMarshalerCode);
void (*ComToOleArray)(BASEARRAYREF* pComArray, void* oleArray, MethodTable* pInterfaceMT,
BOOL fBestFitMapping, BOOL fThrowOnUnmappableChar,
- BOOL fOleArrayIsValid,SIZE_T cElements);
- void (*ClearOleArray)(void* oleArray, SIZE_T cElements, MethodTable* pInterfaceMT);
+ BOOL fOleArrayIsValid,SIZE_T cElements,
+ PCODE pManagedMarshalerCode);
+ void (*ClearOleArray)(BASEARRAYREF* pComArray, void* oleArray, SIZE_T cElements, MethodTable* pInterfaceMT, PCODE pManagedMarshalerCode);
};
static const Marshaler* GetMarshalerForVarType(VARTYPE vt, BOOL fThrow);
// Specific marshaler functions
static void MarshalBoolArrayOleToCom(void *oleArray, BASEARRAYREF* pComArray,
- MethodTable* pInterfaceMT);
+ MethodTable* pInterfaceMT, PCODE pManagedMarshalerCode);
static void MarshalBoolArrayComToOle(BASEARRAYREF* pComArray, void* oleArray,
MethodTable* pInterfaceMT, BOOL fBestFitMapping,
BOOL fThrowOnUnmappableChar, BOOL fOleArrayIsValid,
- SIZE_T cElements);
+ SIZE_T cElements, PCODE pManagedMarshalerCode);
static void MarshalWinBoolArrayOleToCom(void* oleArray, BASEARRAYREF* pComArray,
- MethodTable* pInterfaceMT);
+ MethodTable* pInterfaceMT, PCODE pManagedMarshalerCode);
static void MarshalWinBoolArrayComToOle(BASEARRAYREF* pComArray, void* oleArray,
MethodTable* pInterfaceMT, BOOL fBestFitMapping,
BOOL fThrowOnUnmappableChar, BOOL fOleArrayValid,
- SIZE_T cElements);
+ SIZE_T cElements, PCODE pManagedMarshalerCode);
static void MarshalCBoolVariantOleToCom(VARIANT* pOleVariant, VariantData* pComVariant);
static void MarshalCBoolVariantComToOle(VariantData* pComVariant, VARIANT* pOleVariant);
static void MarshalCBoolVariantOleRefToCom(VARIANT* pOleVariant, VariantData* pComVariant);
static void MarshalCBoolArrayOleToCom(void* oleArray, BASEARRAYREF* pComArray,
- MethodTable* pInterfaceMT);
+ MethodTable* pInterfaceMT, PCODE pManagedMarshalerCode);
static void MarshalCBoolArrayComToOle(BASEARRAYREF* pComArray, void* oleArray,
MethodTable* pInterfaceMT, BOOL fBestFitMapping,
BOOL fThrowOnUnmappableChar, BOOL fOleArrayValid,
- SIZE_T cElements);
+ SIZE_T cElements, PCODE pManagedMarshalerCode);
static void MarshalAnsiCharArrayOleToCom(void* oleArray, BASEARRAYREF* pComArray,
- MethodTable* pInterfaceMT);
+ MethodTable* pInterfaceMT, PCODE pManagedMarshalerCode);
static void MarshalAnsiCharArrayComToOle(BASEARRAYREF* pComArray, void* oleArray,
MethodTable* pInterfaceMT, BOOL fBestFitMapping,
BOOL fThrowOnUnmappableChar, BOOL fOleArrayValid,
- SIZE_T cElements);
+ SIZE_T cElements, PCODE pManagedMarshalerCode);
#ifdef FEATURE_COMINTEROP
static void MarshalIDispatchArrayComToOle(BASEARRAYREF* pComArray, void* oleArray,
MethodTable* pInterfaceMT, BOOL fBestFitMapping,
BOOL fThrowOnUnmappableChar, BOOL fOleArrayValid,
- SIZE_T cElements);
+ SIZE_T cElements, PCODE pManagedMarshalerCode);
#endif // FEATURE_COMINTEROP
#ifdef FEATURE_COMINTEROP
static void MarshalBSTRArrayOleToCom(void* oleArray, BASEARRAYREF* pComArray,
- MethodTable* pInterfaceMT);
+ MethodTable* pInterfaceMT, PCODE pManagedMarshalerCode);
static void MarshalBSTRArrayComToOle(BASEARRAYREF* pComArray, void* oleArray,
MethodTable* pInterfaceMT, BOOL fBestFitMapping,
BOOL fThrowOnUnmappableChar, BOOL fOleArrayValid,
- SIZE_T cElements);
- static void ClearBSTRArray(void* oleArray, SIZE_T cElements, MethodTable* pInterfaceMT);
+ SIZE_T cElements, PCODE pManagedMarshalerCode);
+ static void ClearBSTRArray(BASEARRAYREF* comArray, void* oleArray, SIZE_T cElements, MethodTable* pInterfaceMT, PCODE pManagedMarshalerCode);
#endif // FEATURE_COMINTEROP
static void MarshalNonBlittableRecordArrayOleToCom(void* oleArray, BASEARRAYREF* pComArray,
- MethodTable* pInterfaceMT);
+ MethodTable* pInterfaceMT, PCODE pManagedMarshalerCode);
static void MarshalNonBlittableRecordArrayComToOle(BASEARRAYREF* pComArray, void* oleArray,
MethodTable* pInterfaceMT, BOOL fBestFitMapping,
BOOL fThrowOnUnmappableChar, BOOL fOleArrayValid,
- SIZE_T cElements);
- static void ClearNonBlittableRecordArray(void* oleArray, SIZE_T cElements, MethodTable* pInterfaceMT);
+ SIZE_T cElements, PCODE pManagedMarshalerCode);
+ static void ClearNonBlittableRecordArray(BASEARRAYREF* comArray, void* oleArray,
+ SIZE_T cElements, MethodTable* pInterfaceMT,
+ PCODE pManagedMarshalerCode);
static void MarshalLPWSTRArrayOleToCom(void* oleArray, BASEARRAYREF* pComArray,
- MethodTable* pInterfaceMT);
+ MethodTable* pInterfaceMT, PCODE pManagedMarshalerCode);
static void MarshalLPWSTRRArrayComToOle(BASEARRAYREF* pComArray, void* oleArray,
MethodTable* pInterfaceMT, BOOL fBestFitMapping,
BOOL fThrowOnUnmappableChar, BOOL fOleArrayValid,
- SIZE_T cElements);
- static void ClearLPWSTRArray(void* oleArray, SIZE_T cElements, MethodTable* pInterfaceMT);
+ SIZE_T cElements, PCODE pManagedMarshalerCode);
+ static void ClearLPWSTRArray(BASEARRAYREF* comArray, void* oleArray,
+ SIZE_T cElements, MethodTable* pInterfaceMT, PCODE pManagedMarshalerCode);
static void MarshalLPSTRArrayOleToCom(void* oleArray, BASEARRAYREF* pComArray,
- MethodTable* pInterfaceMT);
+ MethodTable* pInterfaceMT, PCODE pManagedMarshalerCode);
static void MarshalLPSTRRArrayComToOle(BASEARRAYREF* pComArray, void* oleArray,
MethodTable* pInterfaceMT, BOOL fBestFitMapping,
BOOL fThrowOnUnmappableChar, BOOL fOleArrayValid,
- SIZE_T cElements);
- static void ClearLPSTRArray(void* oleArray, SIZE_T cElements, MethodTable* pInterfaceMT);
+ SIZE_T cElements, PCODE pManagedMarshalerCode);
+ static void ClearLPSTRArray(BASEARRAYREF* comArray, void* oleArray,
+ SIZE_T cElements, MethodTable* pInterfaceMT, PCODE pManagedMarshalerCode);
static void MarshalDateArrayOleToCom(void* oleArray, BASEARRAYREF* pComArray,
- MethodTable* pInterfaceMT);
+ MethodTable* pInterfaceMT, PCODE pManagedMarshalerCode);
static void MarshalDateArrayComToOle(BASEARRAYREF* pComArray, void* oleArray,
MethodTable* pInterfaceMT, BOOL fBestFitMapping,
BOOL fThrowOnUnmappableChar, BOOL fOleArrayValid,
- SIZE_T cElements);
+ SIZE_T cElements, PCODE pManagedMarshalerCode);
- static void MarshalRecordArrayOleToCom(void* oleArray, BASEARRAYREF* pComArray, MethodTable* pElementMT);
+ static void MarshalRecordArrayOleToCom(void* oleArray, BASEARRAYREF* pComArray, MethodTable* pElementMT, PCODE pManagedMarshalerCode);
static void MarshalRecordArrayComToOle(BASEARRAYREF* pComArray, void* oleArray, MethodTable* pElementMT,
BOOL fBestFitMapping, BOOL fThrowOnUnmappableChar,
BOOL fOleArrayValid,
- SIZE_T cElements);
- static void ClearRecordArray(void* oleArray, SIZE_T cElements, MethodTable* pElementMT);
+ SIZE_T cElements, PCODE pManagedMarshalerCode);
+ static void ClearRecordArray(BASEARRAYREF* comArray, void* oleArray, SIZE_T cElements, MethodTable* pElementMT, PCODE pManagedMarshalerCode);
#ifdef FEATURE_COMINTEROP
static HRESULT MarshalCommonOleRefVariantForObject(OBJECTREF *pObj, VARIANT *pOle);
static void MarshalInterfaceArrayOleToCom(void* oleArray, BASEARRAYREF* pComArray,
- MethodTable* pInterfaceMT);
+ MethodTable* pInterfaceMT, PCODE pManagedMarshalerCode);
static void MarshalIUnknownArrayComToOle(BASEARRAYREF* pComArray, void* oleArray,
MethodTable* pInterfaceMT, BOOL fBestFitMapping,
BOOL fThrowOnUnmappableChar, BOOL fOleArrayValid,
- SIZE_T cElements);
- static void ClearInterfaceArray(void* oleArray, SIZE_T cElements, MethodTable* pInterfaceMT);
+ SIZE_T cElements, PCODE pManagedMarshalerCode);
+ static void ClearInterfaceArray(BASEARRAYREF* comArray, void* oleArray, SIZE_T cElements, MethodTable* pInterfaceMT, PCODE pManagedMarshalerCode);
static void MarshalBoolVariantOleToCom(VARIANT* pOleVariant, VariantData* pComVariant);
static void MarshalCurrencyVariantComToOle(VariantData* pComVariant, VARIANT* pOleVariant);
static void MarshalCurrencyVariantOleRefToCom(VARIANT* pOleVariant, VariantData* pComVariant);
static void MarshalCurrencyArrayOleToCom(void* oleArray, BASEARRAYREF* pComArray,
- MethodTable* pInterfaceMT);
+ MethodTable* pInterfaceMT, PCODE pManagedMarshalerCode);
static void MarshalCurrencyArrayComToOle(BASEARRAYREF* pComArray, void* oleArray,
MethodTable* pInterfaceMT, BOOL fBestFitMapping,
BOOL fThrowOnUnmappableChar, BOOL fOleArrayValid,
- SIZE_T cElements);
+ SIZE_T cElements, PCODE pManagedMarshalerCode);
static void MarshalVariantArrayOleToCom(void* oleArray, BASEARRAYREF* pComArray,
- MethodTable* pInterfaceMT);
+ MethodTable* pInterfaceMT, PCODE pManagedMarshalerCode);
static void MarshalVariantArrayComToOle(BASEARRAYREF* pComArray, void* oleArray,
MethodTable* pInterfaceMT, BOOL fBestFitMapping,
BOOL fThrowOnUnmappableChar, BOOL fOleArrayValid,
- SIZE_T cElements);
- static void ClearVariantArray(void* oleArray, SIZE_T cElements, MethodTable* pInterfaceMT);
+ SIZE_T cElements, PCODE pManagedMarshalerCode);
+ static void ClearVariantArray(BASEARRAYREF* comArray, void* oleArray, SIZE_T cElements, MethodTable* pInterfaceMT, PCODE pManagedMarshalerCode);
#ifdef FEATURE_CLASSIC_COMINTEROP
static void MarshalArrayVariantOleToCom(VARIANT* pOleVariant, VariantData* pComVariant);
case ELEMENT_TYPE_INTERNAL:
{
- CONSISTENCY_CHECK_MSG(!(pType->InternalToken.GetMethodTable()->IsValueType()), "don't know how to handle value types here");
- EmitLDIND_REF();
+ if (pType->InternalToken.GetMethodTable()->IsValueType())
+ {
+ EmitLDOBJ(m_pOwner->GetToken(pType->InternalToken.GetMethodTable()));
+ }
+ else
+ {
+ EmitLDIND_REF();
+ }
break;
}
case ELEMENT_TYPE_INTERNAL:
{
- CONSISTENCY_CHECK_MSG(!(pType->InternalToken.GetMethodTable()->IsValueType()), "don't know how to handle value types here");
- EmitSTIND_REF();
+ if (pType->InternalToken.GetMethodTable()->IsValueType())
+ {
+ EmitSTOBJ(m_pOwner->GetToken(pType->InternalToken.GetMethodTable()));
+ }
+ else
+ {
+ EmitSTIND_REF();
+ }
break;
}
Emit(CEE_THROW, -1, 0);
}
+void ILCodeStream::EmitUNALIGNED(BYTE alignment)
+{
+ WRAPPER_NO_CONTRACT;
+ Emit(CEE_UNALIGNED, 0, alignment);
+}
+
void ILCodeStream::EmitNEWOBJ(BinderMethodID id, int numInArgs)
{
{
LIMITED_METHOD_CONTRACT;
m_uCurInstrIdx = 0;
-}
\ No newline at end of file
+}
#include "stublink.h"
+struct StructMarshalStubs
+{
+ static const DWORD MANAGED_STRUCT_ARGIDX = 0;
+ static const DWORD NATIVE_STRUCT_ARGIDX = 1;
+ static const DWORD OPERATION_ARGIDX = 2;
+ static const DWORD CLEANUP_WORK_LIST_ARGIDX = 3;
+
+ enum MarshalOperation
+ {
+ Marshal,
+ Unmarshal,
+ Cleanup
+ };
+};
+
struct LocalDesc
{
const static size_t MAX_LOCALDESC_ELEMENTS = 8;
void MakeCopyConstructedPointer()
{
LIMITED_METHOD_CONTRACT;
- ChangeType(ELEMENT_TYPE_PTR);
+ MakePointer();
bIsCopyConstructed = TRUE;
}
+ void MakePointer()
+ {
+ LIMITED_METHOD_CONTRACT;
+ ChangeType(ELEMENT_TYPE_PTR);
+ }
+
void ChangeType(CorElementType elemType)
{
LIMITED_METHOD_CONTRACT;
void EmitSTSFLD (int token);
void EmitSUB ();
void EmitTHROW ();
+ void EmitUNALIGNED (BYTE alignment);
// Overloads to simplify common usage patterns
void EmitNEWOBJ (BinderMethodID id, int numInArgs);
#endif // VERIFY_HEAP
-FCIMPL1_V(double, StubHelpers::DateMarshaler__ConvertToNative, INT64 managedDate)
-{
- FCALL_CONTRACT;
-
- double retval = 0.0;
- HELPER_METHOD_FRAME_BEGIN_RET_0();
- retval = COMDateTime::TicksToDoubleDate(managedDate);
- HELPER_METHOD_FRAME_END();
- return retval;
-}
-FCIMPLEND
-
-FCIMPL1_V(INT64, StubHelpers::DateMarshaler__ConvertToManaged, double nativeDate)
-{
- FCALL_CONTRACT;
-
- INT64 retval = 0;
- HELPER_METHOD_FRAME_BEGIN_RET_0();
- retval = COMDateTime::DoubleDateToTicks(nativeDate);
- HELPER_METHOD_FRAME_END();
- return retval;
-}
-FCIMPLEND
-
-FCIMPL4(void, StubHelpers::ValueClassMarshaler__ConvertToNative, LPVOID pDest, LPVOID pSrc, MethodTable* pMT, OBJECTREF *ppCleanupWorkListOnStack)
-{
- FCALL_CONTRACT;
-
- HELPER_METHOD_FRAME_BEGIN_0();
- FmtValueTypeUpdateNative(&pSrc, pMT, (BYTE*)pDest, ppCleanupWorkListOnStack);
- HELPER_METHOD_FRAME_END();
-}
-FCIMPLEND
-
-FCIMPL3(void, StubHelpers::ValueClassMarshaler__ConvertToManaged, LPVOID pDest, LPVOID pSrc, MethodTable* pMT)
-{
- FCALL_CONTRACT;
-
- HELPER_METHOD_FRAME_BEGIN_0();
- FmtValueTypeUpdateCLR(&pDest, pMT, (BYTE*)pSrc);
- HELPER_METHOD_FRAME_END_POLL();
-}
-FCIMPLEND
-
-FCIMPL2(void, StubHelpers::ValueClassMarshaler__ClearNative, LPVOID pDest, MethodTable* pMT)
-{
- FCALL_CONTRACT;
-
- HELPER_METHOD_FRAME_BEGIN_0();
- FmtClassDestroyNative(pDest, pMT);
- HELPER_METHOD_FRAME_END_POLL();
-}
-FCIMPLEND
-
#ifdef FEATURE_COMINTEROP
FORCEINLINE static void GetCOMIPFromRCW_ClearFP()
OBJECTREF pObj = ObjectToOBJECTREF(pObjUNSAFE);
HELPER_METHOD_FRAME_BEGIN_1(pObj);
- FmtClassUpdateNative(&pObj, pbNative, ppCleanupWorkListOnStack);
+ MethodTable* pMT = pObj->GetMethodTable();
+
+ if (pMT->IsBlittable())
+ {
+ memcpyNoGCRefs(pbNative, pObj->GetData(), pMT->GetNativeSize());
+ }
+ else
+ {
+ MethodDesc* structMarshalStub;
+
+ {
+ GCX_PREEMP();
+ structMarshalStub = NDirect::CreateStructMarshalILStub(pMT);
+ }
+
+ MarshalStructViaILStub(structMarshalStub, pObj->GetData(), pbNative, StructMarshalStubs::MarshalOperation::Marshal, (void**)ppCleanupWorkListOnStack);
+ }
HELPER_METHOD_FRAME_END();
}
OBJECTREF pObj = ObjectToOBJECTREF(pObjUNSAFE);
HELPER_METHOD_FRAME_BEGIN_1(pObj);
- FmtClassUpdateCLR(&pObj, pbNative);
+ MethodTable* pMT = pObj->GetMethodTable();
+
+ if (pMT->IsBlittable())
+ {
+ memcpyNoGCRefs(pObj->GetData(), pbNative, pMT->GetNativeSize());
+ }
+ else
+ {
+ MethodDesc* structMarshalStub;
+
+ {
+ GCX_PREEMP();
+ structMarshalStub = NDirect::CreateStructMarshalILStub(pMT);
+ }
+
+ MarshalStructViaILStub(structMarshalStub, pObj->GetData(), pbNative, StructMarshalStubs::MarshalOperation::Unmarshal);
+ }
HELPER_METHOD_FRAME_END();
}
FCIMPLEND
-FCIMPL2(void, StubHelpers::LayoutDestroyNativeInternal, BYTE* pbNative, MethodTable* pMT)
+FCIMPL2(void, StubHelpers::LayoutDestroyNativeInternal, Object* pObjUNSAFE, BYTE* pbNative)
{
FCALL_CONTRACT;
- HELPER_METHOD_FRAME_BEGIN_0();
- LayoutDestroyNative(pbNative, pMT);
+ OBJECTREF pObj = ObjectToOBJECTREF(pObjUNSAFE);
+ HELPER_METHOD_FRAME_BEGIN_1(pObj);
+ MethodTable* pMT = pObj->GetMethodTable();
+
+ if (!pMT->IsBlittable())
+ {
+ MethodDesc* structMarshalStub;
+
+ {
+ GCX_PREEMP();
+ structMarshalStub = NDirect::CreateStructMarshalILStub(pMT);
+ }
+
+ MarshalStructViaILStub(structMarshalStub, pObj->GetData(), pbNative, StructMarshalStubs::MarshalOperation::Cleanup);
+ }
+
HELPER_METHOD_FRAME_END();
}
FCIMPLEND
// PInvoke stub helpers
//-------------------------------------------------------
- static FCDECL1_V(double, DateMarshaler__ConvertToNative, INT64 managedDate);
- static FCDECL1_V(INT64, DateMarshaler__ConvertToManaged, double nativeDate);
-
- static FCDECL4(void, ValueClassMarshaler__ConvertToNative, LPVOID pDest, LPVOID pSrc, MethodTable* pMT, OBJECTREF *ppCleanupWorkListOnStack);
- static FCDECL3(void, ValueClassMarshaler__ConvertToManaged, LPVOID pDest, LPVOID pSrc, MethodTable* pMT);
- static FCDECL2(void, ValueClassMarshaler__ClearNative, LPVOID pDest, MethodTable* pMT);
-
#ifdef FEATURE_COMINTEROP
static FCDECL4(IUnknown*, GetCOMIPFromRCW, Object* pSrcUNSAFE, MethodDesc* pMD, void **ppTarget, CLR_BOOL* pfNeedsRelease);
static FCDECL3(IUnknown*, GetCOMIPFromRCW_WinRT, Object* pSrcUNSAFE, MethodDesc* pMD, void **ppTarget);
static FCDECL3(void, FmtClassUpdateNativeInternal, Object* pObjUNSAFE, BYTE* pbNative, OBJECTREF *ppCleanupWorkListOnStack);
static FCDECL2(void, FmtClassUpdateCLRInternal, Object* pObjUNSAFE, BYTE* pbNative);
- static FCDECL2(void, LayoutDestroyNativeInternal, BYTE* pbNative, MethodTable* pMT);
+ static FCDECL2(void, LayoutDestroyNativeInternal, Object* pObjUNSAFE, BYTE* pbNative);
static FCDECL1(Object*, AllocateInternal, EnregisteredTypeHandle typeHnd);
static FCDECL3(void, MarshalToUnmanagedVaListInternal, va_list va, DWORD cbVaListSize, const VARARGS* pArgIterator);
static FCDECL2(void, MarshalToManagedVaListInternal, va_list va, VARARGS* pArgIterator);
{
return SimpleSeqLayoutClassByRef(&v.str);
}
+
+extern "C" DLL_EXPORT void __cdecl Invalid(...)
+{
+}
public SeqClass value;
}
+
+ [StructLayout(LayoutKind.Sequential)]
+ public class RecursiveTestClass
+ {
+ public RecursiveTestStruct s;
+ }
+
+ public struct RecursiveTestStruct
+ {
+ public RecursiveTestClass c;
+ }
+
class StructureTests
{
[DllImport("LayoutClassNative")]
[DllImport("LayoutClassNative")]
private static extern bool SimpleBlittableSeqLayoutClassByRef(Blittable p);
+ [DllImport("LayoutClassNative", EntryPoint = "Invalid")]
+ private static extern void RecursiveNativeLayoutInvalid(RecursiveTestStruct str);
+
public static bool SequentialClass()
{
string s = "before";
return retval;
}
+ public static bool RecursiveNativeLayout()
+ {
+ TestFramework.BeginScenario("Test #5 Structure with field of nested layout class with field of containing structure.");
+
+ try
+ {
+ RecursiveNativeLayoutInvalid(new RecursiveTestStruct());
+ }
+ catch (TypeLoadException)
+ {
+ return true;
+ }
+
+ return false;
+ }
+
public static int Main(string[] argv)
{
bool retVal = true;
retVal = retVal && ExplicitClass();
retVal = retVal && BlittableClass();
retVal = retVal && NestedLayoutClass();
+ retVal = retVal && RecursiveNativeLayout();
return (retVal ? 100 : 101);
}