Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 549d532

Browse files
authored
Implement struct marshalling via IL Stubs instead of via Field… (#26340)
* 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 e73b78a. 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 1d8e56e. Revert "Fix initialization of stubMethodInfoCache lock owner." This reverts commit a095390. Revert "Cache Sytem.RuntimeMethodInfoStub instances created in the VM in the MethodDesc's owning LoaderAllocator." This reverts commit 7266538. 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.
1 parent 0a048b8 commit 549d532

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+3283
-6566
lines changed

src/System.Private.CoreLib/Resources/Strings.resx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2401,6 +2401,15 @@
24012401
<data name="Interop_Marshal_Unmappable_Char" xml:space="preserve">
24022402
<value>Cannot marshal: Encountered unmappable character.</value>
24032403
</data>
2404+
<data name="Interop_Marshal_SafeHandle_InvalidOperation" xml:space="preserve">
2405+
<value>Structures containing SafeHandle fields are not allowed in this operation.</value>
2406+
</data>
2407+
<data name="Interop_Marshal_CannotCreateSafeHandleField" xml:space="preserve">
2408+
<value>SafeHandle fields cannot be created from an unmanaged handle.</value>
2409+
</data>
2410+
<data name="Interop_Marshal_CannotCreateCriticalHandleField" xml:space="preserve">
2411+
<value>CriticalHandle fields cannot be created from an unmanaged handle.</value>
2412+
</data>
24042413
<data name="InvalidCast_CannotCastNullToValueType" xml:space="preserve">
24052414
<value>Null object cannot be converted to a value type.</value>
24062415
</data>

src/System.Private.CoreLib/src/System/StubHelpers.cs

Lines changed: 152 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,75 @@ internal static void ClearNative(IntPtr pNative)
121121
{
122122
Interop.Ole32.CoTaskMemFree(pNative);
123123
}
124+
125+
internal static unsafe void ConvertFixedToNative(int flags, string strManaged, IntPtr pNativeBuffer, int length)
126+
{
127+
int numChars = strManaged.Length;
128+
if (numChars >= length)
129+
{
130+
numChars = length - 1;
131+
}
132+
133+
byte* buffer = (byte*)pNativeBuffer;
134+
135+
// Flags defined in ILFixedCSTRMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit).
136+
bool throwOnUnmappableChar = 0 != (flags >> 8);
137+
bool bestFit = 0 != (flags & 0xFF);
138+
uint defaultCharUsed = 0;
139+
140+
int cbWritten;
141+
142+
fixed (char* pwzChar = strManaged)
143+
{
144+
#if PLATFORM_WINDOWS
145+
cbWritten = Interop.Kernel32.WideCharToMultiByte(
146+
Interop.Kernel32.CP_ACP,
147+
bestFit ? 0 : Interop.Kernel32.WC_NO_BEST_FIT_CHARS,
148+
pwzChar,
149+
numChars,
150+
buffer,
151+
length,
152+
IntPtr.Zero,
153+
throwOnUnmappableChar ? new IntPtr(&defaultCharUsed) : IntPtr.Zero);
154+
#else
155+
cbWritten = Encoding.UTF8.GetBytes(pwzChar, numChars, buffer, length);
156+
#endif
157+
}
158+
159+
if (defaultCharUsed != 0)
160+
{
161+
throw new ArgumentException(SR.Interop_Marshal_Unmappable_Char);
162+
}
163+
164+
if (cbWritten == (int)length)
165+
{
166+
cbWritten--;
167+
}
168+
169+
buffer[cbWritten] = 0;
170+
}
171+
172+
internal static unsafe string ConvertFixedToManaged(IntPtr cstr, int length)
173+
{
174+
int allocSize = length + 2;
175+
if (allocSize < length)
176+
{
177+
throw new OutOfMemoryException();
178+
}
179+
Span<sbyte> originalBuffer = new Span<sbyte>((byte*)cstr, length);
180+
181+
Span<sbyte> tempBuf = stackalloc sbyte[allocSize];
182+
183+
originalBuffer.CopyTo(tempBuf);
184+
tempBuf[length - 1] = 0;
185+
tempBuf[length] = 0;
186+
tempBuf[length + 1] = 0;
187+
188+
fixed (sbyte* buffer = tempBuf)
189+
{
190+
return new string(buffer, 0, string.strlen((byte*)buffer));
191+
}
192+
}
124193
} // class CSTRMarshaler
125194

