From 4e0512dd24b1d782fe6964da1ea8dda83d25b7b7 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Wed, 29 Apr 2020 14:26:09 -0700 Subject: [PATCH] Remove WinRT weak handles support in the runtime. --- src/coreclr/src/debug/daccess/daccess.cpp | 4 - src/coreclr/src/debug/daccess/dacdbiimpl.cpp | 7 - src/coreclr/src/debug/daccess/request.cpp | 4 +- src/coreclr/src/gc/gchandletable.cpp | 2 +- src/coreclr/src/gc/gcinterface.h | 16 +- src/coreclr/src/gc/handletable.cpp | 7 - src/coreclr/src/gc/objecthandle.cpp | 22 - src/coreclr/src/vm/appdomain.hpp | 6 - src/coreclr/src/vm/gchandleutilities.h | 41 -- src/coreclr/src/vm/marshalnative.cpp | 2 +- src/coreclr/src/vm/runtimehandles.cpp | 2 +- src/coreclr/src/vm/weakreferencenative.cpp | 483 +------------------ 12 files changed, 28 insertions(+), 568 deletions(-) diff --git a/src/coreclr/src/debug/daccess/daccess.cpp b/src/coreclr/src/debug/daccess/daccess.cpp index a05d4f09d0d68..98c5dbeedc8db 100644 --- a/src/coreclr/src/debug/daccess/daccess.cpp +++ b/src/coreclr/src/debug/daccess/daccess.cpp @@ -8251,10 +8251,6 @@ void CALLBACK DacHandleWalker::EnumCallbackSOS(PTR_UNCHECKED_OBJECTREF handle, u data.Type = param->Type; if (param->Type == HNDTYPE_DEPENDENT) data.Secondary = GetDependentHandleSecondary(handle.GetAddr()).GetAddr(); -#ifdef FEATURE_COMINTEROP - else if (param->Type == HNDTYPE_WEAK_WINRT) - data.Secondary = HndGetHandleExtraInfo(handle.GetAddr()); -#endif // FEATURE_COMINTEROP else data.Secondary = 0; data.AppDomain = param->AppDomain; diff --git a/src/coreclr/src/debug/daccess/dacdbiimpl.cpp b/src/coreclr/src/debug/daccess/dacdbiimpl.cpp index 905698ad4fd71..1cfc9e37fadba 100644 --- a/src/coreclr/src/debug/daccess/dacdbiimpl.cpp +++ b/src/coreclr/src/debug/daccess/dacdbiimpl.cpp @@ -7490,9 +7490,6 @@ UINT32 DacRefWalker::GetHandleWalkerMask() #ifdef FEATURE_COMINTEROP if ((mHandleMask & CorHandleWeakRefCount) || (mHandleMask & CorHandleStrongRefCount)) result |= (1 << HNDTYPE_REFCOUNTED); - - if (mHandleMask & CorHandleWeakWinRT) - result |= (1 << HNDTYPE_WEAK_WINRT); #endif // FEATURE_COMINTEROP if (mHandleMask & CorHandleStrongDependent) @@ -7666,10 +7663,6 @@ void CALLBACK DacHandleWalker::EnumCallbackDac(PTR_UNCHECKED_OBJECTREF handle, u GetRefCountedHandleInfo((OBJECTREF)*handle, param->Type, &refCnt, NULL, NULL, NULL); data.i64ExtraData = refCnt; break; - - case HNDTYPE_WEAK_WINRT: - data.dwType = (DWORD)CorHandleWeakWinRT; - break; #endif case HNDTYPE_DEPENDENT: diff --git a/src/coreclr/src/debug/daccess/request.cpp b/src/coreclr/src/debug/daccess/request.cpp index 2be663ebd77ea..eab9d7f329fcf 100644 --- a/src/coreclr/src/debug/daccess/request.cpp +++ b/src/coreclr/src/debug/daccess/request.cpp @@ -3253,7 +3253,7 @@ HRESULT ClrDataAccess::GetHandleEnum(ISOSHandleEnum **ppHandleEnum) unsigned int types[] = {HNDTYPE_WEAK_SHORT, HNDTYPE_WEAK_LONG, HNDTYPE_STRONG, HNDTYPE_PINNED, HNDTYPE_VARIABLE, HNDTYPE_DEPENDENT, HNDTYPE_ASYNCPINNED, HNDTYPE_SIZEDREF, #ifdef FEATURE_COMINTEROP - HNDTYPE_REFCOUNTED, HNDTYPE_WEAK_WINRT + HNDTYPE_REFCOUNTED #endif }; @@ -3291,7 +3291,7 @@ HRESULT ClrDataAccess::GetHandleEnumForGC(unsigned int gen, ISOSHandleEnum **ppH unsigned int types[] = {HNDTYPE_WEAK_SHORT, HNDTYPE_WEAK_LONG, HNDTYPE_STRONG, HNDTYPE_PINNED, HNDTYPE_VARIABLE, HNDTYPE_DEPENDENT, HNDTYPE_ASYNCPINNED, HNDTYPE_SIZEDREF, #ifdef FEATURE_COMINTEROP - HNDTYPE_REFCOUNTED, HNDTYPE_WEAK_WINRT + HNDTYPE_REFCOUNTED #endif }; diff --git a/src/coreclr/src/gc/gchandletable.cpp b/src/coreclr/src/gc/gchandletable.cpp index b7c4bf2687233..3960353189095 100644 --- a/src/coreclr/src/gc/gchandletable.cpp +++ b/src/coreclr/src/gc/gchandletable.cpp @@ -168,7 +168,7 @@ Object* GCHandleManager::InterlockedCompareExchangeObjectInHandle(OBJECTHANDLE h HandleType GCHandleManager::HandleFetchType(OBJECTHANDLE handle) { uint32_t type = ::HandleFetchType(handle); - assert(type >= HNDTYPE_WEAK_SHORT && type <= HNDTYPE_WEAK_WINRT); + assert(type >= HNDTYPE_WEAK_SHORT && type <= HNDTYPE_SIZEDREF); return static_cast(type); } diff --git a/src/coreclr/src/gc/gcinterface.h b/src/coreclr/src/gc/gcinterface.h index 122106c2ae273..0ad60fe298397 100644 --- a/src/coreclr/src/gc/gcinterface.h +++ b/src/coreclr/src/gc/gcinterface.h @@ -419,21 +419,7 @@ typedef enum * be calculated. * */ - HNDTYPE_SIZEDREF = 8, - - /* - * WINRT WEAK HANDLES - * - * WinRT weak reference handles hold two different types of weak handles to any - * RCW with an underlying COM object that implements IWeakReferenceSource. The - * object reference itself is a short weak handle to the RCW. In addition an - * IWeakReference* to the underlying COM object is stored, allowing the handle - * to create a new RCW if the existing RCW is collected. This ensures that any - * code holding onto a WinRT weak reference can always access an RCW to the - * underlying COM object as long as it has not been released by all of its strong - * references. - */ - HNDTYPE_WEAK_WINRT = 9 + HNDTYPE_SIZEDREF = 8 } HandleType; typedef enum diff --git a/src/coreclr/src/gc/handletable.cpp b/src/coreclr/src/gc/handletable.cpp index 898e843419341..1eb04b03ab0e2 100644 --- a/src/coreclr/src/gc/handletable.cpp +++ b/src/coreclr/src/gc/handletable.cpp @@ -408,13 +408,6 @@ void HndDestroyHandleOfUnknownType(HHANDLETABLE hTable, OBJECTHANDLE handle) // sanity check handle we are being asked to free _ASSERTE(handle); -#ifdef FEATURE_COMINTEROP - // If we're being asked to destroy a WinRT weak handle, that will cause a leak - // of the IWeakReference* that it holds in its extra data. Instead of using this - // API use DestroyWinRTWeakHandle instead. - _ASSERTE(HandleFetchType(handle) != HNDTYPE_WEAK_WINRT); -#endif // FEATURE_COMINTEROP - // fetch the type and then free normally HndDestroyHandle(hTable, HandleFetchType(handle), handle); } diff --git a/src/coreclr/src/gc/objecthandle.cpp b/src/coreclr/src/gc/objecthandle.cpp index 4a4f201ca03bd..b6b371b33d7f4 100644 --- a/src/coreclr/src/gc/objecthandle.cpp +++ b/src/coreclr/src/gc/objecthandle.cpp @@ -425,9 +425,6 @@ void CALLBACK ScanPointerForProfilerAndETW(_UNCHECKED_OBJECTREF *pObjRef, uintpt break; case HNDTYPE_WEAK_SHORT: case HNDTYPE_WEAK_LONG: -#ifdef FEATURE_COMINTEROP - case HNDTYPE_WEAK_WINRT: -#endif // FEATURE_COMINTEROP rootFlags |= kEtwGCRootFlagsWeakRef; break; @@ -520,7 +517,6 @@ static const uint32_t s_rgTypeFlags[] = HNDF_EXTRAINFO, // HNDTYPE_DEPENDENT HNDF_NORMAL, // HNDTYPE_ASYNCPINNED HNDF_EXTRAINFO, // HNDTYPE_SIZEDREF - HNDF_EXTRAINFO, // HNDTYPE_WEAK_WINRT }; int getNumberOfSlots() @@ -1379,9 +1375,6 @@ void Ref_CheckAlive(uint32_t condemned, uint32_t maxgen, uintptr_t lp1) uint32_t types[] = { HNDTYPE_WEAK_SHORT -#ifdef FEATURE_COMINTEROP - , HNDTYPE_WEAK_WINRT -#endif // FEATURE_COMINTEROP }; uint32_t flags = (((ScanContext*) lp1)->concurrent) ? HNDGCF_ASYNC : HNDGCF_NORMAL; @@ -1438,9 +1431,6 @@ void Ref_UpdatePointers(uint32_t condemned, uint32_t maxgen, ScanContext* sc, Re #if defined(FEATURE_COMINTEROP) || defined(FEATURE_REDHAWK) HNDTYPE_REFCOUNTED, #endif // FEATURE_COMINTEROP || FEATURE_REDHAWK -#ifdef FEATURE_COMINTEROP - HNDTYPE_WEAK_WINRT, -#endif // FEATURE_COMINTEROP HNDTYPE_SIZEDREF, }; @@ -1484,9 +1474,6 @@ void Ref_ScanHandlesForProfilerAndETW(uint32_t maxgen, uintptr_t lp1, handle_sca #if defined(FEATURE_COMINTEROP) || defined(FEATURE_REDHAWK) HNDTYPE_REFCOUNTED, #endif // FEATURE_COMINTEROP || FEATURE_REDHAWK -#ifdef FEATURE_COMINTEROP - HNDTYPE_WEAK_WINRT, -#endif // FEATURE_COMINTEROP HNDTYPE_PINNED, // HNDTYPE_VARIABLE, HNDTYPE_ASYNCPINNED, @@ -1630,9 +1617,6 @@ void Ref_AgeHandles(uint32_t condemned, uint32_t maxgen, uintptr_t lp1) #if defined(FEATURE_COMINTEROP) || defined(FEATURE_REDHAWK) HNDTYPE_REFCOUNTED, #endif // FEATURE_COMINTEROP || FEATURE_REDHAWK -#ifdef FEATURE_COMINTEROP - HNDTYPE_WEAK_WINRT, -#endif // FEATURE_COMINTEROP HNDTYPE_ASYNCPINNED, HNDTYPE_SIZEDREF, }; @@ -1673,9 +1657,6 @@ void Ref_RejuvenateHandles(uint32_t condemned, uint32_t maxgen, uintptr_t lp1) #if defined(FEATURE_COMINTEROP) || defined(FEATURE_REDHAWK) HNDTYPE_REFCOUNTED, #endif // FEATURE_COMINTEROP || FEATURE_REDHAWK -#ifdef FEATURE_COMINTEROP - HNDTYPE_WEAK_WINRT, -#endif // FEATURE_COMINTEROP HNDTYPE_ASYNCPINNED, HNDTYPE_SIZEDREF, }; @@ -1715,9 +1696,6 @@ void Ref_VerifyHandleTable(uint32_t condemned, uint32_t maxgen, ScanContext* sc) #if defined(FEATURE_COMINTEROP) || defined(FEATURE_REDHAWK) HNDTYPE_REFCOUNTED, #endif // FEATURE_COMINTEROP || FEATURE_REDHAWK -#ifdef FEATURE_COMINTEROP - HNDTYPE_WEAK_WINRT, -#endif // FEATURE_COMINTEROP HNDTYPE_ASYNCPINNED, HNDTYPE_SIZEDREF, HNDTYPE_DEPENDENT, diff --git a/src/coreclr/src/vm/appdomain.hpp b/src/coreclr/src/vm/appdomain.hpp index cfd48c859570b..30153f886c31e 100644 --- a/src/coreclr/src/vm/appdomain.hpp +++ b/src/coreclr/src/vm/appdomain.hpp @@ -1098,12 +1098,6 @@ class BaseDomain WRAPPER_NO_CONTRACT; return ::CreateRefcountedHandle(m_handleStore, object); } - - OBJECTHANDLE CreateWinRTWeakHandle(OBJECTREF object, IWeakReference* pWinRTWeakReference) - { - WRAPPER_NO_CONTRACT; - return ::CreateWinRTWeakHandle(m_handleStore, object, pWinRTWeakReference); - } #endif // FEATURE_COMINTEROP OBJECTHANDLE CreateVariableHandle(OBJECTREF object, UINT type) diff --git a/src/coreclr/src/vm/gchandleutilities.h b/src/coreclr/src/vm/gchandleutilities.h index b875644b853b5..5ba9dbf97b19e 100644 --- a/src/coreclr/src/vm/gchandleutilities.h +++ b/src/coreclr/src/vm/gchandleutilities.h @@ -200,20 +200,6 @@ inline OBJECTHANDLE CreateGlobalRefcountedHandle(OBJECTREF object) // Special handle creation convenience functions -#ifdef FEATURE_COMINTEROP -inline OBJECTHANDLE CreateWinRTWeakHandle(IGCHandleStore* store, OBJECTREF object, IWeakReference* pWinRTWeakReference) -{ - OBJECTHANDLE hnd = store->CreateHandleWithExtraInfo(OBJECTREFToObject(object), HNDTYPE_WEAK_WINRT, (void*)pWinRTWeakReference); - if (!hnd) - { - COMPlusThrowOM(); - } - - DiagHandleCreated(hnd, object); - return hnd; -} -#endif // FEATURE_COMINTEROP - // Creates a variable-strength handle inline OBJECTHANDLE CreateVariableHandle(IGCHandleStore* store, OBJECTREF object, uint32_t type) { @@ -362,33 +348,6 @@ inline void DestroyTypedHandle(OBJECTHANDLE handle) GCHandleUtilities::GetGCHandleManager()->DestroyHandleOfUnknownType(handle); } -#ifdef FEATURE_COMINTEROP -inline void DestroyWinRTWeakHandle(OBJECTHANDLE handle) -{ - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - MODE_ANY; - CAN_TAKE_LOCK; - } - CONTRACTL_END; - - // Release the WinRT weak reference if we have one. We're assuming that this will not reenter the - // runtime, since if we are pointing at a managed object, we should not be using HNDTYPE_WEAK_WINRT - // but rather HNDTYPE_WEAK_SHORT or HNDTYPE_WEAK_LONG. - void* pExtraInfo = GCHandleUtilities::GetGCHandleManager()->GetExtraInfoFromHandle(handle); - IWeakReference* pWinRTWeakReference = reinterpret_cast(pExtraInfo); - if (pWinRTWeakReference != nullptr) - { - pWinRTWeakReference->Release(); - } - - DiagHandleDestroyed(handle); - GCHandleUtilities::GetGCHandleManager()->DestroyHandleOfType(handle, HNDTYPE_WEAK_WINRT); -} -#endif - // Handle holders/wrappers #ifndef FEATURE_REDHAWK diff --git a/src/coreclr/src/vm/marshalnative.cpp b/src/coreclr/src/vm/marshalnative.cpp index 2c04c5836bf75..3a426cdc269cb 100644 --- a/src/coreclr/src/vm/marshalnative.cpp +++ b/src/coreclr/src/vm/marshalnative.cpp @@ -558,7 +558,7 @@ FCIMPL2(LPVOID, MarshalNative::GCHandleInternalAlloc, Object *obj, int type) OBJECTREF objRef(obj); - assert(type >= HNDTYPE_WEAK_SHORT && type <= HNDTYPE_WEAK_WINRT); + assert(type >= HNDTYPE_WEAK_SHORT && type <= HNDTYPE_SIZEDREF); if (CORProfilerTrackGC()) { diff --git a/src/coreclr/src/vm/runtimehandles.cpp b/src/coreclr/src/vm/runtimehandles.cpp index bd47cc7280623..f4f58a5259385 100644 --- a/src/coreclr/src/vm/runtimehandles.cpp +++ b/src/coreclr/src/vm/runtimehandles.cpp @@ -1066,7 +1066,7 @@ PVOID QCALLTYPE RuntimeTypeHandle::GetGCHandle(QCall::TypeHandle pTypeHandle, IN GCX_COOP(); TypeHandle th = pTypeHandle.AsTypeHandle(); - assert(handleType >= HNDTYPE_WEAK_SHORT && handleType <= HNDTYPE_WEAK_WINRT); + assert(handleType >= HNDTYPE_WEAK_SHORT && handleType <= HNDTYPE_SIZEDREF); objHandle = AppDomain::GetCurrentDomain()->CreateTypedHandle(NULL, static_cast(handleType)); th.GetLoaderAllocator()->RegisterHandleForCleanup(objHandle); diff --git a/src/coreclr/src/vm/weakreferencenative.cpp b/src/coreclr/src/vm/weakreferencenative.cpp index b1dc825494f35..a9084e24b7348 100644 --- a/src/coreclr/src/vm/weakreferencenative.cpp +++ b/src/coreclr/src/vm/weakreferencenative.cpp @@ -32,48 +32,6 @@ const LPVOID specialWeakReferenceHandles[3] = { 0, 0, 0 }; #define IS_SPECIAL_HANDLE(h) ((size_t)(h) - (size_t)(&specialWeakReferenceHandles) < sizeof(specialWeakReferenceHandles)) -// -// A WeakReference instance can hold one of three types of handles - short or long weak handles, -// or a WinRT weak reference handle. The WinRT weak reference handle has the extra capability -// of recreating an RCW for a COM object which is still alive even though the previous RCW had -// been collected. In order to differentiate this type of handle from the standard weak handles, -// the bottom bit is stolen. -// -// Note that the bit is stolen only in the local copy of the object handle, held in the m_handle -// field of the weak reference object. The handle in the handle table itself does not have its -// bottom bit stolen, and requires using HandleFetchType to determine what type it is. The bit -// is strictly a performance optimization for the weak reference implementation, and it is -// responsible for setting up the bit as it needs and ensuring that it is cleared whenever an -// object handle leaves the weak reference code, for instance to interact with the handle table -// or diagnostics tools. -// -// The following functions are to set, test, and unset that bit before the handle is used. -// - -// Determine if an object handle is a WinRT weak reference handle -bool IsWinRTWeakReferenceHandle(OBJECTHANDLE handle) -{ - STATIC_CONTRACT_LEAF; - return (reinterpret_cast(handle) & 0x1) != 0x0; -} - -// Mark an object handle as being a WinRT weak reference handle -OBJECTHANDLE SetWinRTWeakReferenceHandle(OBJECTHANDLE handle) -{ - STATIC_CONTRACT_LEAF; - - _ASSERTE(!IsWinRTWeakReferenceHandle(handle)); - return reinterpret_cast(reinterpret_cast(handle) | 0x1); -} - -// Get the object handle value even if the object is a WinRT weak reference -OBJECTHANDLE GetHandleValue(OBJECTHANDLE handle) -{ - STATIC_CONTRACT_LEAF; - UINT_PTR mask = ~(static_cast(0x1)); - return reinterpret_cast(reinterpret_cast(handle) & mask); -} - FORCEINLINE OBJECTHANDLE AcquireWeakHandleSpinLock(WEAKREFERENCEREF pThis); FORCEINLINE void ReleaseWeakHandleSpinLock(WEAKREFERENCEREF pThis, OBJECTHANDLE newHandle); @@ -84,7 +42,7 @@ struct WeakHandleSpinLockHolder WEAKREFERENCEREF* pWeakReference; WeakHandleSpinLockHolder(OBJECTHANDLE rawHandle, WEAKREFERENCEREF* weakReference) - : RawHandle(rawHandle), Handle(GetHandleValue(rawHandle)), pWeakReference(weakReference) + : RawHandle(rawHandle), Handle(rawHandle), pWeakReference(weakReference) { STATIC_CONTRACT_LEAF; } @@ -100,219 +58,6 @@ struct WeakHandleSpinLockHolder WeakHandleSpinLockHolder& operator=(const WeakHandleSpinLockHolder& other); }; -#ifdef FEATURE_COMINTEROP - -// Get a WinRT weak reference for the object underlying an RCW if applicable. If the incoming object cannot -// use a WinRT weak reference, nullptr is returned. Otherwise, an AddRef-ed IWeakReference* for the COM -// object underlying the RCW is returned. -// -// In order to qualify to be used with a HNDTYPE_WEAK_WINRT, the incoming object must: -// * be an RCW -// * respond to a QI for IWeakReferenceSource -// * succeed when asked for an IWeakReference* -// -// Note that *pObject should be GC protected on the way into this method -IWeakReference* GetWinRTWeakReference(OBJECTREF* pObject) -{ - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_COOPERATIVE; - PRECONDITION(CheckPointer(pObject)); - } - CONTRACTL_END; - - if (*pObject == NULL) - { - return nullptr; - } - - ASSERT_PROTECTED(pObject); - - MethodTable* pMT = (*pObject)->GetMethodTable(); - - // If the object is not an RCW, then we do not want to use a WinRT weak reference to it - if (!pMT->IsComObjectType()) - { - return nullptr; - } - - // If the object is a managed type deriving from a COM type, then we also do not want to use a WinRT - // weak reference to it. (Otherwise, we'll wind up resolving IWeakReference-s back into the CLR - // when we don't want to have reentrancy). - if (pMT != g_pBaseCOMObject && pMT->IsExtensibleRCW()) - { - return nullptr; - } - - SafeComHolder pWeakReferenceSource(reinterpret_cast(GetComIPFromObjectRef(pObject, IID_IWeakReferenceSource, false /* throwIfNoComIP */))); - if (pWeakReferenceSource == nullptr) - { - return nullptr; - } - - GCX_PREEMP(); - SafeComHolderPreemp pWeakReference; - if (FAILED(pWeakReferenceSource->GetWeakReference(&pWeakReference))) - { - return nullptr; - } - - return pWeakReference.Extract(); -} - -// Given an object handle that stores a WinRT weak reference, attempt to create an RCW -// and store it back in the handle, returning the RCW. If the underlying WinRT object -// is not alive, then the result is NULL. -// -// In order to create a new RCW, we must: -// * Have an m_handle of HNDTYPE_WEAK_WINRT (ie the bottom bit of m_handle is set) -// * Have stored an IWeakReference* in the handle extra info when setting up the handle -// (see GetWinRTWeakReference) -// * The IWeakReference* must respond to a Resolve request for IID_IInspectable -// * -NOINLINE Object* LoadWinRTWeakReferenceTarget(WEAKREFERENCEREF weakReference, TypeHandle targetType, LPVOID __me) -{ - CONTRACTL - { - FCALL_CHECK; - PRECONDITION(weakReference != NULL); - } - CONTRACTL_END; - - struct - { - WEAKREFERENCEREF weakReference; - OBJECTREF rcw; - OBJECTREF target; - } gc; - ZeroMemory(&gc, sizeof(gc)); - gc.weakReference = weakReference; - - FC_INNER_PROLOG_NO_ME_SETUP(); - HELPER_METHOD_FRAME_BEGIN_RET_ATTRIB_PROTECT(Frame::FRAME_ATTR_EXACT_DEPTH|Frame::FRAME_ATTR_CAPTURE_DEPTH_2, gc); - - // Acquire the spin lock to get the IWeakReference* associated with the weak reference. We will then need to - // release the lock while resolving the IWeakReference* since we need to enter preemptive mode while calling out - // to COM to resolve the object and we don't want to do that while holding the lock. If we wind up being able - // to geenrate a new RCW, we'll reacquire the lock to save the RCW in the handle. - // - // Since we're acquiring and releasing the lock multiple times, we need to check the handle state each time we - // reacquire the lock to make sure that another thread hasn't reassigned the target of the handle or finalized it - SafeComHolder pWinRTWeakReference = nullptr; - { - WeakHandleSpinLockHolder handle(AcquireWeakHandleSpinLock(gc.weakReference), &gc.weakReference); - GCX_NOTRIGGER(); - - // Make sure that while we were not holding the spin lock, another thread did not change the target of - // this weak reference. Only fetch the IWeakReference* if we still have a valid handle holding a NULL object - // and the handle is still a HNDTYPE_WEAK_WINRT type handle. - if ((handle.Handle != NULL) && !IS_SPECIAL_HANDLE(handle.Handle)) - { - if (*(Object **)(handle.Handle) != NULL) - { - // While we released the spin lock, another thread already set a new target for the weak reference. - // We don't want to replace it with an RCW that we fetch, so save it to return as the object the - // weak reference is targeting. - gc.target = ObjectToOBJECTREF(*(Object **)(handle.Handle)); - } - else if(IsWinRTWeakReferenceHandle(handle.RawHandle)) - { - _ASSERTE(GCHandleUtilities::GetGCHandleManager()->HandleFetchType(handle.Handle) == HNDTYPE_WEAK_WINRT); - - // Retrieve the associated IWeakReference* for this weak reference. Add a reference to it while we release - // the spin lock so that another thread doesn't release it out from underneath us. - // - // Setting pWinRTWeakReference will claim that it triggers a GC, however that's not true in this case because - // it's always set to NULL here and there's nothing for it to release. - _ASSERTE(pWinRTWeakReference.IsNull()); - CONTRACT_VIOLATION(GCViolation); - IGCHandleManager *mgr = GCHandleUtilities::GetGCHandleManager(); - pWinRTWeakReference = reinterpret_cast(mgr->GetExtraInfoFromHandle(handle.Handle)); - if (!pWinRTWeakReference.IsNull()) - { - pWinRTWeakReference->AddRef(); - } - } - } - } - - // If the weak reference was in a state that it had an IWeakReference* for us to use, then we need to find the IUnknown - // identity of the underlying COM object (assuming that object is still alive). This work is done without holding the - // spin lock since it will call out to arbitrary code and as such we need to switch to preemptive mode. - SafeComHolder pTargetIdentity = nullptr; - if (pWinRTWeakReference != nullptr) - { - _ASSERTE(gc.target == NULL); - - GCX_PREEMP(); - - // Using the IWeakReference*, get ahold of the target WinRT object's IInspectable*. If this resolve fails, then we - // assume that the underlying WinRT object is no longer alive, and thus we cannot create a new RCW for it. - SafeComHolderPreemp pTarget = nullptr; - if (SUCCEEDED(pWinRTWeakReference->Resolve(IID_IInspectable, &pTarget))) - { - if (!pTarget.IsNull()) - { - // Get the IUnknown identity for the underlying object - SafeQueryInterfacePreemp(pTarget, IID_IUnknown, &pTargetIdentity); - } - } - } - - // If we were able to get an IUnkown identity for the object, then we can find or create an associated RCW for it. - if (!pTargetIdentity.IsNull()) - { - GetObjectRefFromComIP(&gc.rcw, pTargetIdentity); - } - - // If we were able to get an RCW, then we need to reacquire the spin lock and store the RCW in the handle. Note that - // it's possible that another thread has acquired the spin lock and set the target of the weak reference while we were - // building the RCW. In that case, we will defer to the hadle that the other thread set, and let the RCW die. - if (gc.rcw != NULL) - { - // Make sure the type we got back from the WinRT object is compatible with the type the managed - // weak reference expects. (For instance, in the WeakReference case, the returned type - // had better be compatible with T). - TypeHandle rcwType(gc.rcw->GetMethodTable()); - if (!rcwType.CanCastTo(targetType)) - { - SString weakReferenceTypeName; - TypeString::AppendType(weakReferenceTypeName, targetType, TypeString::FormatNamespace | TypeString::FormatFullInst | TypeString::FormatAssembly); - - SString resolvedTypeName; - TypeString::AppendType(resolvedTypeName, rcwType, TypeString::FormatNamespace | TypeString::FormatFullInst | TypeString::FormatAssembly); - - COMPlusThrow(kInvalidCastException, IDS_EE_WINRT_WEAKREF_BAD_TYPE, weakReferenceTypeName.GetUnicode(), resolvedTypeName.GetUnicode()); - } - - WeakHandleSpinLockHolder handle(AcquireWeakHandleSpinLock(gc.weakReference), &gc.weakReference); - GCX_NOTRIGGER(); - - - // Now that we've reacquired the lock, see if the handle is still empty. If so, then save the RCW as the new target of the handle. - if ((handle.Handle != NULL) && !IS_SPECIAL_HANDLE(handle.Handle)) - { - _ASSERTE(gc.target == NULL); - gc.target = ObjectToOBJECTREF(*(Object **)(handle.Handle)); - - if (gc.target == NULL) - { - StoreObjectInHandle(handle.Handle, gc.rcw); - gc.target = gc.rcw; - } - } - } - - HELPER_METHOD_FRAME_END(); - FC_INNER_EPILOG(); - - return OBJECTREFToObject(gc.target); -} - -#endif // FEATURE_COMINTEROP - //************************************************************************ // @@ -419,20 +164,9 @@ FCIMPL3(void, WeakReferenceNative::Create, WeakReferenceObject * pThisUNSAFE, Ob _ASSERTE(gc.pThis->GetMethodTable()->CanCastToClass(pWeakReferenceMT)); // Create the handle. -#ifdef FEATURE_COMINTEROP - IWeakReference* pRawWinRTWeakReference = GetWinRTWeakReference(&gc.pTarget); - if (pRawWinRTWeakReference != nullptr) - { - SafeComHolder pWinRTWeakReferenceHolder(pRawWinRTWeakReference); - gc.pThis->m_Handle = SetWinRTWeakReferenceHandle(GetAppDomain()->CreateWinRTWeakHandle(gc.pTarget, pWinRTWeakReferenceHolder)); - pWinRTWeakReferenceHolder.SuppressRelease(); - } - else -#endif // FEATURE_COMINTEROP - { - gc.pThis->m_Handle = GetAppDomain()->CreateTypedHandle(gc.pTarget, - trackResurrection ? HNDTYPE_WEAK_LONG : HNDTYPE_WEAK_SHORT); - } + + gc.pThis->m_Handle = GetAppDomain()->CreateTypedHandle(gc.pTarget, + trackResurrection ? HNDTYPE_WEAK_LONG : HNDTYPE_WEAK_SHORT); HELPER_METHOD_FRAME_END(); } @@ -462,20 +196,10 @@ FCIMPL3(void, WeakReferenceOfTNative::Create, WeakReferenceObject * pThisUNSAFE, _ASSERTE(gc.pThis->GetMethodTable()->GetCanonicalMethodTable() == pWeakReferenceOfTCanonMT); // Create the handle. -#ifdef FEATURE_COMINTEROP - IWeakReference* pRawWinRTWeakReference = GetWinRTWeakReference(&gc.pTarget); - if (pRawWinRTWeakReference != nullptr) - { - SafeComHolder pWinRTWeakReferenceHolder(pRawWinRTWeakReference); - gc.pThis->m_Handle = SetWinRTWeakReferenceHandle(GetAppDomain()->CreateWinRTWeakHandle(gc.pTarget, pWinRTWeakReferenceHolder)); - pWinRTWeakReferenceHolder.SuppressRelease(); - } - else -#endif // FEATURE_COMINTEROP - { - gc.pThis->m_Handle = GetAppDomain()->CreateTypedHandle(gc.pTarget, - trackResurrection ? HNDTYPE_WEAK_LONG : HNDTYPE_WEAK_SHORT); - } + + gc.pThis->m_Handle = GetAppDomain()->CreateTypedHandle(gc.pTarget, + trackResurrection ? HNDTYPE_WEAK_LONG : HNDTYPE_WEAK_SHORT); + HELPER_METHOD_FRAME_END(); } @@ -499,21 +223,15 @@ void FinalizeWeakReference(Object * obj) // The suspension state of the runtime must be prevented from changing while in this function in order for this to be safe. OBJECTHANDLE handle = ThreadSuspend::SysIsSuspended() ? pThis->m_Handle.LoadWithoutBarrier() : AcquireWeakHandleSpinLock(pThis); OBJECTHANDLE handleToDestroy = NULL; - bool isWeakWinRTHandle = false; // Check for not yet constructed or already finalized handle if ((handle != NULL) && !IS_SPECIAL_HANDLE(handle)) { - handleToDestroy = GetHandleValue(handle); + handleToDestroy = handle; // Cache the old handle value HandleType handleType = GCHandleUtilities::GetGCHandleManager()->HandleFetchType(handleToDestroy); -#ifdef FEATURE_COMINTEROP - _ASSERTE(handleType == HNDTYPE_WEAK_LONG || handleType == HNDTYPE_WEAK_SHORT || handleType == HNDTYPE_WEAK_WINRT); - isWeakWinRTHandle = handleType == HNDTYPE_WEAK_WINRT; -#else // !FEATURE_COMINTEROP _ASSERTE(handleType == HNDTYPE_WEAK_LONG || handleType == HNDTYPE_WEAK_SHORT); -#endif // FEATURE_COMINTEROP handle = (handleType == HNDTYPE_WEAK_LONG) ? SPECIAL_HANDLE_FINALIZED_LONG : SPECIAL_HANDLE_FINALIZED_SHORT; @@ -527,16 +245,7 @@ void FinalizeWeakReference(Object * obj) if (handleToDestroy != NULL) { -#ifdef FEATURE_COMINTEROP - if (isWeakWinRTHandle) - { - DestroyWinRTWeakHandle(handleToDestroy); - } - else -#endif // FEATURE_COMINTEROP - { - DestroyTypedHandle(handleToDestroy); - } + DestroyTypedHandle(handleToDestroy); } } @@ -588,7 +297,7 @@ static FORCEINLINE OBJECTREF GetWeakReferenceTarget(WEAKREFERENCEREF pThis) CONTRACTL_END; OBJECTHANDLE rawHandle = pThis->m_Handle.LoadWithoutBarrier(); - OBJECTHANDLE handle = GetHandleValue(rawHandle); + OBJECTHANDLE handle = rawHandle; if (handle == NULL) return NULL; @@ -623,7 +332,7 @@ static FORCEINLINE OBJECTREF GetWeakReferenceTarget(WEAKREFERENCEREF pThis) rawHandle = AcquireWeakHandleSpinLock(pThis); GCX_NOTRIGGER(); - handle = GetHandleValue(rawHandle); + handle = rawHandle; OBJECTREF pTarget = OBJECTREF(*(Object **)(handle)); ReleaseWeakHandleSpinLock(pThis, rawHandle); @@ -643,19 +352,7 @@ FCIMPL1(Object *, WeakReferenceNative::GetTarget, WeakReferenceObject * pThisUNS } OBJECTREF pTarget = GetWeakReferenceTarget(pThis); - -#ifdef FEATURE_COMINTEROP - // If we found an object, or we're not a WinRT weak reference, then we're done. Othewrise - // we can try to create a new RCW to the underlying WinRT object if it's still alive. - if (pTarget != NULL || !IsWinRTWeakReferenceHandle(pThis->m_Handle)) - { - FC_GC_POLL_AND_RETURN_OBJREF(pTarget); - } - - FC_INNER_RETURN(Object*, LoadWinRTWeakReferenceTarget(pThis, g_pObjectClass, GetEEFuncEntryPointMacro(WeakReferenceNative::GetTarget))); -#else // !FEATURE_COMINTEROP FC_GC_POLL_AND_RETURN_OBJREF(pTarget); -#endif // FEATURE_COMINTEROP } FCIMPLEND @@ -671,19 +368,7 @@ FCIMPL1(Object *, WeakReferenceOfTNative::GetTarget, WeakReferenceObject * pThis OBJECTREF pTarget = GetWeakReferenceTarget(pThis); - -#ifdef FEATURE_COMINTEROP - // If we found an object, or we're not a WinRT weak reference, then we're done. Othewrise - // we can try to create a new RCW to the underlying WinRT object if it's still alive. - if (pTarget != NULL || !IsWinRTWeakReferenceHandle(pThis->m_Handle)) - { - FC_GC_POLL_AND_RETURN_OBJREF(pTarget); - } - - FC_INNER_RETURN(Object*, LoadWinRTWeakReferenceTarget(pThis, pThis->GetMethodTable()->GetInstantiation()[0], GetEEFuncEntryPointMacro(WeakReferenceOfTNative::GetTarget))); -#else // !FEATURE_COMINTEROP FC_GC_POLL_AND_RETURN_OBJREF(pTarget); -#endif // FEATURE_COMINTEROP } FCIMPLEND @@ -711,89 +396,6 @@ FCIMPLEND #include -// Slow path helper for setting the target of a weak reference. This code is used if a WinRT weak reference might -// be required. -NOINLINE void SetWeakReferenceTarget(WEAKREFERENCEREF weakReference, OBJECTREF target, LPVOID __me) -{ - FCALL_CONTRACT; - - FC_INNER_PROLOG_NO_ME_SETUP(); - HELPER_METHOD_FRAME_BEGIN_ATTRIB_2(Frame::FRAME_ATTR_EXACT_DEPTH|Frame::FRAME_ATTR_CAPTURE_DEPTH_2, target, weakReference); - -#ifdef FEATURE_COMINTEROP - SafeComHolder pTargetWeakReference(GetWinRTWeakReference(&target)); -#endif // FEATURE_COMINTEROP - - - WeakHandleSpinLockHolder handle(AcquireWeakHandleSpinLock(weakReference), &weakReference); - GCX_NOTRIGGER(); - -#ifdef FEATURE_COMINTEROP - // - // We have four combinations to handle here - // - // Existing target is a GC object, new target is a GC object: - // * Just store the new object in the handle - // - // Existing target is WinRT, new target is WinRT: - // * Release the existing IWeakReference* - // * Store the new IWeakReference* - // * Store the new object in the handle - // - // Existing target is WinRT, new target is GC: - // * Release the existing IWeakReference* - // * Store null to the IWeakReference* field - // * Store the new object in the handle - // - // Existing target is GC, new target is WinRT: - // * Destroy the existing handle - // * Allocate a new WinRT weak handle for the new target - // - - if (IsWinRTWeakReferenceHandle(handle.RawHandle)) - { - // If the existing reference is a WinRT weak reference, we need to release its IWeakReference pointer - // and update it with the new weak reference pointer. If the incoming object is not an RCW that can - // use IWeakReference, then pTargetWeakReference will be null. Therefore, no matter what the incoming - // object type is, we can unconditionally store pTargetWeakReference to the object handle's extra data. - IGCHandleManager *mgr = GCHandleUtilities::GetGCHandleManager(); - IWeakReference* pExistingWeakReference = reinterpret_cast(mgr->GetExtraInfoFromHandle(handle.Handle)); - mgr->SetExtraInfoForHandle(handle.Handle, HNDTYPE_WEAK_WINRT, reinterpret_cast(pTargetWeakReference.GetValue())); - StoreObjectInHandle(handle.Handle, target); - - if (pExistingWeakReference != nullptr) - { - pExistingWeakReference->Release(); - } - } - else if (pTargetWeakReference != nullptr) - { - // The existing handle is not a WinRT weak reference, but we need to store the new object in - // a WinRT weak reference. Therefore we need to destroy the old handle and create a new WinRT - // handle. The new handle needs to be allocated first to prevent the weak reference from holding - // a destroyed handle if we fail to allocate the new one. - _ASSERTE(!IsWinRTWeakReferenceHandle(handle.RawHandle)); - OBJECTHANDLE previousHandle = handle.RawHandle; - - handle.Handle = GetAppDomain()->CreateWinRTWeakHandle(target, pTargetWeakReference); - handle.RawHandle = SetWinRTWeakReferenceHandle(handle.Handle); - - DestroyTypedHandle(previousHandle); - } - else -#endif // FEATURE_COMINTEROP - { - StoreObjectInHandle(handle.Handle, target); - } - -#ifdef FEATURE_COMINTEROP - pTargetWeakReference.SuppressRelease(); -#endif // FEATURE_COMINTEROP - - HELPER_METHOD_FRAME_END(); - FC_INNER_EPILOG(); -} - FCIMPL2(void, WeakReferenceNative::SetTarget, WeakReferenceObject * pThisUNSAFE, Object * pTargetUNSAFE) { FCALL_CONTRACT; @@ -807,10 +409,8 @@ FCIMPL2(void, WeakReferenceNative::SetTarget, WeakReferenceObject * pThisUNSAFE, FCThrowVoid(kNullReferenceException); } - bool storedObject = false; - - OBJECTHANDLE handle = AcquireWeakHandleSpinLock(pThis); { + OBJECTHANDLE handle = AcquireWeakHandleSpinLock(pThis); if (handle == NULL || IS_SPECIAL_HANDLE(handle)) { ReleaseWeakHandleSpinLock(pThis, handle); @@ -820,31 +420,13 @@ FCIMPL2(void, WeakReferenceNative::SetTarget, WeakReferenceObject * pThisUNSAFE, // Switch to no-trigger after the handle was validate. FCThrow triggers. GCX_NOTRIGGER(); - // If the existing handle is a GC weak handle and the new target is not an RCW, then - // we can avoid setting up a helper method frame and just reset the handle directly. - if (!IsWinRTWeakReferenceHandle(handle)) - { - if (pTarget == NULL || !pTarget->GetMethodTable()->IsComObjectType()) - { - StoreObjectInHandle(handle, pTarget); - storedObject = true; - } - } + StoreObjectInHandle(handle, pTarget); - // SetWeakReferenceTarget will reacquire the spinlock after setting up a helper method frame. This allows - // the frame setup to throw without worrying about leaking the spinlock, and allows the epilog to be cleanly - // walked by the epilog decoder. ReleaseWeakHandleSpinLock(pThis, handle); } - // If we reset the handle directly, then early out before setting up a helper method frame - if (storedObject) - { - FC_GC_POLL(); - return; - } - - FC_INNER_RETURN_VOID(SetWeakReferenceTarget(pThis, pTarget, GetEEFuncEntryPointMacro(WeakReferenceNative::SetTarget))); + FC_GC_POLL(); + return; } FCIMPLEND @@ -860,10 +442,8 @@ FCIMPL2(void, WeakReferenceOfTNative::SetTarget, WeakReferenceObject * pThisUNSA FCThrowVoid(kNullReferenceException); } - bool storedObject = false; - - OBJECTHANDLE handle = AcquireWeakHandleSpinLock(pThis); { + OBJECTHANDLE handle = AcquireWeakHandleSpinLock(pThis); if (handle == NULL || IS_SPECIAL_HANDLE(handle)) { ReleaseWeakHandleSpinLock(pThis, handle); @@ -872,32 +452,13 @@ FCIMPL2(void, WeakReferenceOfTNative::SetTarget, WeakReferenceObject * pThisUNSA // Switch to no-trigger after the handle was validate. FCThrow triggers. GCX_NOTRIGGER(); + StoreObjectInHandle(handle, pTarget); - // If the existing handle is a GC weak handle and the new target is not an RCW, then - // we can avoid setting up a helper method frame and just reset the handle directly. - if (!IsWinRTWeakReferenceHandle(handle)) - { - if (pTarget == NULL || !pTarget->GetMethodTable()->IsComObjectType()) - { - StoreObjectInHandle(handle, pTarget); - storedObject = true; - } - } - - // SetWeakReferenceTarget will reacquire the spinlock after setting up a helper method frame. This allows - // the frame setup to throw without worrying about leaking the spinlock, and allows the epilog to be cleanly - // walked by the epilog decoder. ReleaseWeakHandleSpinLock(pThis, handle); } - // If we reset the handle directly, then early out before setting up a helper method frame - if (storedObject) - { - FC_GC_POLL(); - return; - } - - FC_INNER_RETURN_VOID(SetWeakReferenceTarget(pThis, pTarget, GetEEFuncEntryPointMacro(WeakReferenceOfTNative::SetTarget))); + FC_GC_POLL(); + return; } FCIMPLEND @@ -933,7 +494,7 @@ FCIMPL1(FC_BOOL_RET, WeakReferenceNative::IsTrackResurrection, WeakReferenceObje } else { - trackResurrection = GCHandleUtilities::GetGCHandleManager()->HandleFetchType(GetHandleValue(handle)) == HNDTYPE_WEAK_LONG; + trackResurrection = GCHandleUtilities::GetGCHandleManager()->HandleFetchType(handle) == HNDTYPE_WEAK_LONG; } ReleaseWeakHandleSpinLock(pThis, handle); @@ -971,7 +532,7 @@ FCIMPL1(FC_BOOL_RET, WeakReferenceOfTNative::IsTrackResurrection, WeakReferenceO } else { - trackResurrection = GCHandleUtilities::GetGCHandleManager()->HandleFetchType(GetHandleValue(handle)) == HNDTYPE_WEAK_LONG; + trackResurrection = GCHandleUtilities::GetGCHandleManager()->HandleFetchType(handle) == HNDTYPE_WEAK_LONG; } ReleaseWeakHandleSpinLock(pThis, handle);