#ifdef FEATURE_SPAN_OF_T
// Load ByReference class
+ //
+ // NOTE: ByReference<T> must be the first by-ref-like system type to be loaded,
+ // because MethodTable::ClassifyEightBytesWithManagedLayout depends on it.
g_pByReferenceClass = MscorlibBinder::GetClass(CLASS__BYREFERENCE);
#endif
_ASSERTE(eightByteSize == 8);
_ASSERTE(IS_ALIGNED((SIZE_T)genRegDest, 8));
- (*fn)(dac_cast<PTR_PTR_Object>(genRegDest), sc, 0);
+ uint32_t flags = eightByteClassification == SystemVClassificationTypeIntegerByRef ? GC_CALL_INTERIOR : 0;
+ (*fn)(dac_cast<PTR_PTR_Object>(genRegDest), sc, flags);
}
genRegDest += eightByteSize;
FieldDesc *pField = GetApproxFieldDescListRaw();
FieldDesc *pFieldEnd = pField + numIntroducedFields;
+ // System types are loaded before others, so ByReference<T> would be loaded before Span<T> or any other type that has a
+ // ByReference<T> field. ByReference<T> is the first by-ref-like system type to be loaded (see
+ // SystemDomain::LoadBaseSystemClasses), so if the current method table is marked as by-ref-like and g_pByReferenceClass is
+ // null, it must be the initial load of ByReference<T>.
+ bool isThisByReferenceOfT = IsByRefLike() && (g_pByReferenceClass == nullptr || HasSameTypeDefAs(g_pByReferenceClass));
+
for (; pField < pFieldEnd; pField++)
{
#ifdef _DEBUG
CorElementType fieldType = pField->GetFieldType();
- SystemVClassificationType fieldClassificationType = CorInfoType2UnixAmd64Classification(fieldType);
+ SystemVClassificationType fieldClassificationType;
+ if (isThisByReferenceOfT)
+ {
+ // ByReference<T> is a special type whose single IntPtr field holds a by-ref potentially interior pointer to GC
+ // memory, so classify its field as such
+ _ASSERTE(numIntroducedFields == 1);
+ _ASSERTE(fieldType == CorElementType::ELEMENT_TYPE_I);
+ fieldClassificationType = SystemVClassificationTypeIntegerByRef;
+ }
+ else
+ {
+ fieldClassificationType = CorInfoType2UnixAmd64Classification(fieldType);
+ }
#ifdef _DEBUG
LPCUTF8 fieldName;
{
WRAPPER_NO_CONTRACT;
- if(pMT->ContainsPointers())
+ if (!pMT->ContainsPointers() && !pMT->IsByRefLike())
{
-#if defined(UNIX_AMD64_ABI) && defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
- if (pSrc->IsStructPassedInRegs())
- {
- pSrc->ReportPointersFromStructInRegisters(fn, sc, pMT->GetNumInstanceFieldBytes());
- return;
- }
-#endif // UNIX_AMD64_ABI && FEATURE_UNIX_AMD64_STRUCT_PASSING
+ return;
}
- else if (!pMT->IsByRefLike())
+
+#if defined(UNIX_AMD64_ABI) && defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
+ if (pSrc->IsStructPassedInRegs())
{
+ pSrc->ReportPointersFromStructInRegisters(fn, sc, pMT->GetNumInstanceFieldBytes());
return;
}
+#endif // UNIX_AMD64_ABI && FEATURE_UNIX_AMD64_STRUCT_PASSING
ReportPointersFromValueType(fn, sc, pMT, pSrc->GetDestinationAddress());
}