126195
internal static class UTF8Marshaler
@@ -443,23 +512,17 @@ internal static void ClearNative(IntPtr pNative)
443512
}
444513
} // class AnsiBSTRMarshaler
445514

446-
internal static class WSTRBufferMarshaler
515+
internal static class FixedWSTRMarshaler
447516
{
448-
internal static IntPtr ConvertToNative(string strManaged)
517+
internal static unsafe void ConvertToNative(string? strManaged, IntPtr nativeHome, int length)
449518
{
450-
Debug.Fail("NYI");
451-
return IntPtr.Zero;
452-
}
519+
ReadOnlySpan<char> managed = strManaged;
520+
Span<char> native = new Span<char>((char*)nativeHome, length);
453521

454-
internal static string? ConvertToManaged(IntPtr bstr)
455-
{
456-
Debug.Fail("NYI");
457-
return null;
458-
}
522+
int numChars = Math.Min(managed.Length, length - 1);
459523

460-
internal static void ClearNative(IntPtr pNative)
461-
{
462-
Debug.Fail("NYI");
524+
managed.Slice(0, numChars).CopyTo(native);
525+
native[numChars] = '\0';
463526
}
464527
} // class WSTRBufferMarshaler
465528

@@ -573,26 +636,45 @@ internal static class ObjectMarshaler
573636

574637
#endif // FEATURE_COMINTEROP
575638

576-
internal static class ValueClassMarshaler
639+
internal sealed class HandleMarshaler
577640
{
578-
[MethodImpl(MethodImplOptions.InternalCall)]
579-
internal static extern void ConvertToNative(IntPtr dst, IntPtr src, IntPtr pMT, ref CleanupWorkListElement pCleanupWorkList);
641+
internal static unsafe IntPtr ConvertSafeHandleToNative(SafeHandle? handle, bool hasCleanupWorkList, ref CleanupWorkListElement? cleanupWorkList)
642+
{
643+
if (!hasCleanupWorkList)
644+
{
645+
throw new InvalidOperationException(SR.Interop_Marshal_SafeHandle_InvalidOperation);
646+
}
580647

581-
[MethodImpl(MethodImplOptions.InternalCall)]
582-
internal static extern void ConvertToManaged(IntPtr dst, IntPtr src, IntPtr pMT);
648+
if (handle is null)
649+
{
650+
throw new ArgumentNullException(nameof(handle));
651+
}
583652

584-
[MethodImpl(MethodImplOptions.InternalCall)]
585-
internal static extern void ClearNative(IntPtr dst, IntPtr pMT);
586-
} // class ValueClassMarshaler
653+
return StubHelpers.AddToCleanupList(ref cleanupWorkList, handle);
654+
}
655+
656+
internal static unsafe void ThrowSafeHandleFieldChanged()
657+
{
658+
throw new NotSupportedException(SR.Interop_Marshal_CannotCreateSafeHandleField);
659+
}
660+
661+
internal static unsafe void ThrowCriticalHandleFieldChanged()
662+
{
663+
throw new NotSupportedException(SR.Interop_Marshal_CannotCreateCriticalHandleField);
664+
}
665+
}
587666

588667
internal static class DateMarshaler
589668
{
590-
[MethodImpl(MethodImplOptions.InternalCall)]
591-
internal static extern double ConvertToNative(DateTime managedDate);
669+
internal static double ConvertToNative(DateTime managedDate)
670+
{
671+
return managedDate.ToOADate();
672+
}
592673

593-
// The return type is really DateTime but we use long to avoid the pain associated with returning structures.
594-
[MethodImpl(MethodImplOptions.InternalCall)]
595-
internal static extern long ConvertToManaged(double nativeDate);
674+
internal static long ConvertToManaged(double nativeDate)
675+
{
676+
return DateTime.DoubleDateToTicks(nativeDate);
677+
}
596678
} // class DateMarshaler
597679

