Implement struct marshalling via IL Stubs instead of via Field… (dotnet/coreclr#26340)
authorJeremy Koritzinsky <jekoritz@microsoft.com>
Thu, 24 Oct 2019 18:29:38 +0000 (11:29 -0700)
committerGitHub <noreply@github.com>
Thu, 24 Oct 2019 18:29:38 +0000 (11:29 -0700)
* First pass on adding support for byref field homes to il marshalers.

Remove dead code for calculating managed field size.

Add field IL marshal infra up to MarshalInfo::GenerateFieldIL.

Add preliminary changes for MarshalInfo ctor to have the logic handle field marshalling logic. Still need to handle WinRT struct field logic correctly.

First shot at handling fields of WinRT structs.

Cleanup

Clean up entrypoints

Fix cleanup marshal emit.

Disable specific paths on struct marshal stubs.

Implement emitting full struct marshalling stub.

Add StructMarshalInteropStub method name.

Add NDirect::CreateMarshalILStub

Get byvalue StructMarshalling/PInvoke tests passing excluding missing ILMarshalers (ByValArray and ByValTStr).

Correctly classify struct marshal stubs as struct marshal stubs instead of PInvoke stubs.

Implement UnmanagedType.ByValArray IL marshaler.

Implement ILMarshaler equivalent for ansi-char fixed arrays.

Fix parameter mismatch in Native->CLR direction for struct marshalling.

Implement ByValTStr marshalling. Support unaligned fields in IL stubs.

Load CleanupWorkList from param list if in a struct marshalling stub

Implement SafeHandle and CriticalHandle field marshalling in IL struct stubs

Fix handle field marshalers. Add error reporting in struct field IL marshalers consistent with old FieldMarshaler error reporting.

Convert Array-of-nonblittable-struct marshalling to use IL stubs.

Convert LayoutClass marshalling to use IL stubs.
Fix marshalling of LayoutClass fields in structs.

Add non-blittable fixed buffer assert in the struct IL stub path.

Implement Marshal APIs via the IL stubs.

Fix default char marshaler selection.

Move hidden-length-array marshalling over to struct marshalling stubs.

Convert struct marshal IL stub users to use helper that will automatically cleanup on failure to marshal.

Match MarshalInfo::MarshalInfo behavior to ParseNativeType for fields.

Remove old FieldMarshaler-based marshalling.

Fix signed/unsigned mismatch.

Fix IsFieldScenario on non-COMINTEROP plaforms

Fix off-Windows build.

Handle automatic partial cleanup of struct marshaling entirely within the struct stub.

Remove now-unused ValueClassMarshaler. Move DateMarshaler to managed since it doesn't need to be an FCall.

Error out on recursive struct definitions in the IL stub generation as we did in the field marshalling.

Remove FieldMarshalers and replace with a significantly simpler structure (NativeFieldDescriptor) that stores only the needed info for determining validity in WinRT, blittability, and calling convention classification.

This will save 4/8 bytes for every field in a non-auto-layout structure or class loaded into the runtime.

Add explicit test for recursive native layout.

Allow marshalling  as UnmanagedType.Error on all platforms (on non-Windows the behavior matches UnmanagedType.I4).

Collapse common primitive marshalling cases together.

Disable WinRT parameter/retval-only marshalers in field scenarios.

Revert "Collapse common primitive marshalling cases together."

This reverts commit dotnet/coreclr@e73b78a5bca80009fb541f5119301329599a16ad.

Fix error marshalling off Windows for uint.

Disable LPStruct marshalling in structs.

Disable copy-constructor marshaler in the field scenario.

Match error messages between MarshalInfo::MarshalInfo and ParseNativeType in the field scenario.

Refactor managed-sequential check out of ParseNativeType.

Remove invalid MARSHAL_TYPE_GENERIC_U8 references.

Add override specifier.

Change ParseNativeType to use MarshalInfo::MarshalInfo to calculate field marshalling info instead of maintaining two native field classification functions.

Clean up native field categories. Remove nsenums.h since it is now unused.

Move CheckIfDisqualifiedFromManagedSequential to class.cpp.

Encapsulate stub flags for struct stubs. Read the BestFitAttribute once for the type instead of per field.

Fix perf regression in by-val arrays of non-blittable structures by caching the MethodDesc* to the struct stub in the "managed marshaler" structure. Now we have a perf improvement!

Fix memory leak in sig creation.

Keep compile-time information for struct stubs around as long as the owning loader allocator (instead of leaking).

Allocate the signature on the same heap as the IL stubs so it shares the same lifetime.

Fix build with fragile NGen support enabled so as to not break partners.

Add missing native field descriptors.

Fix clang build.

Only assert if we're emitting IL (so we don't assert during type-load).

Determine desciptor for pointer-sized fields based on target not host pointer size.

Don't emit IL stubs that call struct stubs into R2R images since there's not a good way for us to emit the token.

Fix tracing test failures.

Force field marshaling to not stackalloc.

Cache Sytem.RuntimeMethodInfoStub instances created in the VM in the MethodDesc's owning LoaderAllocator.

Struct marshal stubs don't have an MethodDesc context arg.

Copy FieldDesc on NFD assignment.

Fix initialization of stubMethodInfoCache lock owner.

Fix alignment calculation of decimal fields and decimal array fields in NFDs.

Fix Crst leveling.

Enable handling decimal-as-currency fields accurately off-Windows.

Fix deadlock where two threads are both trying to generate an IL stub for the same P/Invoke and one of the parameters needs a struct stub generated.

Fix incorrect check for if we need a struct marshal stub in some of the variant/array cases.

We never need to promote a field value to 8 bytes.

Fix issue with recursive pointer fields.

Shortcut blittable types in stubhelpers.

Use LDFTN + PREPARE_NONVIRUTAL_CALLSITE_USING_CODE instead of LDTOKEN + GetInternalToken.

Revert "Fix Crst leveling."

This reverts commit dotnet/coreclr@1d8e56e077bc9863b71fe5f9e948308849aa3a14.

Revert "Fix initialization of stubMethodInfoCache lock owner."

This reverts commit dotnet/coreclr@a095390646d234fdd13f97f620c0af03ffb71d6a.

Revert "Cache Sytem.RuntimeMethodInfoStub instances created in the VM in the MethodDesc's owning LoaderAllocator."

This reverts commit dotnet/coreclr@726653835b6ee0e3ce03d70600732021f3ea2a53.

Fix case where struct marshal stub is unused in native-only mashalling paths.

PR Feedback.

Clean up terenary statement in dispatchinfo.cpp

Cleanup ILStubResolver::AllocGeneratedIL a little bit.

* Cleanup LayoutClass test.

* Encapsulate getting the entrypoint of a struct marshal stub.

* VTHACK_NONBLITTABLERECORD is only used for hidden-length array marshalling, and VT_RECORD is not used in hidden-length array marshalling.

* Align new entries in mtypes.h

* Whitespace and field ordering changes.

Commit migrated from https://github.com/dotnet/coreclr/commit/549d53289620fdd19fd71b4fb18f9889d1fbbb0d

53 files changed:
src/coreclr/src/System.Private.CoreLib/Resources/Strings.resx
src/coreclr/src/System.Private.CoreLib/src/System/StubHelpers.cs
src/coreclr/src/debug/daccess/nidump.cpp
src/coreclr/src/dlls/mscorrc/mscorrc.rc
src/coreclr/src/dlls/mscorrc/resource.h
src/coreclr/src/vm/ClrEtwAll.man
src/coreclr/src/vm/amd64/cgencpu.h
src/coreclr/src/vm/arm/cgencpu.h
src/coreclr/src/vm/arm64/cgencpu.h
src/coreclr/src/vm/array.cpp
src/coreclr/src/vm/ceeload.cpp
src/coreclr/src/vm/class.cpp
src/coreclr/src/vm/class.h
src/coreclr/src/vm/classcompat.cpp
src/coreclr/src/vm/classcompat.h
src/coreclr/src/vm/clrtocomcall.cpp
src/coreclr/src/vm/comtoclrcall.cpp
src/coreclr/src/vm/dispatchinfo.cpp
src/coreclr/src/vm/dispatchinfo.h
src/coreclr/src/vm/dispparammarshaler.cpp
src/coreclr/src/vm/dllimport.cpp
src/coreclr/src/vm/dllimport.h
src/coreclr/src/vm/ecalllist.h
src/coreclr/src/vm/excep.cpp
src/coreclr/src/vm/excep.h
src/coreclr/src/vm/fieldmarshaler.cpp
src/coreclr/src/vm/fieldmarshaler.h
src/coreclr/src/vm/frames.h
src/coreclr/src/vm/i386/cgencpu.h
src/coreclr/src/vm/ilmarshalers.cpp
src/coreclr/src/vm/ilmarshalers.h
src/coreclr/src/vm/ilstubcache.cpp
src/coreclr/src/vm/ilstubresolver.cpp
src/coreclr/src/vm/ilstubresolver.h
src/coreclr/src/vm/marshalnative.cpp
src/coreclr/src/vm/metasig.h
src/coreclr/src/vm/method.hpp
src/coreclr/src/vm/methodtable.cpp
src/coreclr/src/vm/methodtablebuilder.cpp
src/coreclr/src/vm/mlinfo.cpp
src/coreclr/src/vm/mlinfo.h
src/coreclr/src/vm/mscorlib.h
src/coreclr/src/vm/mtypes.h
src/coreclr/src/vm/nativefieldflags.h
src/coreclr/src/vm/nsenums.h [deleted file]
src/coreclr/src/vm/olevariant.cpp
src/coreclr/src/vm/olevariant.h
src/coreclr/src/vm/stubgen.cpp
src/coreclr/src/vm/stubgen.h
src/coreclr/src/vm/stubhelpers.cpp
src/coreclr/src/vm/stubhelpers.h
src/coreclr/tests/src/Interop/LayoutClass/LayoutClassNative.cpp
src/coreclr/tests/src/Interop/LayoutClass/LayoutClassTest.cs

index eeb7f63..6d46159 100644 (file)
   <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>
index 0141e7c..56278dd 100644 (file)
@@ -121,6 +121,75 @@ namespace System.StubHelpers
         {
             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
@@ -443,23 +512,17 @@ namespace System.StubHelpers
         }
     }  // 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
 
@@ -573,26 +636,45 @@ namespace System.StubHelpers
 
 #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
@@ -640,6 +722,7 @@ namespace System.StubHelpers
 #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;
@@ -648,7 +731,7 @@ namespace System.StubHelpers
         }
 
         [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);
@@ -664,17 +747,38 @@ namespace System.StubHelpers
         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);
@@ -695,7 +799,7 @@ namespace System.StubHelpers
     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);
@@ -971,7 +1075,8 @@ namespace System.StubHelpers
             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);
@@ -1460,6 +1565,17 @@ namespace System.StubHelpers
 #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;
@@ -1476,7 +1592,7 @@ namespace System.StubHelpers
             }
         }
 
