From 62ac5f04456e517b76bcfc3d386859a506eed6d1 Mon Sep 17 00:00:00 2001 From: Koundinya Veluri Date: Sun, 22 Jan 2017 23:10:14 -0800 Subject: [PATCH] Report by-ref-like types to the GC (SpanOfT) (#9034) Report by-ref-like types to the GC (SpanOfT) Fixes #8517 --- src/vm/jitinterface.cpp | 11 +++++++++ src/vm/siginfo.cpp | 59 +++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 63 insertions(+), 7 deletions(-) diff --git a/src/vm/jitinterface.cpp b/src/vm/jitinterface.cpp index ee22e72..75a228f 100644 --- a/src/vm/jitinterface.cpp +++ b/src/vm/jitinterface.cpp @@ -2294,6 +2294,15 @@ static unsigned ComputeGCLayout(MethodTable * pMT, BYTE* gcPtrs) _ASSERTE(pMT->IsValueType()); + // TODO: TypedReference should ideally be implemented as a by-ref-like struct containing a ByReference field, in which + // case the check for g_TypedReferenceMT below would not be necessary + if (pMT == g_TypedReferenceMT) + { + gcPtrs[0] = TYPE_GC_BYREF; + gcPtrs[1] = TYPE_GC_NONE; + return 1; + } + ApproxFieldDescIterator fieldIterator(pMT, ApproxFieldDescIterator::INSTANCE_FIELDS); for (FieldDesc *pFD = fieldIterator.Next(); pFD != NULL; pFD = fieldIterator.Next()) { @@ -2357,6 +2366,8 @@ unsigned CEEInfo::getClassGClayout (CORINFO_CLASS_HANDLE clsHnd, BYTE* gcPtrs) if (pMT->IsByRefLike()) { + // TODO: TypedReference should ideally be implemented as a by-ref-like struct containing a ByReference field, in + // which case the check for g_TypedReferenceMT below would not be necessary if (pMT == g_TypedReferenceMT) { gcPtrs[0] = TYPE_GC_BYREF; diff --git a/src/vm/siginfo.cpp b/src/vm/siginfo.cpp index 12803ec..2c2c4f4 100644 --- a/src/vm/siginfo.cpp +++ b/src/vm/siginfo.cpp @@ -4953,11 +4953,51 @@ void PromoteCarefully(promote_func fn, (*fn) (ppObj, sc, flags); } +void ReportByRefPointersFromByRefLikeObject(promote_func *fn, ScanContext *sc, PTR_MethodTable pMT, PTR_VOID pSrc) +{ + WRAPPER_NO_CONTRACT; + + _ASSERTE(pMT->IsByRefLike()); + + // TODO: TypedReference should ideally be implemented as a by-ref-like struct containing a ByReference field, + // in which case the check for g_TypedReferenceMT below would not be necessary + if (pMT == g_TypedReferenceMT || pMT->HasSameTypeDefAs(g_pByReferenceClass)) + { + (*fn)(dac_cast(pSrc), sc, GC_CALL_INTERIOR); + return; + } + + ApproxFieldDescIterator fieldIterator(pMT, ApproxFieldDescIterator::INSTANCE_FIELDS); + for (FieldDesc *pFD = fieldIterator.Next(); pFD != NULL; pFD = fieldIterator.Next()) + { + if (pFD->GetFieldType() != ELEMENT_TYPE_VALUETYPE) + { + continue; + } + + // TODO: GetApproxFieldTypeHandleThrowing may throw. This is a potential stress problem for fragile NGen of non-CoreLib + // assemblies. It won’t ever throw for CoreCLR with R2R. Figure out if anything needs to be done to deal with the + // exception. + PTR_MethodTable pFieldMT = pFD->GetApproxFieldTypeHandleThrowing().AsMethodTable(); + if (!pFieldMT->IsByRefLike()) + { + continue; + } + + int fieldStartIndex = pFD->GetOffset() / sizeof(void *); + PTR_PTR_Object fieldRef = dac_cast(PTR_BYTE(pSrc) + fieldStartIndex); + ReportByRefPointersFromByRefLikeObject(fn, sc, pFieldMT, fieldRef); + } +} + void ReportPointersFromValueType(promote_func *fn, ScanContext *sc, PTR_MethodTable pMT, PTR_VOID pSrc) { WRAPPER_NO_CONTRACT; - // SPAN-TODO: GC reporting - https://github.com/dotnet/coreclr/issues/8517 + if (pMT->IsByRefLike()) + { + ReportByRefPointersFromByRefLikeObject(fn, sc, pMT, pSrc); + } if (!pMT->ContainsPointers()) return; @@ -4987,16 +5027,21 @@ void ReportPointersFromValueType(promote_func *fn, ScanContext *sc, PTR_MethodTa void ReportPointersFromValueTypeArg(promote_func *fn, ScanContext *sc, PTR_MethodTable pMT, ArgDestination *pSrc) { WRAPPER_NO_CONTRACT; - - if (!pMT->ContainsPointers()) - return; + + if(pMT->ContainsPointers()) + { #if defined(UNIX_AMD64_ABI) && defined(FEATURE_UNIX_AMD64_STRUCT_PASSING) - if (pSrc->IsStructPassedInRegs()) + if (pSrc->IsStructPassedInRegs()) + { + pSrc->ReportPointersFromStructInRegisters(fn, sc, pMT->GetNumInstanceFieldBytes()); + return; + } +#endif // UNIX_AMD64_ABI && FEATURE_UNIX_AMD64_STRUCT_PASSING + } + else if (!pMT->IsByRefLike()) { - pSrc->ReportPointersFromStructInRegisters(fn, sc, pMT->GetNumInstanceFieldBytes()); return; } -#endif // UNIX_AMD64_ABI && FEATURE_UNIX_AMD64_STRUCT_PASSING ReportPointersFromValueType(fn, sc, pMT, pSrc->GetDestinationAddress()); } -- 2.7.4