598680
#if FEATURE_COMINTEROP
@@ -640,6 +722,7 @@ internal struct MarshalerState
640722
#pragma warning disable CA1823 // not used by managed code
641723
private IntPtr m_pElementMT;
642724
private IntPtr m_Array;
725+
private IntPtr m_pManagedNativeArrayMarshaler;
643726
private int m_NativeDataValid;
644727
private int m_BestFitMap;
645728
private int m_ThrowOnUnmappableChar;
@@ -648,7 +731,7 @@ internal struct MarshalerState
648731
}
649732

650733
[MethodImpl(MethodImplOptions.InternalCall)]
651-
internal static extern void CreateMarshaler(IntPtr pMarshalState, IntPtr pMT, int dwFlags);
734+
internal static extern void CreateMarshaler(IntPtr pMarshalState, IntPtr pMT, int dwFlags, IntPtr pManagedMarshaler);
652735

653736
[MethodImpl(MethodImplOptions.InternalCall)]
654737
internal static extern void ConvertSpaceToNative(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
@@ -664,17 +747,38 @@ internal static extern void ConvertSpaceToManaged(IntPtr pMarshalState, ref obje
664747
internal static extern void ConvertContentsToManaged(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
665748

666749
[MethodImpl(MethodImplOptions.InternalCall)]
667-
internal static extern void ClearNative(IntPtr pMarshalState, IntPtr pNativeHome, int cElements);
750+
internal static extern void ClearNative(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome, int cElements);
668751

669752
[MethodImpl(MethodImplOptions.InternalCall)]
670-
internal static extern void ClearNativeContents(IntPtr pMarshalState, IntPtr pNativeHome, int cElements);
753+
internal static extern void ClearNativeContents(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome, int cElements);
671754
} // class MngdNativeArrayMarshaler
672755

756+
internal static class MngdFixedArrayMarshaler
757+
{
758+
[MethodImpl(MethodImplOptions.InternalCall)]
759+
internal static extern void CreateMarshaler(IntPtr pMarshalState, IntPtr pMT, int dwFlags, int cElements, IntPtr pManagedMarshaler);
760+
761+
[MethodImpl(MethodImplOptions.InternalCall)]
762+
internal static extern void ConvertSpaceToNative(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
763+
764+
[MethodImpl(MethodImplOptions.InternalCall)]
765+
internal static extern void ConvertContentsToNative(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
766+
767+
[MethodImpl(MethodImplOptions.InternalCall)]
768+
internal static extern void ConvertSpaceToManaged(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
769+
770+
[MethodImpl(MethodImplOptions.InternalCall)]
771+
internal static extern void ConvertContentsToManaged(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
772+
773+
[MethodImpl(MethodImplOptions.InternalCall)]
774+
internal static extern void ClearNativeContents(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
775+
} // class MngdFixedArrayMarshaler
776+
673777
#if FEATURE_COMINTEROP
674778
internal static class MngdSafeArrayMarshaler
675779
{
676780
[MethodImpl(MethodImplOptions.InternalCall)]
677-
internal static extern void CreateMarshaler(IntPtr pMarshalState, IntPtr pMT, int iRank, int dwFlags);
781+
internal static extern void CreateMarshaler(IntPtr pMarshalState, IntPtr pMT, int iRank, int dwFlags, IntPtr pManagedMarshaler);
678782

679783
[MethodImpl(MethodImplOptions.InternalCall)]
680784
internal static extern void ConvertSpaceToNative(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
@@ -695,7 +799,7 @@ internal static class MngdSafeArrayMarshaler
695799
internal static class MngdHiddenLengthArrayMarshaler
696800
{
697801
[MethodImpl(MethodImplOptions.InternalCall)]
698-
internal static extern void CreateMarshaler(IntPtr pMarshalState, IntPtr pMT, IntPtr cbElementSize, ushort vt);
802+
internal static extern void CreateMarshaler(IntPtr pMarshalState, IntPtr pMT, IntPtr cbElementSize, ushort vt, IntPtr pManagedMarshaler);
699803

700804
[MethodImpl(MethodImplOptions.InternalCall)]
701805
internal static extern void ConvertSpaceToNative(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
@@ -971,7 +1075,8 @@ private unsafe IntPtr ConvertArrayToNative(object pManagedHome, int dwFlags)
9711075
MngdNativeArrayMarshaler.CreateMarshaler(
9721076
pvArrayMarshaler,
9731077
IntPtr.Zero, // not needed as we marshal primitive VTs only
974-
dwArrayMarshalerFlags);
1078+
dwArrayMarshalerFlags,
1079+
IntPtr.Zero); // not needed as we marshal primitive VTs only
9751080

9761081
IntPtr pNativeHome;
9771082
IntPtr pNativeHomeAddr = new IntPtr(&pNativeHome);
@@ -1460,6 +1565,17 @@ internal struct NativeVariant
14601565
#endif
14611566
} // struct NativeVariant
14621567

1568+
// This NativeDecimal type is very similar to the System.Decimal type, except it requires an 8-byte alignment
1569+
// like the native DECIMAL type instead of the 4-byte requirement of the System.Decimal type.
1570+
[StructLayout(LayoutKind.Sequential)]
1571+
internal struct NativeDecimal
1572+
{
1573+
private ushort reserved;
1574+
private ushort signScale;
1575+
private uint hi32;
1576+
private ulong lo64;
1577+
}
1578+
14631579
internal abstract class CleanupWorkListElement
14641580
{
14651581
private CleanupWorkListElement? m_Next;
@@ -1476,7 +1592,7 @@ public void Destroy()
14761592
}
14771593
}
14781594

1479-
public static void AddToCleanupList(ref CleanupWorkListElement list, CleanupWorkListElement newElement)
1595+
public static void AddToCleanupList(ref CleanupWorkListElement? list, CleanupWorkListElement newElement)
14801596
{
14811597
if (list == null)
14821598
{
@@ -1560,14 +1676,14 @@ internal static class StubHelpers
15601676
[MethodImpl(MethodImplOptions.InternalCall)]
15611677
internal static extern void ThrowInteropParamException(int resID, int paramIdx);
15621678

1563-
internal static IntPtr AddToCleanupList(ref CleanupWorkListElement pCleanupWorkList, SafeHandle handle)
1679+
internal static IntPtr AddToCleanupList(ref CleanupWorkListElement? pCleanupWorkList, SafeHandle handle)
15641680
{
15651681
SafeHandleCleanupWorkListElement element = new SafeHandleCleanupWorkListElement(handle);
15661682
CleanupWorkListElement.AddToCleanupList(ref pCleanupWorkList, element);
15671683
return element.AddRef();
15681684
}
15691685

1570-
internal static void KeepAliveViaCleanupList(ref CleanupWorkListElement pCleanupWorkList, object obj)
1686+
internal static void KeepAliveViaCleanupList(ref CleanupWorkListElement? pCleanupWorkList, object obj)
15711687
{
15721688
KeepAliveCleanupWorkListElement element = new KeepAliveCleanupWorkListElement(obj);
15731689
CleanupWorkListElement.AddToCleanupList(ref pCleanupWorkList, element);
@@ -1713,7 +1829,7 @@ internal static void CheckStringLength(uint length)
17131829
[MethodImpl(MethodImplOptions.InternalCall)]
17141830
internal static extern unsafe void FmtClassUpdateCLRInternal(object obj, byte* pNative);
17151831
[MethodImpl(MethodImplOptions.InternalCall)]
1716-
internal static extern unsafe void LayoutDestroyNativeInternal(byte* pNative, IntPtr pMT);
1832+
internal static extern unsafe void LayoutDestroyNativeInternal(object obj, byte* pNative);
17171833
[MethodImpl(MethodImplOptions.InternalCall)]
17181834
internal static extern object AllocateInternal(IntPtr typeHandle);
17191835

src/debug/daccess/nidump.cpp

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
#include <comcallablewrapper.h>
1616
#include <gcdump.h>
17+
#include <fieldmarshaler.h>
1718

1819
#if !defined(FEATURE_CORESYSTEM)
1920
#include <algorithm>
@@ -8383,36 +8384,36 @@ NativeImageDumper::DumpEEClassForMethodTable( PTR_MethodTable mt )
83838384
VERBOSE_TYPES );
83848385
DisplayWriteFieldInt( m_numCTMFields, eecli->m_numCTMFields,
83858386
EEClassLayoutInfo, VERBOSE_TYPES );
8386-
PTR_FieldMarshaler fmArray = eecli->GetFieldMarshalers();
8387-
DisplayWriteFieldAddress( m_pFieldMarshalers,
8387+
PTR_NativeFieldDescriptor fmArray = eecli->GetNativeFieldDescriptors();
8388+
DisplayWriteFieldAddress( m_pNativeFieldDescriptors,
83888389
DPtrToPreferredAddr(fmArray),
83898390
eecli->m_numCTMFields
8390-
* MAXFIELDMARSHALERSIZE,
8391+
* sizeof(NativeFieldDescriptor),
83918392
EEClassLayoutInfo, VERBOSE_TYPES );
83928393
/* REVISIT_TODO Wed 03/22/2006
8393-
* Dump the various types of FieldMarshalers.
8394+
* Dump the various types of NativeFieldDescriptors.
83948395
*/
83958396
#if 0
8396-
DisplayStartArrayWithOffset( m_pFieldMarshalers, NULL,
8397+
DisplayStartArrayWithOffset( m_pNativeFieldDescriptors, NULL,
83978398
EEClassLayoutInfo, VERBOSE_TYPES );
83988399
for( unsigned i = 0; i < eecli->m_numCTMFields; ++i )
83998400
{
84008401
/* REVISIT_TODO Wed 03/22/2006
84018402
* Try to display the type of the field marshaler in the future.
84028403
*/
8403-
PTR_FieldMarshaler current = fmArray + i;
8404-
DisplayStartStructure( "FieldMarshaler",
8404+
PTR_NativeFieldDescriptor current = fmArray + i;
8405+
DisplayStartStructure( "NativeFieldDescriptor",
84058406
DPtrToPreferredAddr(current),
84068407
sizeof(*current), VERBOSE_TYPES );
84078408
WriteFieldFieldDesc( m_pFD, PTR_FieldDesc(TO_TADDR(current->m_pFD)),
8408-
FieldMarshaler, VERBOSE_TYPES );
8409-
DisplayWriteFieldInt( m_dwExternalOffset,
8410-
current->m_dwExternalOffset, FieldMarshaler,
8409+
NativeFieldDescriptor, VERBOSE_TYPES );
8410+
DisplayWriteFieldInt( m_offset,
8411+
current->m_offset, NativeFieldDescriptor,
84118412
VERBOSE_TYPES );
84128413
DisplayEndStructure( VERBOSE_TYPES ); //FieldMarshaler
84138414
}
84148415

8415-
DisplayEndArray( "Number of FieldMarshalers", VERBOSE_TYPES ); //m_pFieldMarshalers
8416+
DisplayEndArray( "Number of NativeFieldDescriptors", VERBOSE_TYPES ); //m_pNativeFieldDescriptors
84168417
#endif
84178418

84188419
DisplayEndStructure( EECLASSES ); //LayoutInfo

src/dlls/mscorrc/mscorrc.rc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -758,6 +758,8 @@ BEGIN
758758
IDS_CLASSLOAD_WRONGCPU "Could not load file or assembly '%1'. This assembly was compiled for a different processor."
759759

760760
IDS_CANNOT_MARSHAL "Type '%1' cannot be marshaled as an unmanaged structure; no meaningful size or offset can be computed."
761+
762+
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."
761763

762764
IDS_INVALID_REDIM "Illegal attempt to replace or redimension a fixed or locked SafeArray."
763765

src/dlls/mscorrc/resource.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@
179179
#define IDS_EE_ADUNLOAD_CANT_UNWIND_THREAD 0x1769
180180

181181
#define IDS_CANNOT_MARSHAL 0x1770
182+
#define IDS_CANNOT_MARSHAL_RECURSIVE_DEF 0x1771
182183
#define IDS_EE_HASH_VAL_FAILED 0x1772
183184

184185

0 commit comments

Comments
 (0)