-        public static void AddToCleanupList(ref CleanupWorkListElement list, CleanupWorkListElement newElement)
+        public static void AddToCleanupList(ref CleanupWorkListElement? list, CleanupWorkListElement newElement)
         {
             if (list == null)
             {
@@ -1560,14 +1676,14 @@ namespace System.StubHelpers
         [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);
@@ -1713,7 +1829,7 @@ namespace System.StubHelpers
         [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);
 
index b83fe31..551486d 100644 (file)
@@ -14,6 +14,7 @@
 
 #include <comcallablewrapper.h>
 #include <gcdump.h>
+#include <fieldmarshaler.h>
 
 #if !defined(FEATURE_CORESYSTEM)
 #include <algorithm>
@@ -8383,36 +8384,36 @@ NativeImageDumper::DumpEEClassForMethodTable( PTR_MethodTable mt )
                                      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
index 9e9ce02..9e6485a 100644 (file)
@@ -758,6 +758,8 @@ BEGIN
     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."
 
index 9c7865a..56a70a1 100644 (file)
 #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
 
 
index f0596d6..3f5deee 100644 (file)
                         <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" />
index 619fd4b..d2872b3 100644 (file)
@@ -103,16 +103,6 @@ EXTERN_C void FastCallFinalizeWorker(Object *obj, PCODE funcPtr);
 #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
index 6ac5877..ec33125 100644 (file)
@@ -96,18 +96,6 @@ EXTERN_C void setFPReturn(int fpSize, INT64 retVal);
 // 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
 //**********************************************************************
index 6922cd7..b3bb0d1 100644 (file)
@@ -63,14 +63,6 @@ extern PCODE GetPreStubEntryPoint();
 // 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)
 {
index c48449f..ac4e76b 100644 (file)
@@ -26,7 +26,6 @@
 #include "jitinterface.h"
 #include "eeconfig.h"
 #include "log.h"
-#include "fieldmarshaler.h"
 #include "cgensys.h"
 #include "array.h"
 #include "typestring.h"
index 7116181..bc82872 100644 (file)
@@ -9051,7 +9051,7 @@ void Module::PlaceType(DataImage *image, TypeHandle th, DWORD profilingFlags)
         {
             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);
             }
         }
     }
index 00737e3..9713ec1 100644 (file)
@@ -1470,12 +1470,13 @@ CorElementType EEClassLayoutInfo::GetNativeHFATypeRaw()
     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)
         {
@@ -1498,14 +1499,14 @@ CorElementType EEClassLayoutInfo::GetNativeHFATypeRaw()
             }
 
             // 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
         {
@@ -1528,8 +1529,6 @@ CorElementType EEClassLayoutInfo::GetNativeHFATypeRaw()
         {
             return ELEMENT_TYPE_END;
         }
-
-        ((BYTE*&)pFieldMarshaler) += MAXFIELDMARSHALERSIZE;
     }
 
     if (hfaType == ELEMENT_TYPE_END)
@@ -2712,17 +2711,17 @@ void EEClass::Save(DataImage *image, MethodTable *pMT)
 
         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));
             }
         }
     }
@@ -2923,16 +2922,15 @@ void EEClass::Fixup(DataImage *image, MethodTable *pMT)
 
     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())
@@ -3664,7 +3662,7 @@ VOID EEClassLayoutInfo::CollectLayoutFieldMetadataThrowing(
     _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());
@@ -3719,8 +3717,8 @@ VOID EEClassLayoutInfo::CollectLayoutFieldMetadataThrowing(
     // 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
@@ -3745,7 +3743,7 @@ VOID EEClassLayoutInfo::CollectLayoutFieldMetadataThrowing(
     // 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)
@@ -3755,15 +3753,12 @@ VOID EEClassLayoutInfo::CollectLayoutFieldMetadataThrowing(
 
             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];
             }
         }
 
@@ -3855,19 +3850,18 @@ VOID EEClassLayoutInfo::CollectLayoutFieldMetadataThrowing(
             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;
             }
         }
         
