Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/coreclr/debug/daccess/daccess.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7746,6 +7746,8 @@ void CALLBACK DacHandleWalker::EnumCallback(PTR_UNCHECKED_OBJECTREF handle, uint
data.Type = param->Type;
if (param->Type == HNDTYPE_DEPENDENT)
data.Secondary = GetDependentHandleSecondary(handle.GetAddr()).GetAddr();
else if (param->Type == HNDTYPE_WEAK_INTERIOR_POINTER)
data.Secondary = TO_CDADDR(HndGetHandleExtraInfo(handle.GetAddr()));
else
data.Secondary = 0;
data.AppDomain = param->AppDomain;
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/debug/daccess/request.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3255,7 +3255,7 @@ ClrDataAccess::GetThreadLocalModuleData(CLRDATA_ADDRESS thread, unsigned int ind
HRESULT ClrDataAccess::GetHandleEnum(ISOSHandleEnum **ppHandleEnum)
{
unsigned int types[] = {HNDTYPE_WEAK_SHORT, HNDTYPE_WEAK_LONG, HNDTYPE_STRONG, HNDTYPE_PINNED, HNDTYPE_DEPENDENT,
HNDTYPE_SIZEDREF,
HNDTYPE_SIZEDREF, HNDTYPE_WEAK_INTERIOR_POINTER,
#if defined(FEATURE_COMINTEROP) || defined(FEATURE_COMWRAPPERS) || defined(FEATURE_OBJCMARSHAL)
HNDTYPE_REFCOUNTED,
#endif // FEATURE_COMINTEROP || FEATURE_COMWRAPPERS || FEATURE_OBJCMARSHAL
Expand Down
14 changes: 14 additions & 0 deletions src/coreclr/gc/env/gcenv.base.h
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,20 @@ typedef uintptr_t TADDR;
typedef DPTR(size_t) PTR_size_t;
typedef DPTR(uint8_t) PTR_uint8_t;

#if defined(BUILD_AS_STANDALONE)
// In the standalone build, we don't have the DAC headers, so we need to define a non-DAC variant of dac_cast.
template <typename Tgt, typename Src>
inline Tgt dac_cast(Src src)
{
// In non-DAC builds, dac_cast is the same as a C-style cast because we need to support:
// - casting away const
// - conversions between pointers and TADDR
// Perhaps we should more precisely restrict it's usage, but we get the precise
// restrictions in DAC builds, so it wouldn't buy us much.
return (Tgt)(src);
}
#endif

// -----------------------------------------------------------------------------------------------------------

#define DATA_ALIGNMENT sizeof(uintptr_t)
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/gc/gchandletable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ Object* GCHandleManager::InterlockedCompareExchangeObjectInHandle(OBJECTHANDLE h
HandleType GCHandleManager::HandleFetchType(OBJECTHANDLE handle)
{
uint32_t type = ::HandleFetchType(handle);
assert(type >= HNDTYPE_WEAK_SHORT && type <= HNDTYPE_WEAK_NATIVE_COM);
assert(type >= HNDTYPE_WEAK_SHORT && type <= HNDTYPE_WEAK_INTERIOR_POINTER);
return static_cast<HandleType>(type);
}

Expand Down
12 changes: 11 additions & 1 deletion src/coreclr/gc/gcinterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -502,7 +502,17 @@ typedef enum
* but we are keeping it here for backward compatibility purposes"
*
*/
HNDTYPE_WEAK_NATIVE_COM = 9
HNDTYPE_WEAK_NATIVE_COM = 9,

/*
* INTERIOR POINTER HANDLES
*
* Interior pointer handles allow the vm to request that the GC keep an interior pointer to
* a given object updated to keep pointing at the same location within an object. These handles
* have an extra pointer which points at an interior pointer into the first object.
*
*/
HNDTYPE_WEAK_INTERIOR_POINTER = 10
} HandleType;

typedef enum
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/gc/gcscan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ void GCScan::GcScanHandles (promote_func* fn, int condemned, int max_gen,
Ref_UpdatePointers(condemned, max_gen, sc, fn);
Ref_UpdatePinnedPointers(condemned, max_gen, sc, fn);
Ref_ScanDependentHandlesForRelocation(condemned, max_gen, sc, fn);
Ref_ScanWeakInteriorPointersForRelocation(condemned, max_gen, sc, fn);
}
}

Expand Down
26 changes: 26 additions & 0 deletions src/coreclr/gc/handletablescan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -931,6 +931,15 @@ static void VerifyObjectAndAge(_UNCHECKED_OBJECTREF from, _UNCHECKED_OBJECTREF o
}
}

size_t my_get_size (_UNCHECKED_OBJECTREF ob)
{
DPTR(MethodTable) mT = dac_cast<DPTR(MethodTable)>((TADDR)ob->GetGCSafeMethodTable());

return (mT->GetBaseSize() +
(mT->HasComponentSize() ?
((size_t)dac_cast<DPTR(ArrayBase)>(ob)->GetNumComponents() * mT->RawGetComponentSize()) : 0));
}

/*
* BlockVerifyAgeMapForBlocksWorker
*
Expand Down Expand Up @@ -992,6 +1001,23 @@ void BlockVerifyAgeMapForBlocksWorker(uint32_t *pdwGen, uint32_t dwClumpMask, Sc
}
}
}
if (uType == HNDTYPE_WEAK_INTERIOR_POINTER)
{
PTR_uintptr_t pUserData = HandleQuickFetchUserDataPointer((OBJECTHANDLE)pValue);

// if we did then copy the value
if (pUserData)
{
TADDR pObjectInteriorPointer = **dac_cast<DPTR(DPTR(TADDR))>(pUserData);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: None of the surrounding code is DACized so dac_cast is unnecessary complication.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I thought that VerifyHeap worked in the DAC, but it turns out that it is an entirely parallel managed implementation these days. I'll pull that out if you'd like.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a build break introduced by the dac_cast macro. My guess is that the easiest way to fix it is to delete the use here.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

_UNCHECKED_OBJECTREF pObjectPointerRef = *pValue;
TADDR pObjectPointer = dac_cast<TADDR>(pObjectPointerRef);
if (pObjectInteriorPointer < pObjectPointer || pObjectInteriorPointer >= (pObjectPointer + my_get_size(pObjectPointerRef)))
{
_ASSERTE(!"Weak interior pointer has interior pointer which does not point at the object of the handle.");
GCToEEInterface::HandleFatalError(COR_E_EXECUTIONENGINE);
}
}
}
}
}
}
Expand Down
82 changes: 82 additions & 0 deletions src/coreclr/gc/objecthandle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,47 @@ void CALLBACK TraceDependentHandle(_UNCHECKED_OBJECTREF *pObjRef, uintptr_t *pEx
}
}

void CALLBACK UpdateWeakInteriorHandle(_UNCHECKED_OBJECTREF *pObjRef, uintptr_t *pExtraInfo, uintptr_t lp1, uintptr_t lp2)
{
LIMITED_METHOD_CONTRACT;
_ASSERTE(pExtraInfo);

Object **pPrimaryRef = (Object **)pObjRef;
uintptr_t **ppInteriorPtrRef = (uintptr_t **)pExtraInfo;

LOG((LF_GC, LL_INFO10000, LOG_HANDLE_OBJECT("Querying for new location of ",
pPrimaryRef, "to ", *pPrimaryRef)));

Object *pOldPrimary = *pPrimaryRef;

_ASSERTE(lp2);
promote_func* callback = (promote_func*) lp2;
callback(pPrimaryRef, (ScanContext *)lp1, 0);

Object *pNewPrimary = *pPrimaryRef;
if (pNewPrimary != NULL)
{
uintptr_t pOldInterior = **ppInteriorPtrRef;
uintptr_t delta = ((uintptr_t)pNewPrimary) - ((uintptr_t)pOldPrimary);
uintptr_t pNewInterior = pOldInterior + delta;
**ppInteriorPtrRef = pNewInterior;
#ifdef _DEBUG
if (pOldPrimary != *pPrimaryRef)
LOG((LF_GC, LL_INFO10000, "Updating " FMT_HANDLE "from" FMT_ADDR "to " FMT_OBJECT "\n",
DBG_ADDR(pPrimaryRef), DBG_ADDR(pOldPrimary), DBG_ADDR(*pPrimaryRef)));
else
LOG((LF_GC, LL_INFO10000, "Updating " FMT_HANDLE "- " FMT_OBJECT "did not move\n",
DBG_ADDR(pPrimaryRef), DBG_ADDR(*pPrimaryRef)));
if (pOldInterior != pNewInterior)
LOG((LF_GC, LL_INFO10000, "Updating " FMT_HANDLE "from" FMT_ADDR "to " FMT_OBJECT "\n",
DBG_ADDR(*ppInteriorPtrRef), DBG_ADDR(pOldInterior), DBG_ADDR(pNewInterior)));
else
LOG((LF_GC, LL_INFO10000, "Updating " FMT_HANDLE "- " FMT_OBJECT "did not move\n",
DBG_ADDR(*ppInteriorPtrRef), DBG_ADDR(pOldInterior)));
#endif
}
}

void CALLBACK UpdateDependentHandle(_UNCHECKED_OBJECTREF *pObjRef, uintptr_t *pExtraInfo, uintptr_t lp1, uintptr_t lp2)
{
LIMITED_METHOD_CONTRACT;
Expand Down Expand Up @@ -427,6 +468,7 @@ void CALLBACK ScanPointerForProfilerAndETW(_UNCHECKED_OBJECTREF *pObjRef, uintpt
break;
case HNDTYPE_WEAK_SHORT:
case HNDTYPE_WEAK_LONG:
case HNDTYPE_WEAK_INTERIOR_POINTER:
#ifdef FEATURE_WEAK_NATIVE_COM_HANDLES
case HNDTYPE_WEAK_NATIVE_COM:
#endif // FEATURE_WEAK_NATIVE_COM_HANDLES
Expand Down Expand Up @@ -527,6 +569,7 @@ static const uint32_t s_rgTypeFlags[] =
HNDF_NORMAL, // HNDTYPE_ASYNCPINNED
HNDF_EXTRAINFO, // HNDTYPE_SIZEDREF
HNDF_EXTRAINFO, // HNDTYPE_WEAK_NATIVE_COM
HNDF_EXTRAINFO, // HNDTYPE_WEAK_INTERIOR_POINTER
};

int getNumberOfSlots()
Expand Down Expand Up @@ -1170,6 +1213,7 @@ void Ref_CheckReachable(uint32_t condemned, uint32_t maxgen, ScanContext *sc)
#ifdef FEATURE_REFCOUNTED_HANDLES
HNDTYPE_REFCOUNTED,
#endif
HNDTYPE_WEAK_INTERIOR_POINTER
};

// check objects pointed to by short weak handles
Expand Down Expand Up @@ -1339,6 +1383,40 @@ void Ref_ScanDependentHandlesForClearing(uint32_t condemned, uint32_t maxgen, Sc
}
}

// Perform a scan of weak interior pointers for the purpose of updating handles to track relocated objects.
void Ref_ScanWeakInteriorPointersForRelocation(uint32_t condemned, uint32_t maxgen, ScanContext* sc, Ref_promote_func* fn)
{
LOG((LF_GC, LL_INFO10000, "Relocating moved dependent handles in generation %u\n", condemned));
uint32_t type = HNDTYPE_WEAK_INTERIOR_POINTER;
uint32_t flags = (sc->concurrent) ? HNDGCF_ASYNC : HNDGCF_NORMAL;
flags |= HNDGCF_EXTRAINFO;

HandleTableMap *walk = &g_HandleTableMap;
while (walk)
{
for (uint32_t i = 0; i < INITIAL_HANDLE_TABLE_ARRAY_SIZE; i ++)
{
if (walk->pBuckets[i] != NULL)
{
int uCPUindex = getSlotNumber(sc);
int uCPUlimit = getNumberOfSlots();
assert(uCPUlimit > 0);
int uCPUstep = getThreadCount(sc);
HHANDLETABLE* pTable = walk->pBuckets[i]->pTable;
for ( ; uCPUindex < uCPUlimit; uCPUindex += uCPUstep)
{
HHANDLETABLE hTable = pTable[uCPUindex];
if (hTable)
{
HndScanHandlesForGC(hTable, UpdateWeakInteriorHandle, uintptr_t(sc), uintptr_t(fn), &type, 1, condemned, maxgen, flags );
}
}
}
}
walk = walk->pNext;
}
}

// Perform a scan of dependent handles for the purpose of updating handles to track relocated objects.
void Ref_ScanDependentHandlesForRelocation(uint32_t condemned, uint32_t maxgen, ScanContext* sc, Ref_promote_func* fn)
{
Expand Down Expand Up @@ -1590,6 +1668,7 @@ void Ref_ScanHandlesForProfilerAndETW(uint32_t maxgen, uintptr_t lp1, handle_sca
HNDTYPE_ASYNCPINNED,
#endif
HNDTYPE_SIZEDREF,
HNDTYPE_WEAK_INTERIOR_POINTER
};

uint32_t flags = HNDGCF_NORMAL;
Expand Down Expand Up @@ -1712,6 +1791,7 @@ void Ref_AgeHandles(uint32_t condemned, uint32_t maxgen, ScanContext* sc)
HNDTYPE_ASYNCPINNED,
#endif
HNDTYPE_SIZEDREF,
HNDTYPE_WEAK_INTERIOR_POINTER
};

// perform a multi-type scan that ages the handles
Expand Down Expand Up @@ -1766,6 +1846,7 @@ void Ref_RejuvenateHandles(uint32_t condemned, uint32_t maxgen, ScanContext* sc)
HNDTYPE_ASYNCPINNED,
#endif
HNDTYPE_SIZEDREF,
HNDTYPE_WEAK_INTERIOR_POINTER
};

// reset the ages of these handles
Expand Down Expand Up @@ -1819,6 +1900,7 @@ void Ref_VerifyHandleTable(uint32_t condemned, uint32_t maxgen, ScanContext* sc)
#endif
HNDTYPE_SIZEDREF,
HNDTYPE_DEPENDENT,
HNDTYPE_WEAK_INTERIOR_POINTER
};

// verify these handles
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/gc/objecthandle.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ DhContext *Ref_GetDependentHandleContext(ScanContext* sc);
bool Ref_ScanDependentHandlesForPromotion(DhContext *pDhContext);
void Ref_ScanDependentHandlesForClearing(uint32_t condemned, uint32_t maxgen, ScanContext* sc);
void Ref_ScanDependentHandlesForRelocation(uint32_t condemned, uint32_t maxgen, ScanContext* sc, Ref_promote_func* fn);
void Ref_ScanWeakInteriorPointersForRelocation(uint32_t condemned, uint32_t maxgen, ScanContext* sc, Ref_promote_func* fn);
void Ref_ScanSizedRefHandles(uint32_t condemned, uint32_t maxgen, ScanContext* sc, Ref_promote_func* fn);

void Ref_CheckReachable (uint32_t uCondemnedGeneration, uint32_t uMaxGeneration, ScanContext* sc);
Expand Down
6 changes: 6 additions & 0 deletions src/coreclr/vm/appdomain.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1038,6 +1038,12 @@ class BaseDomain
return ::CreatePinningHandle(m_handleStore, object);
}

OBJECTHANDLE CreateWeakInteriorHandle(OBJECTREF object, void* pInteriorPointerLocation)
{
WRAPPER_NO_CONTRACT;
return ::CreateWeakInteriorHandle(m_handleStore, object, pInteriorPointerLocation);
}

OBJECTHANDLE CreateSizedRefHandle(OBJECTREF object)
{
WRAPPER_NO_CONTRACT;
Expand Down
18 changes: 18 additions & 0 deletions src/coreclr/vm/gchandleutilities.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,18 @@ inline OBJECTHANDLE CreateDependentHandle(IGCHandleStore* store, OBJECTREF prima
return hnd;
}

inline OBJECTHANDLE CreateWeakInteriorHandle(IGCHandleStore* store, OBJECTREF primary, void* interiorPointerLocation)
{
OBJECTHANDLE hnd = store->CreateHandleWithExtraInfo(OBJECTREFToObject(primary), HNDTYPE_WEAK_INTERIOR_POINTER, interiorPointerLocation);
if (!hnd)
{
COMPlusThrowOM();
}

DiagHandleCreated(hnd, primary);
return hnd;
}

// Global handle creation convenience functions
inline OBJECTHANDLE CreateGlobalHandleCommon(OBJECTREF object, HandleType type)
{
Expand Down Expand Up @@ -321,6 +333,11 @@ inline void DestroyGlobalRefcountedHandle(OBJECTHANDLE handle)
DestroyHandleCommon(handle, HNDTYPE_REFCOUNTED);
}

inline void DestroyWeakInteriorHandle(OBJECTHANDLE handle)
{
DestroyHandleCommon(handle, HNDTYPE_WEAK_INTERIOR_POINTER);
}

inline void DestroyTypedHandle(OBJECTHANDLE handle)
{
DiagHandleDestroyed(handle);
Expand All @@ -338,6 +355,7 @@ typedef Wrapper<OBJECTHANDLE, DoNothing<OBJECTHANDLE>, DestroyRefcountedHandle>
typedef Holder<OBJECTHANDLE, DoNothing<OBJECTHANDLE>, DestroyLongWeakHandle> LongWeakHandleHolder;
typedef Holder<OBJECTHANDLE, DoNothing<OBJECTHANDLE>, DestroyGlobalStrongHandle> GlobalStrongHandleHolder;
typedef Holder<OBJECTHANDLE, DoNothing<OBJECTHANDLE>, DestroyGlobalShortWeakHandle> GlobalShortWeakHandleHolder;
typedef Holder<OBJECTHANDLE, DoNothing<OBJECTHANDLE>, DestroyWeakInteriorHandle> WeakInteriorHandleHolder;
typedef Holder<OBJECTHANDLE, DoNothing<OBJECTHANDLE>, ResetOBJECTHANDLE> ObjectInHandleHolder;

class RCOBJECTHANDLEHolder : public RefCountedOHWrapper
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/vm/jithelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3518,7 +3518,7 @@ NOINLINE HCIMPL1(Object*, JIT_GetRuntimeType_Framed, CORINFO_CLASS_HANDLE type)
TypeHandle typeHandle(type);

// Array/other type handle case.
OBJECTREF refType = typeHandle.GetManagedClassObjectFast();
OBJECTREF refType = typeHandle.GetManagedClassObjectIfExists();
if (refType == NULL)
{
HELPER_METHOD_FRAME_BEGIN_RET_1(refType);
Expand Down
Loading