summaryrefslogtreecommitdiff
path: root/src/vm
diff options
context:
space:
mode:
authorKoundinya Veluri <kouvel@users.noreply.github.com>2017-11-06 14:28:41 -0800
committerGitHub <noreply@github.com>2017-11-06 14:28:41 -0800
commit1a67e84aca889cf94c716a7847cfe0b4d1ee62d6 (patch)
treeee24ebe93ec1ea69c456b729c495f1ead37394de /src/vm
parentaee95b5490f55512635f8f87c21e54e164fb9a2f (diff)
downloadcoreclr-1a67e84aca889cf94c716a7847cfe0b4d1ee62d6.tar.gz
coreclr-1a67e84aca889cf94c716a7847cfe0b4d1ee62d6.tar.bz2
coreclr-1a67e84aca889cf94c716a7847cfe0b4d1ee62d6.zip
Fix GC reporting for slow tail call arguments of type `Span<T>` (#14826)
Fix GC reporting for slow tail call arguments of type `Span<T>` Fixes https://github.com/dotnet/coreclr/issues/9032: - Refactored by-ref-like method table walking to find offsets of by-ref pointers in siginfo.hpp/cpp - Reused that for appending GC layout when creating the copy-args helper for a slow tail call
Diffstat (limited to 'src/vm')
-rw-r--r--src/vm/i386/stublinkerx86.cpp11
-rw-r--r--src/vm/object.inl37
-rw-r--r--src/vm/siginfo.cpp46
-rw-r--r--src/vm/siginfo.hpp1
4 files changed, 56 insertions, 39 deletions
diff --git a/src/vm/i386/stublinkerx86.cpp b/src/vm/i386/stublinkerx86.cpp
index e07b6e1c37..14b9701a29 100644
--- a/src/vm/i386/stublinkerx86.cpp
+++ b/src/vm/i386/stublinkerx86.cpp
@@ -5925,6 +5925,17 @@ static void AppendGCLayout(ULONGARRAY &gcLayout, size_t baseOffset, BOOL fIsType
_ASSERTE(pMT);
_ASSERTE(pMT->IsValueType());
+ if (pMT->IsByRefLike())
+ {
+ FindByRefPointerOffsetsInByRefLikeObject(
+ pMT,
+ baseOffset,
+ [&](size_t pointerOffset)
+ {
+ *gcLayout.AppendThrowing() = (ULONG)(pointerOffset | 1); // "| 1" to mark it as an interior pointer
+ });
+ }
+
// walk the GC descriptors, reporting the correct offsets
if (pMT->ContainsPointers())
{
diff --git a/src/vm/object.inl b/src/vm/object.inl
index 5dc3d6d116..495f7bff71 100644
--- a/src/vm/object.inl
+++ b/src/vm/object.inl
@@ -325,4 +325,41 @@ inline TypeHandle Object::GetGCSafeTypeHandle() const
return TypeHandle(pMT);
}
+template<class F>
+inline void FindByRefPointerOffsetsInByRefLikeObject(PTR_MethodTable pMT, SIZE_T baseOffset, const F processPointerOffset)
+{
+ WRAPPER_NO_CONTRACT;
+ _ASSERTE(pMT != nullptr);
+ _ASSERTE(pMT->IsByRefLike());
+
+ // TODO: TypedReference should ideally be implemented as a by-ref-like struct containing a ByReference<T> field,
+ // in which case the check for g_TypedReferenceMT below would not be necessary
+ if (pMT == g_TypedReferenceMT || pMT->HasSameTypeDefAs(g_pByReferenceClass))
+ {
+ processPointerOffset(baseOffset);
+ 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;
+ }
+
+ SIZE_T fieldStartIndex = pFD->GetOffset() / sizeof(void *);
+ FindByRefPointerOffsetsInByRefLikeObject(pFieldMT, baseOffset + fieldStartIndex, processPointerOffset);
+ }
+}
+
#endif // _OBJECT_INL_
diff --git a/src/vm/siginfo.cpp b/src/vm/siginfo.cpp
index be919c8b7e..bc16bdffda 100644
--- a/src/vm/siginfo.cpp
+++ b/src/vm/siginfo.cpp
@@ -4946,50 +4946,20 @@ 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<T> 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<PTR_PTR_Object>(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_PTR_Object>(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;
if (pMT->IsByRefLike())
{
- ReportByRefPointersFromByRefLikeObject(fn, sc, pMT, pSrc);
+ FindByRefPointerOffsetsInByRefLikeObject(
+ pMT,
+ 0 /* baseOffset */,
+ [&](SIZE_T pointerOffset)
+ {
+ PTR_PTR_Object fieldRef = dac_cast<PTR_PTR_Object>(PTR_BYTE(pSrc) + pointerOffset);
+ (*fn)(fieldRef, sc, GC_CALL_INTERIOR);
+ });
}
if (!pMT->ContainsPointers())
diff --git a/src/vm/siginfo.hpp b/src/vm/siginfo.hpp
index 52b05928db..4cfa548270 100644
--- a/src/vm/siginfo.hpp
+++ b/src/vm/siginfo.hpp
@@ -1191,4 +1191,3 @@ BOOL IsTypeDefExternallyVisible(mdToken tk, Module *pModule, DWORD dwAttrs);
void ReportPointersFromValueType(promote_func *fn, ScanContext *sc, PTR_MethodTable pMT, PTR_VOID pSrc);
#endif /* _H_SIGINFO */
-