@@ -3881,6 +3875,76 @@ VOID EEClassLayoutInfo::CollectLayoutFieldMetadataThrowing(
 #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
@@ -3961,16 +4025,20 @@ void EEClassLayoutInfo::ParseFieldNativeTypes(
             }
 #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,
@@ -3979,7 +4047,7 @@ void EEClassLayoutInfo::ParseFieldNativeTypes(
 #endif
             );
 
-            if (!IsFieldBlittable((FieldMarshaler*)(&pFieldInfoArrayOut->m_FieldMarshaler)))
+            if (!pFieldInfoArrayOut->m_nfd.IsBlittable())
                 pEEClassLayoutInfoOut->SetIsBlittable(FALSE);
 
             (*cInstanceFields)++;
index b174cc2..6dc9520 100644 (file)
@@ -76,7 +76,7 @@ class   FCallMethodDesc;
 class   EEClass;
 class   EnCFieldDesc;
 class   FieldDesc;
-class   FieldMarshaler;
+class   NativeFieldDescriptor;
 struct  LayoutRawFieldInfo;
 class   MetaSig;
 class   MethodDesc;
@@ -99,7 +99,7 @@ class ComCallWrapperTemplate;
 enum class ParseNativeTypeFlags : int;
 
 typedef DPTR(DictionaryLayout) PTR_DictionaryLayout;
-typedef DPTR(FieldMarshaler) PTR_FieldMarshaler;
+typedef DPTR(NativeFieldDescriptor) PTR_NativeFieldDescriptor;
 
 
 //---------------------------------------------------------------------------------
@@ -471,10 +471,10 @@ class EEClassLayoutInfo
         // # 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:
@@ -503,17 +503,17 @@ class EEClassLayoutInfo
             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
 
index 3cc6f72..1af5b11 100644 (file)
@@ -28,7 +28,6 @@
 #include "jitinterface.h"
 #include "eeconfig.h"
 #include "log.h"
-#include "fieldmarshaler.h"
 #include "cgensys.h"
 #include "gcheaputilities.h"
 #include "dbginterface.h"
@@ -47,6 +46,7 @@
 #include "eeconfig.h"
 #include "contractimpl.h"
 #include "prettyprintsig.h"
+#include "compile.h"
 
 #include "comcallablewrapper.h"
 #include "clrtocomcall.h"
index a3f8aa4..0d5bd78 100644 (file)
@@ -43,7 +43,6 @@ class   EEClass;
 class   LayoutEEClass;
 class   EnCFieldDesc;
 class   FieldDesc;
-class   FieldMarshaler;
 struct  LayoutRawFieldInfo;
 class   MetaSig;
 class   MethodDesc;
index 70c9f71..429cd07 100644 (file)
@@ -521,7 +521,7 @@ I4ARRAYREF SetUpWrapperInfo(MethodDesc *pMD)
 
             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
index 033dfdd..a17f863 100644 (file)
@@ -1112,7 +1112,7 @@ void ComCallMethodDesc::InitNativeInfo()
 
             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
@@ -1218,7 +1218,7 @@ void ComCallMethodDesc::InitNativeInfo()
                 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
@@ -1280,7 +1280,7 @@ void ComCallMethodDesc::InitNativeInfo()
                 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
index 2a2d55b..f6ef8eb 100644 (file)
@@ -30,6 +30,7 @@
 #include "dispparammarshaler.h"
 #include "reflectioninvocation.h"
 #include "dbginterface.h"
+#include "dllimport.h"
 
 #define EXCEPTION_INNER_PROP                            "InnerException"
 
@@ -749,11 +750,7 @@ void DispatchMemberInfo::SetUpParamMarshalerInfo()
         }
         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))
         {
@@ -906,7 +903,7 @@ void DispatchMemberInfo::SetUpMethodMarshalerInfo(MethodDesc *pMD, BOOL bReturnV
 
             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
@@ -943,7 +940,7 @@ void DispatchMemberInfo::SetUpMethodMarshalerInfo(MethodDesc *pMD, BOOL bReturnV
     {
         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
@@ -953,12 +950,6 @@ void DispatchMemberInfo::SetUpMethodMarshalerInfo(MethodDesc *pMD, BOOL bReturnV
     }
 }
 
-void DispatchMemberInfo::SetUpFieldMarshalerInfo(FieldDesc *pField)
-{
-    // @TODO(DM): Implement this.
-    LIMITED_METHOD_CONTRACT;
-}
-
 void DispatchMemberInfo::SetUpDispParamMarshalerForMarshalInfo(int iParam, MarshalInfo *pInfo)
 {
     CONTRACTL
@@ -2344,8 +2335,17 @@ void DispatchInfo::MarshalParamManagedToNativeRef(DispatchMemberInfo *pMemberInf
         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
 {
index f5f9b9b..111526a 100644 (file)
@@ -174,7 +174,6 @@ private:
     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:
index 2df417f..b5df8dc 100644 (file)
@@ -229,6 +229,7 @@ void DispParamArrayMarshaler::MarshalNativeToManaged(VARIANT *pSrcVar, OBJECTREF
         GC_TRIGGERS;
         MODE_COOPERATIVE;
         PRECONDITION(CheckPointer(pSrcVar));
+        PRECONDITION(CheckPointer(pDestObj) && *pDestObj == NULL);
     }
     CONTRACTL_END;
     
@@ -242,25 +243,30 @@ void DispParamArrayMarshaler::MarshalNativeToManaged(VARIANT *pSrcVar, OBJECTREF
     // 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)
@@ -293,13 +299,22 @@ void DispParamArrayMarshaler::MarshalManagedToNative(OBJECTREF *pSrcObj, VARIANT
             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.
@@ -397,7 +412,15 @@ void DispParamRecordMarshaler::MarshalNativeToManaged(VARIANT *pSrcVar, OBJECTRE
             // 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;
index ce60fa6..9181f00 100644 (file)
 #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"
@@ -99,9 +101,10 @@ StubSigDesc::StubSigDesc(MethodDesc *pMD, PInvokeStaticSigInfo* pSigInfo /*= NUL
         GC_NOTRIGGER;
         SUPPORTS_DAC;
     }
-    CONTRACTL_END
+    CONTRACTL_END;
 
     m_pMD = pMD;
+    m_pMT = nullptr;
     if (pSigInfo != NULL)
     {
         m_sig           = pSigInfo->GetSignature();
@@ -129,7 +132,7 @@ StubSigDesc::StubSigDesc(MethodDesc *pMD, PInvokeStaticSigInfo* pSigInfo /*= NUL
     INDEBUG(InitDebugNames());
 }
 
-StubSigDesc::StubSigDesc(MethodDesc *pMD, Signature sig, Module *pModule)
+StubSigDesc::StubSigDesc(MethodDesc* pMD, Signature sig, Module* pModule)
 {
     CONTRACTL
     {
@@ -139,11 +142,12 @@ StubSigDesc::StubSigDesc(MethodDesc *pMD, Signature sig, Module *pModule)
         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)
     {
@@ -160,6 +164,60 @@ StubSigDesc::StubSigDesc(MethodDesc *pMD, Signature sig, Module *pModule)
     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
@@ -170,6 +228,7 @@ public:
     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;
@@ -262,6 +321,18 @@ public:
         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)
@@ -584,15 +655,15 @@ public:
         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);
@@ -691,8 +762,8 @@ public:
             pcsExceptionHandler->EmitLDLOC(retvalLocalNum);
         }
         pcsExceptionHandler->EmitRET();
-    }
 #endif // FEATURE_COMINTEROP
+    }
 
     void FinishEmit(MethodDesc* pStubMD)
     {
@@ -724,6 +795,8 @@ public:
                                     && !SF_IsFieldGetterStub(m_dwStubFlags) 
                                     && !SF_IsFieldSetterStub(m_dwStubFlags);
 
+        bool hasTryCatchExceptionHandler = hasTryCatchForHRESULT || SF_IsStructMarshalStub(m_dwStubFlags);
+
 #ifdef FEATURE_COMINTEROP
         if (hasTryCatchForHRESULT)
         {
@@ -774,7 +847,7 @@ public:
         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);
@@ -895,6 +968,10 @@ public:
         {
             // 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)))
@@ -915,14 +992,13 @@ public:
             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;
@@ -939,25 +1015,23 @@ public:
         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)
@@ -966,7 +1040,7 @@ public:
         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);
@@ -1001,12 +1075,12 @@ public:
                     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);
@@ -1028,7 +1102,7 @@ public:
                 pbLocalSig, 
                 cbSig,
                 jitFlags,
-                &convertToHRTryCatch,
+                &tryCatchClause,
                 &cleanupTryFinally,
                 maxStack,
                 (DWORD)cbCode
@@ -1152,6 +1226,8 @@ public:
             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)
@@ -1209,6 +1285,7 @@ public:
         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
@@ -1245,6 +1322,7 @@ public:
             NDIRECTSTUB_FL_NGENEDSTUBFORPROFILING   |
             NDIRECTSTUB_FL_GENERATEDEBUGGABLEIL     |
             NDIRECTSTUB_FL_UNMANAGED_CALLI          |
+            NDIRECTSTUB_FL_STRUCT_MARSHAL           |
             NDIRECTSTUB_FL_TRIGGERCCTOR             |
 #ifdef FEATURE_COMINTEROP
             NDIRECTSTUB_FL_COM                      |
@@ -1320,6 +1398,132 @@ protected:
     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
 {
@@ -2010,8 +2214,15 @@ void NDirectStubLinker::LoadCleanupWorkList(ILCodeStream* pcsEmit)
 {
     STANDARD_VM_CONTRACT;
 
-    NeedsCleanupList();
-    pcsEmit->EmitLDLOCA(GetCleanupWorkListLocalNum());
+    if (SF_IsStructMarshalStub(m_dwStubFlags))
+    {
+        pcsEmit->EmitLDARG(StructMarshalStubs::CLEANUP_WORK_LIST_ARGIDX);
+    }
+    else
+    {
+        NeedsCleanupList();
+        pcsEmit->EmitLDLOCA(GetCleanupWorkListLocalNum());
+    }
 }
 
 
@@ -2089,7 +2300,7 @@ void NDirectStubLinker::End(DWORD dwStubFlags)
     //
     // 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;
@@ -2126,7 +2337,7 @@ void NDirectStubLinker::End(DWORD dwStubFlags)
     //
     // 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();
@@ -2169,7 +2380,7 @@ void NDirectStubLinker::End(DWORD dwStubFlags)
     }
 
     // Reload the return value 
-    if ((m_dwRetValLocalNum != (DWORD)-1) && !hasTryCatchForHRESULT)
+    if ((m_dwRetValLocalNum != (DWORD)-1) && !hasTryCatchForHRESULT && !SF_IsStructMarshalStub(dwStubFlags))
     {
         pcs->EmitLDLOC(m_dwRetValLocalNum);
     }
@@ -2178,6 +2389,13 @@ void NDirectStubLinker::End(DWORD dwStubFlags)
 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
     {
 
@@ -2563,6 +2781,12 @@ public:
         LIMITED_METHOD_CONTRACT;
     }
 
+    void MarshalField(MarshalInfo* pInfo, UINT32 managedOffset, UINT32 nativeOffset, FieldDesc* pFieldDesc)
+    {
+        LIMITED_METHOD_CONTRACT;
+        UNREACHABLE();
+    }
+
 #ifdef FEATURE_COMINTEROP
     void MarshalHiddenLengthArgument(MarshalInfo *, BOOL)
     {
@@ -3428,7 +3652,8 @@ static MarshalInfo::MarshalType DoMarshalReturnValue(MetaSig&           msig,
                                 TRUE,
                                 isInstanceMethod,
                                 pMD,
-                                TRUE
+                                TRUE,
+                                FALSE
                                 DEBUG_ARG(pDebugName)
                                 DEBUG_ARG(pDebugClassName)
                                 DEBUG_ARG(0)
@@ -3660,8 +3885,6 @@ static void CreateNDirectStubWorker(StubState*         pss,
         CONSISTENCY_CHECK_MSGF(false, ("BreakOnInteropStubSetup: '%s' ", pSigDesc->m_pDebugName));
 #endif // _DEBUG
 
-    Stub* pstub = NULL;
-
     if (SF_IsCOMStub(dwStubFlags))
     {
         _ASSERTE(0 == nlType);
@@ -3820,7 +4043,8 @@ static void CreateNDirectStubWorker(StubState*         pss,
                                                  TRUE,
                                                  isInstanceMethod ? TRUE : FALSE,
                                                  pMD,
-                                                 TRUE
+                                                 TRUE,
+                                                 FALSE
                                                  DEBUG_ARG(pSigDesc->m_pDebugName)
                                                  DEBUG_ARG(pSigDesc->m_pDebugClassName)
                                                  DEBUG_ARG(i + 1));
@@ -4063,10 +4287,148 @@ static void CreateNDirectStubWorker(StubState*         pss,
     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
@@ -4165,6 +4527,7 @@ ILStubHashBlob* NDirect::CreateHashBlob(NDirectStubParameters* pParams)
         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);
@@ -4802,7 +5165,8 @@ MethodDesc* CreateInteropILStub(
                          DWORD              dwStubFlags,            // NDirectStubFlags
                          int                nParamTokens,
                          mdParamDef*        pParamTokenArray,
-                         int                iLCIDArg
+                         int                iLCIDArg,
+                         bool*              pGeneratedNewStub = nullptr
                            )
 {
     CONTRACT(MethodDesc*)
@@ -4826,6 +5190,7 @@ MethodDesc* CreateInteropILStub(
     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.
@@ -4864,7 +5229,8 @@ MethodDesc* CreateInteropILStub(
                                dwStubFlags,
                                nParamTokens,
                                pParamTokenArray,
-                               iLCIDArg
+                               iLCIDArg,
+                               pSigDesc->m_pMT
                                );
 
     // The following two ILStubCreatorHelperHolder are to recover the status when an
@@ -4911,6 +5277,9 @@ MethodDesc* CreateInteropILStub(
                 // 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 
@@ -4918,12 +5287,26 @@ MethodDesc* CreateInteropILStub(
 
                     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();
 
@@ -4934,12 +5317,27 @@ MethodDesc* CreateInteropILStub(
                             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();
                         }
                     }
@@ -4949,6 +5347,8 @@ MethodDesc* CreateInteropILStub(
                         // 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 
@@ -4994,15 +5394,23 @@ MethodDesc* CreateInteropILStub(
                             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());
 
@@ -5014,6 +5422,11 @@ MethodDesc* CreateInteropILStub(
                             sgh.SuppressRelease();
                         }
 
+                        if (pGeneratedNewStub)
+                        {
+                            *pGeneratedNewStub = true;
+                        }
+
                         pEntry->m_hrResultCode = S_OK;
                         break;
                     }
@@ -5130,8 +5543,6 @@ MethodDesc* NDirect::CreateCLRToNativeILStub(
                 pParamTokenArray,
                 iLCIDArg);
 
-
-
     RETURN pStubMD;
 }
 
@@ -5184,7 +5595,7 @@ MethodDesc* NDirect::CreateFieldAccessILStub(
     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();
@@ -5210,6 +5621,129 @@ MethodDesc* NDirect::CreateFieldAccessILStub(
 }
 #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)
@@ -6648,6 +7182,52 @@ VOID NDirect::NDirectLink(NDirectMethodDesc *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.
index ec413ad..0f1bbe9 100644 (file)
@@ -19,10 +19,13 @@ class LoadLibErrorTracker;
 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;
@@ -100,6 +103,9 @@ public:
                     FieldDesc*         pFD);
 #endif // FEATURE_COMINTEROP
 
+    static MethodDesc* CreateStructMarshalILStub(MethodTable* pMT);
+    static PCODE GetEntryPointForStructMarshalStub(MethodTable* pMT);
+
     static MethodDesc* CreateCLRToNativeILStub(PInvokeStaticSigInfo* pSigInfo,
                              DWORD dwStubFlags,
                              MethodDesc* pMD);
@@ -143,7 +149,7 @@ enum NDirectStubFlags
 #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
@@ -208,6 +214,7 @@ inline bool SF_IsDebuggableStub        (DWORD dwStubFlags) { LIMITED_METHOD_CONT
 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) || 
@@ -282,6 +289,11 @@ inline void SF_ConsistencyCheck(DWORD dwStubFlags)
 
     // 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
@@ -291,7 +303,8 @@ 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
 };
 
 //---------------------------------------------------------
@@ -571,7 +584,8 @@ public:
                           DWORD              dwStubFlags,  // NDirectStubFlags
                           int                nParamTokens,
                           mdParamDef*        pParamTokenArray,
-                          int                iLCIDArg
+                          int                iLCIDArg,
+                          MethodTable*       pMT
                           ) :
         m_sig(sig),
         m_pTypeContext(pTypeContext),
@@ -583,7 +597,8 @@ public:
         m_nlFlags(nlFlags),
         m_dwStubFlags(dwStubFlags),
         m_iLCIDArg(iLCIDArg),
-        m_nParamTokens(nParamTokens)
+        m_nParamTokens(nParamTokens),
+        m_pMT(pMT)
     {
         LIMITED_METHOD_CONTRACT;
     }
@@ -599,6 +614,7 @@ public:
     DWORD               m_dwStubFlags;
     int                 m_iLCIDArg;
     int                 m_nParamTokens;
+    MethodTable*        m_pMT;
 };
 
 PCODE GetILStubForCalli(VASigCookie *pVASigCookie, MethodDesc *pMD);
@@ -613,6 +629,9 @@ PCODE GetStubForInteropMethod(MethodDesc* pMD, DWORD dwStubFlags = 0, MethodDesc
 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
index 21b0ff8..215ed58 100644 (file)
@@ -936,15 +936,13 @@ FCFuncStart(gContextSynchronizationFuncs)
 #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)
@@ -1224,7 +1222,6 @@ FCClassElement("CompatibilitySwitch", "System.Runtime.Versioning", gCompatibilit
 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)
@@ -1257,6 +1254,7 @@ FCClassElement("MathF", "System", gMathFFuncs)
 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
@@ -1319,7 +1317,6 @@ FCClassElement("UriMarshaler", "System.StubHelpers", gUriMarshalerFuncs)
 #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)
index a3546c2..92b645e 100644 (file)
@@ -12720,7 +12720,7 @@ VOID DECLSPEC_NORETURN ThrowTypeLoadException(LPCWSTR pFullTypeName,
 // 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
 {
index cea16de..8ffd8ef 100644 (file)
@@ -592,7 +592,7 @@ VOID DECLSPEC_NORETURN ThrowTypeLoadException(LPCWSTR pFullTypeName,
                                               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);
 
index 7cb09bd..6dff529 100644 (file)
 #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, &param)
-        {
-            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);
 }
index 4e4c037..9ef147b 100644 (file)
@@ -5,15 +5,6 @@
 // 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__
@@ -24,9 +15,6 @@
 #include "olevariant.h"
 #include "nativefieldflags.h"
 
-#ifdef FEATURE_COMINTEROP
-#endif  // FEATURE_COMINTEROP
-
 #ifdef FEATURE_PREJIT
 #include "compile.h"
 #endif // FEATURE_PREJIT
@@ -36,53 +24,6 @@ class EEClassLayoutInfo;
 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.
 //
@@ -91,6 +32,17 @@ enum NStructFieldType : short
 //=======================================================================
 #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,
@@ -101,15 +53,11 @@ enum class ParseNativeTypeFlags : int
 };
 
 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,
@@ -118,2066 +66,163 @@ VOID ParseNativeType(Module*    pModule,
 #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__
index 90944ca..c590e43 100644 (file)
@@ -286,7 +286,6 @@ FRAME_TYPE_NAME(AssumeByrefFromJITStack)
 
 // Forward references
 class Frame;
-class FieldMarshaler;
 class FramedMethodFrame;
 typedef VPTR(class FramedMethodFrame) PTR_FramedMethodFrame;
 struct HijackArgs;
index d248208..051bde1 100644 (file)
@@ -99,14 +99,6 @@ EXTERN_C void SinglecastDelegateInvokeStub();
 #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
 //**********************************************************************
index 6c09fbb..5cbfd76 100644 (file)
@@ -142,7 +142,22 @@ void ILDelegateMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit
     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);
+    }
+
 }
 
 
@@ -530,7 +545,7 @@ void ILUTF8BufferMarshaler::EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit)
 
     // 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);
@@ -679,7 +694,7 @@ void ILWSTRBufferMarshaler::EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit)
 
     // 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);
@@ -880,7 +895,7 @@ void ILCSTRBufferMarshaler::EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit)
 
     // 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);
@@ -1072,12 +1087,14 @@ void ILValueClassMarshaler::EmitClearNative(ILCodeStream * pslILEmit)
 {
     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);
 }
 
 
@@ -1085,28 +1102,28 @@ void ILValueClassMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEm
 {
     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);
 }
 
 
@@ -1776,7 +1793,7 @@ void ILBSTRMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
 
     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);
@@ -1897,6 +1914,58 @@ void ILAnsiBSTRMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
     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()
@@ -2363,14 +2432,14 @@ void ILLayoutClassPtrMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* psl
     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);
 }
 
@@ -2383,11 +2452,14 @@ void ILLayoutClassPtrMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* psl
     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);
 }
 
@@ -2395,14 +2467,14 @@ void ILLayoutClassPtrMarshaler::EmitClearNativeContents(ILCodeStream * pslILEmit
 {
     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);
 }
 
 
@@ -2452,7 +2524,7 @@ void ILBlittablePtrMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslIL
 
 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)
@@ -2486,8 +2558,119 @@ void ILBlittablePtrMarshaler::EmitConvertSpaceAndContentsCLRToNativeTemp(ILCodeS
     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,
@@ -2554,6 +2737,40 @@ MarshalerOverrideStatus ILHandleRefMarshaler::ReturnOverride(NDirectStubLinker*
     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,
@@ -2884,6 +3101,32 @@ ILSafeHandleMarshaler::ReturnOverride(
     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);
+}
 
 //---------------------------------------------------------------------------------------
 // 
@@ -3695,8 +3938,17 @@ void ILNativeArrayMarshaler::EmitCreateMngdMarshaler(ILCodeStream* pslILEmit)
     }
 
     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()
@@ -4013,6 +4265,7 @@ void ILNativeArrayMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
     STANDARD_VM_CONTRACT;
 
     EmitLoadMngdMarshaler(pslILEmit);
+    EmitLoadManagedHomeAddr(pslILEmit);
     EmitLoadNativeHomeAddr(pslILEmit);
     EmitLoadNativeSize(pslILEmit);
     
@@ -4047,6 +4300,7 @@ void ILNativeArrayMarshaler::EmitClearNativeContents(ILCodeStream* pslILEmit)
     STANDARD_VM_CONTRACT;
 
     EmitLoadMngdMarshaler(pslILEmit);
+    EmitLoadManagedHomeAddr(pslILEmit);
     EmitLoadNativeHomeAddr(pslILEmit);
     EmitLoadNativeSize(pslILEmit);
    
@@ -4073,7 +4327,7 @@ void ILNativeArrayMarshaler::EmitNewSavedSizeArgLocal(ILCodeStream* 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;
 
@@ -4086,6 +4340,7 @@ FCIMPL3(void, MngdNativeArrayMarshaler::CreateMarshaler, MngdNativeArrayMarshale
     pThis->m_BestFitMap            = (BYTE)(dwFlags >> 16);
     pThis->m_ThrowOnUnmappableChar = (BYTE)(dwFlags >> 24);
     pThis->m_Array                 = TypeHandle();
+    pThis->m_pManagedMarshaler     = pManagedMarshaler;
 }
 FCIMPLEND
 
@@ -4148,7 +4403,7 @@ FCIMPL3(void, MngdNativeArrayMarshaler::ConvertContentsToNative, MngdNativeArray
         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();
@@ -4209,7 +4464,7 @@ FCIMPL3(void, MngdNativeArrayMarshaler::ConvertContentsToManaged, MngdNativeArra
         }
         else
         {
-            pMarshaler->OleToComArray(*pNativeHome, pArrayRef, pThis->m_pElementMT);
+            pMarshaler->OleToComArray(*pNativeHome, pArrayRef, pThis->m_pElementMT, pThis->m_pManagedMarshaler);
         }
     }
     
@@ -4217,7 +4472,7 @@ FCIMPL3(void, MngdNativeArrayMarshaler::ConvertContentsToManaged, MngdNativeArra
 }
 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;
 
@@ -4225,7 +4480,7 @@ FCIMPL3(void, MngdNativeArrayMarshaler::ClearNative, MngdNativeArrayMarshaler* p
     
     if (*pNativeHome != NULL)
     {
-        DoClearNativeContents(pThis, pNativeHome, cElements);
+        DoClearNativeContents(pThis, pManagedHome, pNativeHome, cElements);
         CoTaskMemFree(*pNativeHome);
     }
     
@@ -4233,19 +4488,19 @@ FCIMPL3(void, MngdNativeArrayMarshaler::ClearNative, MngdNativeArrayMarshaler* p
 }
 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
     {
@@ -4261,10 +4516,227 @@ void MngdNativeArrayMarshaler::DoClearNativeContents(MngdNativeArrayMarshaler* p
 
         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
 
@@ -4306,7 +4778,16 @@ void ILSafeArrayMarshaler::EmitCreateMngdMarshaler(ILCodeStream* pslILEmit)
     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)
@@ -4346,7 +4827,7 @@ void ILSafeArrayMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmi
 
 #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;
 
@@ -4355,6 +4836,7 @@ FCIMPL4(void, MngdSafeArrayMarshaler::CreateMarshaler, MngdSafeArrayMarshaler* p
     pThis->m_vt            = (VARTYPE)dwFlags;
     pThis->m_fStatic       = (BYTE)(dwFlags >> 16);
     pThis->m_nolowerbounds = (BYTE)(dwFlags >> 24);
+    pThis->m_pManagedMarshaler = pManagedMarshaler;
 }
 FCIMPLEND
 
@@ -4415,6 +4897,7 @@ FCIMPL4(void, MngdSafeArrayMarshaler::ConvertContentsToNative, MngdSafeArrayMars
                                                 (SAFEARRAY*)*pNativeHome,
                                                 pThis->m_vt,
                                                 pThis->m_pElementMT,
+                                                pThis->m_pManagedMarshaler,
                                                 (pThis->m_fStatic & SCSF_NativeDataValid));
     }
 
@@ -4499,6 +4982,7 @@ FCIMPL3(void, MngdSafeArrayMarshaler::ConvertContentsToManaged, MngdSafeArrayMar
         OleVariant::MarshalArrayRefForSafeArray((SAFEARRAY*)*pNativeHome,
                                                 (BASEARRAYREF *) pManagedHome,
                                                 pThis->m_vt,
+                                                pThis->m_pManagedMarshaler,
                                                 pThis->m_pElementMT);
     }
     
@@ -4562,7 +5046,16 @@ void ILHiddenLengthArrayMarshaler::EmitCreateMngdMarshaler(ILCodeStream* pslILEm
     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)
@@ -5016,13 +5509,14 @@ MethodDesc *ILHiddenLengthArrayMarshaler::GetExactMarshalerMethod(MethodDesc *pG
 
 #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
 
@@ -5122,7 +5616,8 @@ FCIMPL3(void, MngdHiddenLengthArrayMarshaler::ConvertContentsToNative, MngdHidde
                 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;
                 }
@@ -5243,15 +5738,15 @@ FCIMPL3(void, MngdHiddenLengthArrayMarshaler::ConvertContentsToManaged, MngdHidd
 
             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;
                 }
@@ -5299,7 +5794,7 @@ FCIMPL3(void, MngdHiddenLengthArrayMarshaler::ClearNativeContents, MngdHiddenLen
 
     if (*pNativeHome != NULL)
     {
-        pThis->DoClearNativeContents(pNativeHome, cElements);
+        pThis->DoClearNativeContents(pThis, pNativeHome, cElements);
     }
 
     HELPER_METHOD_FRAME_END();
@@ -5338,7 +5833,7 @@ SIZE_T MngdHiddenLengthArrayMarshaler::GetArraySize(SIZE_T elements)
 }
 
 #ifndef CROSSGEN_COMPILE
-void MngdHiddenLengthArrayMarshaler::DoClearNativeContents(void** pNativeHome, INT32 cElements)
+void MngdHiddenLengthArrayMarshaler::DoClearNativeContents(MngdHiddenLengthArrayMarshaler* pThis, void** pNativeHome, INT32 cElements)
 {
     CONTRACTL
     {
@@ -5376,14 +5871,13 @@ void MngdHiddenLengthArrayMarshaler::DoClearNativeContents(void** pNativeHome, I
 
         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;
         }
index db856bb..15ab12c 100644 (file)
@@ -25,7 +25,7 @@
 class ILStubMarshalHome
 {
 public:
-    typedef enum 
+    typedef enum : byte
     {
         HomeType_Unspecified     = 0,
         HomeType_ILLocal         = 1,
@@ -35,16 +35,33 @@ public:
     } 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)
@@ -61,6 +78,18 @@ public:
         {
             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");
@@ -105,6 +134,29 @@ public:
         {
             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");
@@ -152,6 +204,7 @@ public:
         else
         {
             pslILEmit->EmitLDARG(argidx);
+            EmitUnalignedPrefixIfNeeded(pslILEmit);
             pslILEmit->EmitLDIND_T(pManagedType);
             EmitStoreHome(pslILEmit);
         }
@@ -177,6 +230,7 @@ public:
         {
             pslILEmit->EmitLDARG(argidx);
             EmitLoadHome(pslILEmit);
+            EmitUnalignedPrefixIfNeeded(pslILEmit);
             pslILEmit->EmitSTIND_T(pManagedType);
         }
     }
@@ -305,6 +359,12 @@ protected:
         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;
@@ -375,6 +435,12 @@ public:
         return true;
     }
 
+    virtual bool SupportsFieldMarshal(UINT* pErrorResID)
+    {
+        LIMITED_METHOD_CONTRACT;
+        return true;
+    }
+
     // True if marshaling creates data that could need cleanup.
     bool NeedsMarshalCleanupIndex()
     {
@@ -389,6 +455,33 @@ public:
         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, 
@@ -815,7 +908,6 @@ public:
         }
     }        
 
-
 protected:
 
     virtual void EmitCreateMngdMarshaler(ILCodeStream* pslILEmit)
@@ -1104,6 +1196,50 @@ protected:
         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;
@@ -1540,9 +1676,24 @@ protected:
     {
         // 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:
@@ -1704,7 +1855,7 @@ 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) ||
@@ -2207,6 +2358,12 @@ public:
         return LocalDesc();
     }
 
+    virtual bool SupportsFieldMarshal(UINT* pErrorResID)
+    {
+        LIMITED_METHOD_CONTRACT;
+        return false;
+    }
+
     static MarshalerOverrideStatus ArgumentOverride(NDirectStubLinker* psl,
                                                     BOOL               byref,
                                                     BOOL               fin,
@@ -2237,15 +2394,18 @@ public:
     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,
@@ -2279,14 +2439,17 @@ public:
     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,
@@ -2305,7 +2468,6 @@ public:
                                                   UINT       *pResID);
 };
 
-
 class ILValueClassMarshaler : public ILMarshaler
 {
 public:
@@ -2437,6 +2599,12 @@ public:
         c_CLRSize               = sizeof(ELEMENT),
     };
 
+    bool SupportsFieldMarshal(UINT* pErrorResID) override
+    {
+        LIMITED_METHOD_CONTRACT;
+        return false;
+    }
+
 protected:
     LocalDesc GetNativeType() override
     {
@@ -2811,7 +2979,100 @@ protected:
     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
@@ -2837,13 +3098,13 @@ class ILLayoutClassPtrMarshaler : public ILLayoutClassPtrMarshalerBase
 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
@@ -2851,9 +3112,9 @@ class ILBlittablePtrMarshaler : public ILLayoutClassPtrMarshalerBase
 public:
     enum
     {
-        c_fInOnly               = FALSE,
+        c_fInOnly = FALSE,
     };
-            
+
 protected:
     void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override;
     void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override;
@@ -2862,6 +3123,62 @@ private:
     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:
@@ -2978,6 +3295,11 @@ protected:
         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
@@ -3183,6 +3505,11 @@ public:
     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);
@@ -3202,16 +3529,15 @@ private :
 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
@@ -3219,12 +3545,77 @@ public:
 
     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
@@ -3290,7 +3681,7 @@ protected:
 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);
@@ -3305,6 +3696,7 @@ public:
     };
 
     MethodTable*    m_pElementMT;
+    PCODE           m_pManagedMarshaler;
     int             m_iRank;
     VARTYPE         m_vt;
     BYTE            m_fStatic;     // StaticCheckStateFlags
@@ -3363,7 +3755,7 @@ private:
 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);
@@ -3373,12 +3765,13 @@ public:
 
 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
 
index a1b591f..64e4005 100644 (file)
@@ -208,6 +208,7 @@ MethodDesc* ILStubCache::CreateNewMethodDesc(LoaderHeap* pCreationHeap, MethodTa
     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))
@@ -267,6 +268,12 @@ MethodDesc* ILStubCache::CreateNewMethodDesc(LoaderHeap* pCreationHeap, MethodTa
     }
     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))
index 7f5964b..22f12b8 100644 (file)
@@ -77,6 +77,7 @@ LPCUTF8 ILStubResolver::GetStubMethodName()
         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
@@ -299,12 +300,30 @@ ILStubResolver::ILStubResolver() :
     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 * 
@@ -318,42 +337,62 @@ ILStubResolver::AllocGeneratedIL(
 #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();
@@ -398,6 +437,13 @@ COR_ILMETHOD_SECT_EH* ILStubResolver::AllocEHSect(size_t nClauses)
     }
 }
 
+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
@@ -414,7 +460,11 @@ void ILStubResolver::FreeCompileTimeState()
         return;
     }
 
-    ClearCompileTimeState(ILGeneratedAndFreed);
+    if (!UseLoaderHeap())
+    {
+        ClearCompileTimeState(ILGeneratedAndFreed);
+    }
+
 }
 
 //---------------------------------------------------------------------------------------
@@ -427,6 +477,7 @@ ILStubResolver::ClearCompileTimeState(CompileTimeStatePtrSpecialValues newState)
         NOTHROW;
         GC_NOTRIGGER;
         MODE_ANY;
+        PRECONDITION(!UseLoaderHeap());
     }
     CONTRACTL_END;
 
index 6f49398..f3bb180 100644 (file)
@@ -54,6 +54,8 @@ public:
     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);
@@ -68,6 +70,8 @@ public:
     void SetJitFlags(CORJIT_FLAGS jitFlags);
     CORJIT_FLAGS GetJitFlags();
 
+    void SetLoaderHeap(PTR_LoaderHeap pLoaderHeap);
+
     static void StubGenFailed(ILStubResolver* pResolver);
 
 protected:    
@@ -80,6 +84,7 @@ protected:
         NativeToCLRInteropStub,
         COMToCLRInteropStub,
         WinRTToCLRInteropStub,
+        StructMarshalInteropStub,
 #ifdef FEATURE_ARRAYSTUB_AS_IL 
         ArrayOpStub,
 #endif
@@ -101,6 +106,7 @@ protected:
 
     void ClearCompileTimeState(CompileTimeStatePtrSpecialValues newState);
     void SetStubType(ILStubType stubType);
+    bool UseLoaderHeap();
 
     //
     // This stuff is only needed during JIT
@@ -120,6 +126,7 @@ protected:
     PTR_MethodDesc          m_pStubTargetMD;
     ILStubType              m_type;
     CORJIT_FLAGS            m_jitFlags;
+    PTR_LoaderHeap          m_loaderHeap;
 };
 
 typedef Holder<ILStubResolver*, DoNothing<ILStubResolver*>, ILStubResolver::StubGenFailed, NULL> ILStubGenHolder;
index 349fb1b..2b8f9fc 100644 (file)
@@ -155,10 +155,19 @@ FCIMPL3(VOID, MarshalNative::StructureToPtr, Object* pObjUNSAFE, LPVOID ptr, CLR
     }
     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
     {
@@ -201,7 +210,14 @@ FCIMPL3(VOID, MarshalNative::PtrToStructureHelper, LPVOID ptr, Object* pObjIn, C
     }
     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
     {
@@ -243,7 +259,14 @@ FCIMPL2(VOID, MarshalNative::DestroyStructure, LPVOID ptr, ReflectClassBaseObjec
     }
     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
     {
@@ -362,16 +385,16 @@ FCIMPL1(UINT32, MarshalNative::OffsetOfHelper, ReflectFieldObject *pFieldUNSAFE)
         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");   
index 2c04b45..e034ccf 100644 (file)
@@ -205,7 +205,7 @@ DEFINE_METASIG(SM(IntPtr_IntPtr_RetVoid, I I, v))
 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))
@@ -216,8 +216,6 @@ DEFINE_METASIG(SM(RetIntPtr, _, I))
 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) ))
@@ -226,6 +224,7 @@ DEFINE_METASIG(SM(Byte_RetChar, b, u))
 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) ))
@@ -241,7 +240,7 @@ DEFINE_METASIG(SM(RefObj_RefIntPtr_RetVoid, r(j) r(I), v))
 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))
 
@@ -357,6 +356,7 @@ DEFINE_METASIG(SM(Str_RetInt, s, i))
 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))
 
index 526fd02..9dcd235 100644 (file)
@@ -2610,7 +2610,7 @@ protected:
         // 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,
@@ -2712,13 +2712,14 @@ public:
     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;
index e4b3253..ddf37e8 100644 (file)
@@ -2571,7 +2571,7 @@ bool MethodTable::ClassifyEightBytesWithNativeLayout(SystemVStructRegisterPassin
         return ClassifyEightBytesWithManagedLayout(helperPtr, nestingLevel, startOffsetOfStruct, useNativeLayout);
     }
 
-    const FieldMarshaler *pFieldMarshalers = GetLayoutInfo()->GetFieldMarshalers();
+    const NativeFieldDescriptor *pNativeFieldDescs = GetLayoutInfo()->GetNativeFieldDescriptors();
     UINT  numIntroducedFields = GetLayoutInfo()->GetNumCTMFields();
 
     // No fields.
@@ -2587,17 +2587,17 @@ bool MethodTable::ClassifyEightBytesWithNativeLayout(SystemVStructRegisterPassin
     // 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
@@ -2633,18 +2633,18 @@ bool MethodTable::ClassifyEightBytesWithNativeLayout(SystemVStructRegisterPassin
 
     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.
@@ -2653,12 +2653,12 @@ bool MethodTable::ClassifyEightBytesWithNativeLayout(SystemVStructRegisterPassin
             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;
         }
 
@@ -2681,7 +2681,7 @@ bool MethodTable::ClassifyEightBytesWithNativeLayout(SystemVStructRegisterPassin
         pField->GetName_NoThrow(&fieldName);
 #endif // _DEBUG
 
-        NativeFieldFlags nfc = pFieldMarshaler->GetNativeFieldFlags();
+        NativeFieldFlags nfc = pNFD->GetNativeFieldFlags();
 
 #ifdef FEATURE_COMINTEROP
         if (nfc & NATIVE_FIELD_SUBCATEGORY_COM_ONLY)
@@ -2693,11 +2693,10 @@ bool MethodTable::ClassifyEightBytesWithNativeLayout(SystemVStructRegisterPassin
 #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)
             {
@@ -2739,13 +2738,13 @@ bool MethodTable::ClassifyEightBytesWithNativeLayout(SystemVStructRegisterPassin
             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;
         }
 
@@ -5584,12 +5583,12 @@ void MethodTable::DoFullyLoad(Generics::RecursionGraph * const pVisited,  const
     // 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
@@ -5603,8 +5602,6 @@ void MethodTable::DoFullyLoad(Generics::RecursionGraph * const pVisited,  const
                 
                 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
index c032e63..b332530 100644 (file)
@@ -3724,10 +3724,10 @@ VOID    MethodTableBuilder::InitializeFieldDescs(FieldDesc *pFieldDescList,
     DWORD i;
     IMDInternalImport * pInternalImport = GetMDImport(); // to avoid multiple dereferencings
 
-    FieldMarshaler * pNextFieldMarshaler = NULL;
+    NativeFieldDescriptor * pNextNativeFieldDescriptor = NULL;
     if (HasLayout())
     {
-        pNextFieldMarshaler = (FieldMarshaler*)(GetLayoutInfo()->GetFieldMarshalers());
+        pNextNativeFieldDescriptor = GetLayoutInfo()->GetNativeFieldDescriptors();
     }
 
 
@@ -4189,14 +4189,14 @@ VOID    MethodTableBuilder::InitializeFieldDescs(FieldDesc *pFieldDescList,
                 {
                     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++;
index 0780960..4fd02a8 100644 (file)
@@ -488,7 +488,7 @@ BOOL ParseNativeTypeInfo(mdToken                    token,
     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);
@@ -794,6 +794,16 @@ VOID ThrowInteropParamException(UINT resID, UINT paramIdx)
     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:
 //
@@ -1413,7 +1423,8 @@ MarshalInfo::MarshalInfo(Module* pModule,
                          BOOL fEmitsIL,
                          BOOL onInstanceMethod,
                          MethodDesc* pMD,
-                         BOOL fLoadCustomMarshal
+                         BOOL fLoadCustomMarshal,
+                         BOOL fCalculatingFieldMetadata
 #ifdef _DEBUG
                          ,
                          LPCUTF8 pDebugName,
@@ -1442,14 +1453,14 @@ MarshalInfo::MarshalInfo(Module* pModule,
     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;
@@ -1584,58 +1595,59 @@ MarshalInfo::MarshalInfo(Module* pModule,
         }
 #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_
@@ -1670,6 +1682,12 @@ MarshalInfo::MarshalInfo(Module* pModule,
 
     if (nativeType == NATIVE_TYPE_CUSTOMMARSHALER)
     {
+        if (IsFieldScenario())
+        {
+            m_resID = IDS_EE_BADMARSHALFIELD_NOCUSTOMMARSH;
+            IfFailGoto(E_FAIL, lFail);
+        }
+
         switch (mtype)
         {
             case ELEMENT_TYPE_VAR:
@@ -1754,7 +1772,7 @@ MarshalInfo::MarshalInfo(Module* pModule,
                         // 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;
@@ -1763,7 +1781,7 @@ MarshalInfo::MarshalInfo(Module* pModule,
 #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;
@@ -1788,7 +1806,7 @@ MarshalInfo::MarshalInfo(Module* pModule,
                     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:
@@ -1842,11 +1860,11 @@ MarshalInfo::MarshalInfo(Module* pModule,
                 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;
@@ -1863,17 +1881,17 @@ MarshalInfo::MarshalInfo(Module* pModule,
                 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:
@@ -1904,7 +1922,11 @@ MarshalInfo::MarshalInfo(Module* pModule,
                 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:
@@ -1914,7 +1936,11 @@ MarshalInfo::MarshalInfo(Module* pModule,
                 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;
 
 
@@ -1946,7 +1972,11 @@ MarshalInfo::MarshalInfo(Module* pModule,
                 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:
@@ -1963,15 +1993,24 @@ MarshalInfo::MarshalInfo(Module* pModule,
                 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())
@@ -2019,13 +2058,13 @@ MarshalInfo::MarshalInfo(Module* pModule,
                 // 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))
@@ -2091,6 +2130,12 @@ MarshalInfo::MarshalInfo(Module* pModule,
                     || 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:
@@ -2108,7 +2153,7 @@ MarshalInfo::MarshalInfo(Module* pModule,
                         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. 
@@ -2174,12 +2219,28 @@ MarshalInfo::MarshalInfo(Module* pModule,
                             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)
                                 {
@@ -2189,9 +2250,8 @@ MarshalInfo::MarshalInfo(Module* pModule,
 
                                 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
@@ -2208,14 +2268,27 @@ MarshalInfo::MarshalInfo(Module* pModule,
                         }
     
                         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;
@@ -2277,14 +2350,14 @@ MarshalInfo::MarshalInfo(Module* pModule,
                     }
                     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;
@@ -2294,7 +2367,7 @@ MarshalInfo::MarshalInfo(Module* pModule,
                 {
                     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))
@@ -2313,7 +2386,7 @@ MarshalInfo::MarshalInfo(Module* pModule,
 
                         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;
                             }
@@ -2344,34 +2417,34 @@ MarshalInfo::MarshalInfo(Module* pModule,
                 }
                 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;
                 }
@@ -2382,12 +2455,17 @@ MarshalInfo::MarshalInfo(Module* pModule,
                     {
 #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;
@@ -2425,7 +2503,7 @@ MarshalInfo::MarshalInfo(Module* pModule,
                             break;
 
                         default:
-                            m_resID = IDS_EE_BADMARSHAL_OBJECT;
+                            m_resID = IsFieldScenario() ? IDS_EE_BADMARSHALFIELD_OBJECT : IDS_EE_BADMARSHAL_OBJECT;
                             IfFailGoto(E_FAIL, lFail);
                     }
                 }
@@ -2467,7 +2545,7 @@ MarshalInfo::MarshalInfo(Module* pModule,
                                 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;
                         }
 
@@ -2483,7 +2561,7 @@ MarshalInfo::MarshalInfo(Module* pModule,
                     _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;
                 }
@@ -2535,6 +2613,11 @@ MarshalInfo::MarshalInfo(Module* pModule,
                         break;
 
                     case NATIVE_TYPE_LPSTRUCT:
+                        if (IsFieldScenario())
+                        {
+                            m_resID = IDS_EE_BADMARSHALFIELD_DECIMAL;
+                            IfFailGoto(E_FAIL, lFail);
+                        }
                         m_type = MARSHAL_TYPE_DECIMAL_PTR;
                         break;
 
@@ -2543,7 +2626,7 @@ MarshalInfo::MarshalInfo(Module* pModule,
                         break;
 
                     default:
-                        m_resID = IDS_EE_BADMARSHALPARAM_DECIMAL;
+                        m_resID = IsFieldScenario() ? IDS_EE_BADMARSHALFIELD_DECIMAL : IDS_EE_BADMARSHALPARAM_DECIMAL;
                         IfFailGoto(E_FAIL, lFail);
                 }
             }
@@ -2557,6 +2640,11 @@ MarshalInfo::MarshalInfo(Module* pModule,
                         break;
 
                     case NATIVE_TYPE_LPSTRUCT:
+                        if (IsFieldScenario())
+                        {
+                            m_resID = IDS_EE_BADMARSHAL_GUID;
+                            IfFailGoto(E_FAIL, lFail);
+                        }
                         m_type = MARSHAL_TYPE_GUID_PTR;
                         break;
 
@@ -2588,6 +2676,10 @@ MarshalInfo::MarshalInfo(Module* pModule,
             }
             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);
@@ -2596,6 +2688,10 @@ MarshalInfo::MarshalInfo(Module* pModule,
             }
             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);
@@ -2604,6 +2700,10 @@ MarshalInfo::MarshalInfo(Module* pModule,
             }
             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);
@@ -2629,7 +2729,7 @@ MarshalInfo::MarshalInfo(Module* pModule,
 #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);
                 }
@@ -2638,7 +2738,7 @@ MarshalInfo::MarshalInfo(Module* pModule,
             }
             else if (sig.IsClassThrowing(pModule, g_RuntimeFieldHandleClassName, pTypeContext))
             {
-                if (nativeType != NATIVE_TYPE_DEFAULT)
+                if (nativeType != NATIVE_TYPE_DEFAULT || IsFieldScenario())
                 {
                     IfFailGoto(E_FAIL, lFail);
                 }
@@ -2647,7 +2747,7 @@ MarshalInfo::MarshalInfo(Module* pModule,
             }
             else if (sig.IsClassThrowing(pModule, g_RuntimeMethodHandleClassName, pTypeContext))
             {
-                if (nativeType != NATIVE_TYPE_DEFAULT)
+                if (nativeType != NATIVE_TYPE_DEFAULT || IsFieldScenario())
                 {
                     IfFailGoto(E_FAIL, lFail);
                 }
@@ -2656,13 +2756,18 @@ MarshalInfo::MarshalInfo(Module* pModule,
             }
             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))
                     {
@@ -2673,6 +2778,11 @@ MarshalInfo::MarshalInfo(Module* pModule,
 
                     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;
@@ -2710,7 +2820,7 @@ MarshalInfo::MarshalInfo(Module* pModule,
                         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;
@@ -2718,10 +2828,10 @@ MarshalInfo::MarshalInfo(Module* pModule,
                     }
                     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
@@ -2750,7 +2860,8 @@ MarshalInfo::MarshalInfo(Module* pModule,
                                  && 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;
@@ -2770,7 +2881,12 @@ MarshalInfo::MarshalInfo(Module* pModule,
                         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;
                 }
@@ -2782,7 +2898,12 @@ MarshalInfo::MarshalInfo(Module* pModule,
         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();
@@ -2996,7 +3117,7 @@ VOID MarshalInfo::EmitOrThrowInteropParamException(NDirectStubLinker* psl, BOOL
 #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;
@@ -3006,8 +3127,22 @@ VOID MarshalInfo::EmitOrThrowInteropParamException(NDirectStubLinker* psl, BOOL
     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
     {
@@ -3032,7 +3167,7 @@ HRESULT MarshalInfo::HandleArrayElemType(NativeTypeParamInfo *pParamInfo, TypeHa
     //
 
 #ifdef FEATURE_COMINTEROP
-    if (m_ms == MARSHAL_SCENARIO_WINRT)
+    if (IsWinRTScenario())
     {
         m_type = MARSHAL_TYPE_HIDDENLENGTHARRAY;
     }
@@ -3048,6 +3183,16 @@ HRESULT MarshalInfo::HandleArrayElemType(NativeTypeParamInfo *pParamInfo, TypeHa
     }
     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)
         {
@@ -3059,9 +3204,13 @@ HRESULT MarshalInfo::HandleArrayElemType(NativeTypeParamInfo *pParamInfo, TypeHa
             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;
     }
 
@@ -3076,6 +3225,11 @@ HRESULT MarshalInfo::HandleArrayElemType(NativeTypeParamInfo *pParamInfo, TypeHa
     }
     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);
@@ -3092,13 +3246,30 @@ HRESULT MarshalInfo::HandleArrayElemType(NativeTypeParamInfo *pParamInfo, TypeHa
     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)
@@ -3284,10 +3455,10 @@ void MarshalInfo::GenerateArgumentIL(NDirectStubLinker* psl,
 }
 
 void MarshalInfo::GenerateReturnIL(NDirectStubLinker* psl,
-                                   int argOffset,
-                                   BOOL fMngToNative,
-                                   BOOL fieldGetter,
-                                   BOOL retval)
+    int argOffset,
+    BOOL fMngToNative,
+    BOOL fieldGetter,
+    BOOL retval)
 {
     CONTRACTL
     {
@@ -3295,7 +3466,7 @@ void MarshalInfo::GenerateReturnIL(NDirectStubLinker* psl,
         PRECONDITION(CheckPointer(psl));
     }
     CONTRACTL_END;
-    
+
     MarshalerOverrideStatus amostat;
     UINT resID = IDS_EE_BADMARSHAL_RESTRICTION;
 
@@ -3306,10 +3477,10 @@ void MarshalInfo::GenerateReturnIL(NDirectStubLinker* psl,
     else
     {
         amostat = (GetReturnOverrideProc(m_type)) (psl,
-                                                   fMngToNative,
-                                                   retval,
-                                                   &m_args,
-                                                   &resID);
+            fMngToNative,
+            retval,
+            &m_args,
+            &resID);
     }
 
     if (amostat == DISALLOWED)
@@ -3317,7 +3488,7 @@ void MarshalInfo::GenerateReturnIL(NDirectStubLinker* psl,
         EmitOrThrowInteropParamException(psl, fMngToNative, resID, 0);
         return;
     }
-        
+
     if (amostat == HANDLEASNORMAL)
     {
         // Historically we have always allowed reading fields that are marshaled as C arrays.
@@ -3326,7 +3497,7 @@ void MarshalInfo::GenerateReturnIL(NDirectStubLinker* psl,
             EmitOrThrowInteropParamException(psl, fMngToNative, m_resID, 0);
             return;
         }
-    
+
         NewHolder<ILMarshaler> pMarshaler = CreateILMarshaler(m_type, psl);
         DWORD dwMarshalFlags = CalculateReturnMarshalFlags(retval, fMngToNative);
 
@@ -3336,14 +3507,14 @@ void MarshalInfo::GenerateReturnIL(NDirectStubLinker* psl,
             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
@@ -3361,37 +3532,49 @@ void MarshalInfo::GenerateReturnIL(NDirectStubLinker* psl,
     }
 }
 
-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
     {
@@ -3400,40 +3583,23 @@ UINT16 MarshalInfo::GetManagedSize(MarshalType mtype, MarshalScenario ms)
         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
     {
@@ -3717,7 +3883,7 @@ void MarshalInfo::GetItfMarshalInfo(TypeHandle th, TypeHandle thItf, BOOL fDispI
     // 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
@@ -4630,7 +4796,7 @@ CorElementType MarshalInfo::GetHiddenLengthParamElementType()
 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)
index d185517..96ecdf6 100644 (file)
@@ -56,6 +56,7 @@ enum MarshalFlags
     MARSHAL_FLAG_HRESULT_SWAP   = 0x10,
     MARSHAL_FLAG_RETVAL         = 0x20,
     MARSHAL_FLAG_HIDDENLENPARAM = 0x40,
+    MARSHAL_FLAG_FIELD          = 0x80
 };
 
 #include <pshpack1.h>
@@ -104,6 +105,10 @@ struct OverrideProcArgs
             void*       m_hndManagedType; // TypeHandle cannot be a union member
         } rcm;  // MARSHAL_TYPE_REFERENCECUSTOMMARSHALER
 
+        struct
+        {
+            UINT32 fixedStringLength;
+        } fs;
     };
 };
 
@@ -196,6 +201,10 @@ void VerifyAndAdjustNormalizedType(
                          CorElementType *           pManagedElemType,
                          CorNativeType *            pNativeType);
 
+#ifdef _DEBUG
+BOOL IsFixedBuffer(mdFieldDef field, IMDInternalImport* pInternalImport);
+#endif
+
 #ifdef FEATURE_COMINTEROP
 
 class EventArgsMarshalingInfo
@@ -430,6 +439,7 @@ public:
 #ifdef FEATURE_COMINTEROP
         MARSHAL_SCENARIO_COMINTEROP,
         MARSHAL_SCENARIO_WINRT,
+        MARSHAL_SCENARIO_WINRT_FIELD,
 #endif // FEATURE_COMINTEROP
         MARSHAL_SCENARIO_FIELD
     };
@@ -458,7 +468,8 @@ public:
                 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,
@@ -470,13 +481,16 @@ public:
 
     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
@@ -488,6 +502,17 @@ public:
                           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();
 
@@ -651,14 +676,23 @@ public:
     {
         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);
 
@@ -697,7 +731,6 @@ private:
 #endif // FEATURE_COMINTEROP
 
     UINT16          m_nativeArgSize;
-    UINT16          m_managedArgSize;
 
     MarshalScenario m_ms;
     BOOL            m_fAnsi;
@@ -727,6 +760,7 @@ private:
 #endif
 
     Module*         m_pModule;
+    mdToken         m_token;
 };
 
 
@@ -791,7 +825,11 @@ public:
         {
             // 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
         {
@@ -855,7 +893,11 @@ protected:
     {
         LIMITED_METHOD_CONTRACT;
 
-        return sizeof(LPVOID);
+#ifdef _TARGET_64BIT_
+            return 8;
+#else
+            return 4;
+#endif
     }
 
 protected:
index 339b3b9..49434fa 100644 (file)
@@ -690,6 +690,7 @@ DEFINE_METHOD(RUNTIME_HELPERS,      IS_REFERENCE_OR_CONTAINS_REFERENCES, IsRefer
 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)
@@ -882,6 +883,10 @@ DEFINE_METHOD(UNHANDLED_EVENTARGS,  CTOR,                   .ctor,
 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)
@@ -979,7 +984,7 @@ DEFINE_METHOD(STUBHELPERS,          CHECK_STRING_LENGTH,    CheckStringLength,
 
 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)
@@ -1025,13 +1030,13 @@ DEFINE_METHOD(ANSICHARMARSHALER,    DO_ANSI_CONVERSION,     DoAnsiConversion,
 
 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)
@@ -1066,7 +1071,7 @@ DEFINE_METHOD(INTERFACEMARSHALER,   CLEAR_NATIVE,           ClearNative,
 
 
 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)
@@ -1074,7 +1079,7 @@ DEFINE_METHOD(MNGD_SAFE_ARRAY_MARSHALER, CONVERT_CONTENTS_TO_MANAGED, ConvertCon
 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)
@@ -1120,11 +1125,6 @@ DEFINE_METHOD(HRESULTEXCEPTIONMARSHALER,  CONVERT_TO_MANAGED,    ConvertToManage
 
 #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)
@@ -1135,13 +1135,21 @@ DEFINE_METHOD(VBBYVALSTRMARSHALER,  CONVERT_TO_MANAGED,     ConvertToManaged,
 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)
@@ -1156,7 +1164,13 @@ DEFINE_METHOD(ASANY_MARSHALER,           CONVERT_TO_NATIVE,           ConvertToN
 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)
index 67cb806..47fbff8 100644 (file)
@@ -112,5 +112,11 @@ DEFINE_MARSHALER_TYPE(MARSHAL_TYPE_SYSTEMTYPE,                      SystemTypeMa
 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
index e1efd98..5520b99 100644 (file)
@@ -6,7 +6,7 @@
 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)
@@ -20,19 +20,19 @@ enum NativeFieldFlags : short
     // 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.
diff --git a/src/coreclr/src/vm/nsenums.h b/src/coreclr/src/vm/nsenums.h
deleted file mode 100644 (file)
index fbf4d1f..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-// 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.
index e7d11fe..3a9f68b 100644 (file)
@@ -17,6 +17,7 @@
 #include "olevariant.h"
 #include "comdatetime.h"
 #include "fieldmarshaler.h"
+#include "dllimport.h"
 
 /* ------------------------------------------------------------------------- *
  * Local constants
@@ -845,6 +846,8 @@ MethodTable* OleVariant::GetNativeMethodTableForVarType(VARTYPE vt, MethodTable*
             // 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;
@@ -1301,7 +1304,7 @@ void OleVariant::MarshalBoolVariantOleToCom(VARIANT *pOleVariant,
 #endif // FEATURE_COMINTEROP
 
 void OleVariant::MarshalBoolArrayOleToCom(void *oleArray, BASEARRAYREF *pComArray,
-                                          MethodTable *pInterfaceMT)
+                                          MethodTable *pInterfaceMT, PCODE pManagedMarshalerCode)
 {
     CONTRACTL
     {
@@ -1333,7 +1336,8 @@ void OleVariant::MarshalBoolArrayOleToCom(void *oleArray, BASEARRAYREF *pComArra
 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
     {
@@ -1391,7 +1395,7 @@ void OleVariant::MarshalWinBoolVariantOleRefToCom(VARIANT *pOleVariant,
 #endif // FEATURE_COMINTEROP
 
 void OleVariant::MarshalWinBoolArrayOleToCom(void *oleArray, BASEARRAYREF *pComArray,
-                                          MethodTable *pInterfaceMT)
+                                          MethodTable *pInterfaceMT, PCODE pManagedMarshalerCode)
 {
     CONTRACTL
     {
@@ -1423,7 +1427,8 @@ void OleVariant::MarshalWinBoolArrayOleToCom(void *oleArray, BASEARRAYREF *pComA
 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
     {
@@ -1478,7 +1483,7 @@ void OleVariant::MarshalCBoolVariantOleRefToCom(VARIANT* pOleVariant, VariantDat
 #endif // FEATURE_COMINTEROP
 
 void OleVariant::MarshalCBoolArrayOleToCom(void* oleArray, BASEARRAYREF* pComArray,
-                                        MethodTable* pInterfaceMT)
+                                        MethodTable* pInterfaceMT, PCODE pManagedMarshalerCode)
 {
     LIMITED_METHOD_CONTRACT;
       
@@ -1513,7 +1518,8 @@ void OleVariant::MarshalCBoolArrayOleToCom(void* oleArray, BASEARRAYREF* pComArr
 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;
       
@@ -1574,7 +1580,7 @@ void OleVariant::MarshalAnsiCharVariantOleRefToCom(VARIANT *pOleVariant,
 #endif // FEATURE_COMINTEROP
 
 void OleVariant::MarshalAnsiCharArrayOleToCom(void *oleArray, BASEARRAYREF *pComArray,
-                                          MethodTable *pInterfaceMT)
+                                          MethodTable *pInterfaceMT, PCODE pManagedMarshalerCode)
 {
     CONTRACTL
     {
@@ -1612,7 +1618,7 @@ void OleVariant::MarshalAnsiCharArrayOleToCom(void *oleArray, BASEARRAYREF *pCom
 void OleVariant::MarshalAnsiCharArrayComToOle(BASEARRAYREF *pComArray, void *oleArray,
                                           MethodTable *pInterfaceMT, BOOL fBestFitMapping,
                                           BOOL fThrowOnUnmappableChar, BOOL fOleArrayIsValid,
-                                          SIZE_T cElements)
+                                          SIZE_T cElements, PCODE pManagedMarshalerCode)
 {
     CONTRACTL
     {
@@ -1757,7 +1763,7 @@ void OleVariant::MarshalInterfaceVariantOleRefToCom(VARIANT *pOleVariant,
 }
 
 void OleVariant::MarshalInterfaceArrayOleToCom(void *oleArray, BASEARRAYREF *pComArray,
-                                               MethodTable *pElementMT)
+                                               MethodTable *pElementMT, PCODE pManagedMarshalerCode)
 {
     CONTRACTL
     {
@@ -1827,14 +1833,14 @@ void OleVariant::MarshalInterfaceArrayOleToCom(void *oleArray, BASEARRAYREF *pCo
 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
     {
@@ -1916,7 +1922,7 @@ void OleVariant::MarshalBSTRVariantComToOle(VariantData *pComVariant,
 }
 
 void OleVariant::MarshalBSTRArrayOleToCom(void *oleArray, BASEARRAYREF *pComArray,
-                                          MethodTable *pInterfaceMT)
+                                          MethodTable *pInterfaceMT, PCODE pManagedMarshalerCode)
 {
     CONTRACTL
     {
@@ -1969,7 +1975,7 @@ void OleVariant::MarshalBSTRArrayOleToCom(void *oleArray, BASEARRAYREF *pComArra
 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
     {
@@ -2008,7 +2014,7 @@ void OleVariant::MarshalBSTRArrayComToOle(BASEARRAYREF *pComArray, void *oleArra
     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
     {
@@ -2038,7 +2044,7 @@ void OleVariant::ClearBSTRArray(void *oleArray, SIZE_T cElements, MethodTable *p
  * Structure marshaling routines
  * ------------------------------------------------------------------------- */
 void OleVariant::MarshalNonBlittableRecordArrayOleToCom(void *oleArray, BASEARRAYREF *pComArray,
-                                                        MethodTable *pInterfaceMT)
+                                                        MethodTable *pInterfaceMT, PCODE pManagedMarshalerCode)
 {
     CONTRACTL
     {
@@ -2052,6 +2058,7 @@ void OleVariant::MarshalNonBlittableRecordArrayOleToCom(void *oleArray, BASEARRA
     CONTRACTL_END;
     
     ASSERT_PROTECTED(pComArray);
+
     SIZE_T elementCount = (*pComArray)->GetNumComponents();
     SIZE_T elemSize     = pInterfaceMT->GetNativeSize();
 
@@ -2061,7 +2068,10 @@ void OleVariant::MarshalNonBlittableRecordArrayOleToCom(void *oleArray, BASEARRA
     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;
     }
@@ -2070,7 +2080,7 @@ void OleVariant::MarshalNonBlittableRecordArrayOleToCom(void *oleArray, BASEARRA
 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
     {
@@ -2099,31 +2109,40 @@ void OleVariant::MarshalNonBlittableRecordArrayComToOle(BASEARRAYREF *pComArray,
     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();
     }
 }
 
@@ -2133,7 +2152,7 @@ void OleVariant::ClearNonBlittableRecordArray(void *oleArray, SIZE_T cElements,
  * ------------------------------------------------------------------------- */
 
 void OleVariant::MarshalLPWSTRArrayOleToCom(void *oleArray, BASEARRAYREF *pComArray,
-                                            MethodTable *pInterfaceMT)
+                                            MethodTable *pInterfaceMT, PCODE pManagedMarshalerCode)
 {
     CONTRACTL
     {
@@ -2185,7 +2204,7 @@ void OleVariant::MarshalLPWSTRArrayOleToCom(void *oleArray, BASEARRAYREF *pComAr
 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
     {
@@ -2241,7 +2260,7 @@ void OleVariant::MarshalLPWSTRRArrayComToOle(BASEARRAYREF *pComArray, void *oleA
     }
 }
 
-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
     {
@@ -2269,7 +2288,7 @@ void OleVariant::ClearLPWSTRArray(void *oleArray, SIZE_T cElements, MethodTable
  * ------------------------------------------------------------------------- */
 
 void OleVariant::MarshalLPSTRArrayOleToCom(void *oleArray, BASEARRAYREF *pComArray,
-                                           MethodTable *pInterfaceMT)
+                                           MethodTable *pInterfaceMT, PCODE pManagedMarshalerCode)
 {
     CONTRACTL
     {
@@ -2321,7 +2340,7 @@ void OleVariant::MarshalLPSTRArrayOleToCom(void *oleArray, BASEARRAYREF *pComArr
 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
     {
@@ -2378,7 +2397,7 @@ void OleVariant::MarshalLPSTRRArrayComToOle(BASEARRAYREF *pComArray, void *oleAr
     }
 }
 
-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
     {
@@ -2432,7 +2451,7 @@ void OleVariant::MarshalDateVariantOleRefToCom(VARIANT *pOleVariant,
 #endif // FEATURE_COMINTEROP
 
 void OleVariant::MarshalDateArrayOleToCom(void *oleArray, BASEARRAYREF *pComArray,
-                                          MethodTable *pInterfaceMT)
+                                          MethodTable *pInterfaceMT, PCODE pManagedMarshalerCode)
 {
     CONTRACTL
     {
@@ -2465,7 +2484,7 @@ void OleVariant::MarshalDateArrayOleToCom(void *oleArray, BASEARRAYREF *pComArra
 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
     {
@@ -2611,7 +2630,15 @@ void OleVariant::MarshalRecordVariantOleToCom(VARIANT *pOleVariant,
             // 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);
@@ -2653,7 +2680,7 @@ void OleVariant::MarshalRecordVariantOleRefToCom(VARIANT *pOleVariant,
 #endif // FEATURE_CLASSIC_COMINTEROP
 
 void OleVariant::MarshalRecordArrayOleToCom(void *oleArray, BASEARRAYREF *pComArray,
-                                            MethodTable *pElementMT)
+                                            MethodTable *pElementMT, PCODE pManagedMarshalerCode)
 {
     CONTRACTL
     {
@@ -2678,14 +2705,14 @@ void OleVariant::MarshalRecordArrayOleToCom(void *oleArray, BASEARRAYREF *pComAr
     {
         // 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
     {
@@ -2709,16 +2736,16 @@ void OleVariant::MarshalRecordArrayComToOle(BASEARRAYREF *pComArray, void *oleAr
     {
         // 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));
@@ -2729,7 +2756,7 @@ void OleVariant::ClearRecordArray(void *oleArray, SIZE_T cElements, MethodTable
     if (!pElementMT->IsBlittable())
     {
         _ASSERTE(pElementMT->HasLayout());
-        ClearNonBlittableRecordArray(oleArray, cElements, pElementMT);
+        ClearNonBlittableRecordArray(pComArray, oleArray, cElements, pElementMT, pManagedMarshalerCode);
     }
 }
 
@@ -3774,7 +3801,7 @@ HRESULT OleVariant::ClearAndInsertContentsIntoByrefRecordVariant(VARIANT* pOle,
 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;
     
@@ -3860,7 +3887,7 @@ void OleVariant::MarshalCurrencyVariantOleRefToCom(VARIANT *pOleVariant,
 }
 
 void OleVariant::MarshalCurrencyArrayOleToCom(void *oleArray, BASEARRAYREF *pComArray,
-                                              MethodTable *pInterfaceMT)
+                                              MethodTable *pInterfaceMT, PCODE pManagedMarshalerCode)
 {
     CONTRACTL
     {
@@ -3889,7 +3916,7 @@ void OleVariant::MarshalCurrencyArrayOleToCom(void *oleArray, BASEARRAYREF *pCom
 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
     {
@@ -3918,7 +3945,7 @@ void OleVariant::MarshalCurrencyArrayComToOle(BASEARRAYREF *pComArray, void *ole
  * ------------------------------------------------------------------------- */
 
 void OleVariant::MarshalVariantArrayOleToCom(void *oleArray, BASEARRAYREF *pComArray,
-                                             MethodTable *pInterfaceMT)
+                                             MethodTable *pInterfaceMT, PCODE pManagedMarshalerCode)
 {
     CONTRACTL
     {
@@ -3966,7 +3993,7 @@ void OleVariant::MarshalVariantArrayOleToCom(void *oleArray, BASEARRAYREF *pComA
 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
     {
@@ -4050,7 +4077,7 @@ void OleVariant::MarshalVariantArrayComToOle(BASEARRAYREF *pComArray, void *oleA
     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
     {
@@ -4100,9 +4127,17 @@ void OleVariant::MarshalArrayVariantOleToCom(VARIANT *pOleVariant,
         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
     {
@@ -4135,10 +4170,20 @@ void OleVariant::MarshalArrayVariantComToOle(VariantData *pComVariant,
 
     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();
@@ -4167,9 +4212,17 @@ void OleVariant::MarshalArrayVariantOleRefToCom(VARIANT *pOleVariant,
         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
     {
@@ -4520,6 +4573,7 @@ void OleVariant::MarshalSafeArrayForArrayRef(BASEARRAYREF *pArrayRef,
                                              SAFEARRAY *pSafeArray,
                                              VARTYPE vt,
                                              MethodTable *pInterfaceMT,
+                                             PCODE pManagedMarshalerCode,
                                              BOOL fSafeArrayIsValid /*= TRUE*/)
 {        
     CONTRACTL
@@ -4584,7 +4638,7 @@ void OleVariant::MarshalSafeArrayForArrayRef(BASEARRAYREF *pArrayRef,
                     // 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)
@@ -4605,6 +4659,7 @@ void OleVariant::MarshalSafeArrayForArrayRef(BASEARRAYREF *pArrayRef,
 void OleVariant::MarshalArrayRefForSafeArray(SAFEARRAY *pSafeArray, 
                                              BASEARRAYREF *pArrayRef,
                                              VARTYPE vt,
+                                             PCODE pManagedMarshalerCode,
                                              MethodTable *pInterfaceMT)
 {        
     CONTRACTL
@@ -4674,7 +4729,7 @@ void OleVariant::MarshalArrayRefForSafeArray(SAFEARRAY *pSafeArray,
 
         PinningHandleHolder handle = GetAppDomain()->CreatePinningHandle((OBJECTREF)*pArrayRef);
 
-        marshal->OleToComArray(pSrcData, pArrayRef, pInterfaceMT);
+        marshal->OleToComArray(pSrcData, pArrayRef, pInterfaceMT, pManagedMarshalerCode);
     }
 }
 
@@ -4716,12 +4771,21 @@ void OleVariant::ConvertValueClassToVariant(OBJECTREF *pBoxedValueClass, VARIANT
             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();
 }
index 2058364..44eeef9 100644 (file)
@@ -383,11 +383,13 @@ class OleVariant
                                             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.
@@ -455,11 +457,12 @@ class OleVariant
         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);
@@ -475,99 +478,103 @@ private:
     // 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);
 
@@ -604,19 +611,19 @@ private:
     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);
index ed9dc8a..0027147 100644 (file)
@@ -1423,8 +1423,14 @@ void ILCodeStream::EmitLDIND_T(LocalDesc* pType)
 
         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;
         }
 
@@ -1630,8 +1636,14 @@ void ILCodeStream::EmitSTIND_T(LocalDesc* pType)
 
         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;
         }
 
@@ -1671,6 +1683,12 @@ void ILCodeStream::EmitTHROW()
     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)
 {
@@ -2956,4 +2974,4 @@ void ILCodeStream::ClearCode()
 {
     LIMITED_METHOD_CONTRACT;
     m_uCurInstrIdx = 0;
-}
\ No newline at end of file
+}
index 329bf66..bffe5fa 100644 (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;
@@ -80,10 +95,16 @@ struct LocalDesc
     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;
@@ -682,6 +703,7 @@ public:
     void EmitSTSFLD     (int token);
     void EmitSUB        ();
     void EmitTHROW      ();
+    void EmitUNALIGNED  (BYTE alignment);
 
     // Overloads to simplify common usage patterns
     void EmitNEWOBJ     (BinderMethodID id, int numInArgs);
index 328771c..9ecad9d 100644 (file)
@@ -180,60 +180,6 @@ void StubHelpers::ProcessByrefValidationList()
 
 #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()
@@ -1518,7 +1464,23 @@ FCIMPL3(void, StubHelpers::FmtClassUpdateNativeInternal, Object* pObjUNSAFE, BYT
     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();
 }
@@ -1531,18 +1493,48 @@ FCIMPL2(void, StubHelpers::FmtClassUpdateCLRInternal, Object* pObjUNSAFE, BYTE*
     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
index ae22858..3ecc245 100644 (file)
@@ -46,13 +46,6 @@ public:
     // 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);
@@ -98,7 +91,7 @@ public:
 
     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);
index 3185040..e7980b7 100644 (file)
@@ -72,3 +72,7 @@ extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE SimpleNestedLayoutClassByValue(Nest
 {
     return SimpleSeqLayoutClassByRef(&v.str);
 }
+
+extern "C" DLL_EXPORT void __cdecl Invalid(...)
+{
+}
index 49984d5..63b52de 100644 (file)
@@ -84,6 +84,18 @@ namespace PInvokeTests
         public SeqClass value;
     }
 
+
+    [StructLayout(LayoutKind.Sequential)]
+    public class RecursiveTestClass
+    {
+        public RecursiveTestStruct s;
+    }
+
+    public struct RecursiveTestStruct
+    {
+        public RecursiveTestClass c;
+    }
+
     class StructureTests
     {
         [DllImport("LayoutClassNative")]
@@ -98,6 +110,9 @@ namespace PInvokeTests
         [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";
@@ -210,6 +225,22 @@ namespace PInvokeTests
             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;
@@ -218,6 +249,7 @@ namespace PInvokeTests
             retVal = retVal && ExplicitClass();
             retVal = retVal && BlittableClass();
             retVal = retVal && NestedLayoutClass();
+            retVal = retVal && RecursiveNativeLayout();
 
             return (retVal ? 100 : 101);
         }