diff options
Diffstat (limited to 'src/vm/gchandleutilities.h')
-rw-r--r-- | src/vm/gchandleutilities.h | 495 |
1 files changed, 495 insertions, 0 deletions
diff --git a/src/vm/gchandleutilities.h b/src/vm/gchandleutilities.h new file mode 100644 index 0000000000..665c1da453 --- /dev/null +++ b/src/vm/gchandleutilities.h @@ -0,0 +1,495 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#ifndef _GCHANDLEUTILITIES_H_ +#define _GCHANDLEUTILITIES_H_ + +#include "gcinterface.h" + +#ifdef FEATURE_COMINTEROP +#include <weakreference.h> +#endif + +extern "C" IGCHandleManager* g_pGCHandleManager; + +class GCHandleUtilities +{ +public: + // Retrieves the GC handle table. + static IGCHandleManager* GetGCHandleManager() + { + LIMITED_METHOD_CONTRACT; + + assert(g_pGCHandleManager != nullptr); + return g_pGCHandleManager; + } + +private: + // This class should never be instantiated. + GCHandleUtilities() = delete; +}; + +void ValidateObjectAndAppDomain(OBJECTREF objRef, ADIndex appDomainIndex); +void ValidateHandleAssignment(OBJECTHANDLE handle, OBJECTREF objRef); + +// Given a handle, returns an OBJECTREF for the object it refers to. +inline OBJECTREF ObjectFromHandle(OBJECTHANDLE handle) +{ + _ASSERTE(handle); + +#ifdef _DEBUG_IMPL + DWORD context = (DWORD)GCHandleUtilities::GetGCHandleManager()->GetHandleContext(handle); + OBJECTREF objRef = ObjectToOBJECTREF(*(Object**)handle); + + ValidateObjectAndAppDomain(objRef, ADIndex(context)); +#endif // _DEBUG_IMPL + + // Wrap the raw OBJECTREF and return it + return UNCHECKED_OBJECTREF_TO_OBJECTREF(*PTR_UNCHECKED_OBJECTREF(handle)); +} + +// Quick inline check for whether a handle is null +inline BOOL IsHandleNullUnchecked(OBJECTHANDLE handle) +{ + LIMITED_METHOD_CONTRACT; + + return (handle == NULL || (*(_UNCHECKED_OBJECTREF *)handle) == NULL); +} + +inline BOOL ObjectHandleIsNull(OBJECTHANDLE handle) +{ + LIMITED_METHOD_CONTRACT; + + return *(Object **)handle == NULL; +} + +#ifndef DACCESS_COMPILE + +// Handle creation convenience functions + +inline OBJECTHANDLE CreateHandle(IGCHandleStore* store, OBJECTREF object) +{ + OBJECTHANDLE hnd = store->CreateHandleOfType(OBJECTREFToObject(object), HNDTYPE_DEFAULT); + if (!hnd) + { + COMPlusThrowOM(); + } + + return hnd; +} + +inline OBJECTHANDLE CreateWeakHandle(IGCHandleStore* store, OBJECTREF object) +{ + OBJECTHANDLE hnd = store->CreateHandleOfType(OBJECTREFToObject(object), HNDTYPE_WEAK_DEFAULT); + if (!hnd) + { + COMPlusThrowOM(); + } + + return hnd; +} + +inline OBJECTHANDLE CreateShortWeakHandle(IGCHandleStore* store, OBJECTREF object) +{ + OBJECTHANDLE hnd = store->CreateHandleOfType(OBJECTREFToObject(object), HNDTYPE_WEAK_SHORT); + if (!hnd) + { + COMPlusThrowOM(); + } + + return hnd; +} + +inline OBJECTHANDLE CreateLongWeakHandle(IGCHandleStore* store, OBJECTREF object) +{ + OBJECTHANDLE hnd = store->CreateHandleOfType(OBJECTREFToObject(object), HNDTYPE_WEAK_LONG); + if (!hnd) + { + COMPlusThrowOM(); + } + + return hnd; +} + +inline OBJECTHANDLE CreateStrongHandle(IGCHandleStore* store, OBJECTREF object) +{ + OBJECTHANDLE hnd = store->CreateHandleOfType(OBJECTREFToObject(object), HNDTYPE_STRONG); + if (!hnd) + { + COMPlusThrowOM(); + } + + return hnd; +} + +inline OBJECTHANDLE CreatePinningHandle(IGCHandleStore* store, OBJECTREF object) +{ + OBJECTHANDLE hnd = store->CreateHandleOfType(OBJECTREFToObject(object), HNDTYPE_PINNED); + if (!hnd) + { + COMPlusThrowOM(); + } + + return hnd; +} + +inline OBJECTHANDLE CreateAsyncPinningHandle(IGCHandleStore* store, OBJECTREF object) +{ + OBJECTHANDLE hnd = store->CreateHandleOfType(OBJECTREFToObject(object), HNDTYPE_ASYNCPINNED); + if (!hnd) + { + COMPlusThrowOM(); + } + + return hnd; +} + +inline OBJECTHANDLE CreateRefcountedHandle(IGCHandleStore* store, OBJECTREF object) +{ + OBJECTHANDLE hnd = store->CreateHandleOfType(OBJECTREFToObject(object), HNDTYPE_REFCOUNTED); + if (!hnd) + { + COMPlusThrowOM(); + } + + return hnd; +} + +inline OBJECTHANDLE CreateSizedRefHandle(IGCHandleStore* store, OBJECTREF object) +{ + OBJECTHANDLE hnd = store->CreateHandleOfType(OBJECTREFToObject(object), HNDTYPE_SIZEDREF); + if (!hnd) + { + COMPlusThrowOM(); + } + + return hnd; +} + +inline OBJECTHANDLE CreateSizedRefHandle(IGCHandleStore* store, OBJECTREF object, int heapToAffinitizeTo) +{ + OBJECTHANDLE hnd = store->CreateHandleOfType(OBJECTREFToObject(object), HNDTYPE_SIZEDREF, heapToAffinitizeTo); + if (!hnd) + { + COMPlusThrowOM(); + } + + return hnd; +} + +// Global handle creation convenience functions + +inline OBJECTHANDLE CreateGlobalHandle(OBJECTREF object) +{ + CONDITIONAL_CONTRACT_VIOLATION(ModeViolation, object == NULL); + OBJECTHANDLE hnd = GCHandleUtilities::GetGCHandleManager()->CreateGlobalHandleOfType(OBJECTREFToObject(object), HNDTYPE_DEFAULT); + if (!hnd) + { + COMPlusThrowOM(); + } + + return hnd; +} + +inline OBJECTHANDLE CreateGlobalWeakHandle(OBJECTREF object) +{ + OBJECTHANDLE hnd = GCHandleUtilities::GetGCHandleManager()->CreateGlobalHandleOfType(OBJECTREFToObject(object), HNDTYPE_WEAK_DEFAULT); + if (!hnd) + { + COMPlusThrowOM(); + } + + return hnd; +} + +inline OBJECTHANDLE CreateGlobalShortWeakHandle(OBJECTREF object) +{ + CONDITIONAL_CONTRACT_VIOLATION(ModeViolation, object == NULL); + OBJECTHANDLE hnd = GCHandleUtilities::GetGCHandleManager()->CreateGlobalHandleOfType(OBJECTREFToObject(object), HNDTYPE_WEAK_SHORT); + if (!hnd) + { + COMPlusThrowOM(); + } + + return hnd; +} + +inline OBJECTHANDLE CreateGlobalLongWeakHandle(OBJECTREF object) +{ + OBJECTHANDLE hnd = GCHandleUtilities::GetGCHandleManager()->CreateGlobalHandleOfType(OBJECTREFToObject(object), HNDTYPE_WEAK_LONG); + if (!hnd) + { + COMPlusThrowOM(); + } + + return hnd; +} + +inline OBJECTHANDLE CreateGlobalStrongHandle(OBJECTREF object) +{ + CONDITIONAL_CONTRACT_VIOLATION(ModeViolation, object == NULL); + OBJECTHANDLE hnd = GCHandleUtilities::GetGCHandleManager()->CreateGlobalHandleOfType(OBJECTREFToObject(object), HNDTYPE_STRONG); + if (!hnd) + { + COMPlusThrowOM(); + } + + return hnd; +} + +inline OBJECTHANDLE CreateGlobalPinningHandle(OBJECTREF object) +{ + OBJECTHANDLE hnd = GCHandleUtilities::GetGCHandleManager()->CreateGlobalHandleOfType(OBJECTREFToObject(object), HNDTYPE_PINNED); + if (!hnd) + { + COMPlusThrowOM(); + } + + return hnd; +} + +inline OBJECTHANDLE CreateGlobalRefcountedHandle(OBJECTREF object) +{ + OBJECTHANDLE hnd = GCHandleUtilities::GetGCHandleManager()->CreateGlobalHandleOfType(OBJECTREFToObject(object), HNDTYPE_REFCOUNTED); + if (!hnd) + { + COMPlusThrowOM(); + } + + return hnd; +} + +// 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(); + } + + return hnd; +} +#endif // FEATURE_COMINTEROP + +// Creates a variable-strength handle +inline OBJECTHANDLE CreateVariableHandle(IGCHandleStore* store, OBJECTREF object, uint32_t type) +{ + OBJECTHANDLE hnd = store->CreateHandleWithExtraInfo(OBJECTREFToObject(object), HNDTYPE_VARIABLE, (void*)((uintptr_t)type)); + if (!hnd) + { + COMPlusThrowOM(); + } + + return hnd; +} + +// Handle object manipulation convenience functions + +inline void StoreObjectInHandle(OBJECTHANDLE handle, OBJECTREF object) +{ + ValidateHandleAssignment(handle, object); + + GCHandleUtilities::GetGCHandleManager()->StoreObjectInHandle(handle, OBJECTREFToObject(object)); +} + +inline bool StoreFirstObjectInHandle(OBJECTHANDLE handle, OBJECTREF object) +{ + ValidateHandleAssignment(handle, object); + + return GCHandleUtilities::GetGCHandleManager()->StoreObjectInHandleIfNull(handle, OBJECTREFToObject(object)); +} + +inline void* InterlockedCompareExchangeObjectInHandle(OBJECTHANDLE handle, OBJECTREF object, OBJECTREF comparandObject) +{ + ValidateHandleAssignment(handle, object); + + return GCHandleUtilities::GetGCHandleManager()->InterlockedCompareExchangeObjectInHandle(handle, OBJECTREFToObject(object), OBJECTREFToObject(comparandObject)); +} + +inline void ResetOBJECTHANDLE(OBJECTHANDLE handle) +{ + GCHandleUtilities::GetGCHandleManager()->StoreObjectInHandle(handle, NULL); +} + +// Handle destruction convenience functions + +inline void DestroyHandle(OBJECTHANDLE handle) +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + MODE_ANY; + CAN_TAKE_LOCK; + SO_TOLERANT; + } + CONTRACTL_END; + + GCHandleUtilities::GetGCHandleManager()->DestroyHandleOfType(handle, HNDTYPE_DEFAULT); +} + +inline void DestroyWeakHandle(OBJECTHANDLE handle) +{ + GCHandleUtilities::GetGCHandleManager()->DestroyHandleOfType(handle, HNDTYPE_WEAK_DEFAULT); +} + +inline void DestroyShortWeakHandle(OBJECTHANDLE handle) +{ + GCHandleUtilities::GetGCHandleManager()->DestroyHandleOfType(handle, HNDTYPE_WEAK_SHORT); +} + +inline void DestroyLongWeakHandle(OBJECTHANDLE handle) +{ + GCHandleUtilities::GetGCHandleManager()->DestroyHandleOfType(handle, HNDTYPE_WEAK_LONG); +} + +inline void DestroyStrongHandle(OBJECTHANDLE handle) +{ + GCHandleUtilities::GetGCHandleManager()->DestroyHandleOfType(handle, HNDTYPE_STRONG); +} + +inline void DestroyPinningHandle(OBJECTHANDLE handle) +{ + GCHandleUtilities::GetGCHandleManager()->DestroyHandleOfType(handle, HNDTYPE_PINNED); +} + +inline void DestroyAsyncPinningHandle(OBJECTHANDLE handle) +{ + GCHandleUtilities::GetGCHandleManager()->DestroyHandleOfType(handle, HNDTYPE_ASYNCPINNED); +} + +inline void DestroyRefcountedHandle(OBJECTHANDLE handle) +{ + GCHandleUtilities::GetGCHandleManager()->DestroyHandleOfType(handle, HNDTYPE_REFCOUNTED); +} + +inline void DestroyDependentHandle(OBJECTHANDLE handle) +{ + GCHandleUtilities::GetGCHandleManager()->DestroyHandleOfType(handle, HNDTYPE_DEPENDENT); +} + +inline void DestroyVariableHandle(OBJECTHANDLE handle) +{ + GCHandleUtilities::GetGCHandleManager()->DestroyHandleOfType(handle, HNDTYPE_VARIABLE); +} + +inline void DestroyGlobalHandle(OBJECTHANDLE handle) +{ + GCHandleUtilities::GetGCHandleManager()->DestroyHandleOfType(handle, HNDTYPE_DEFAULT); +} + +inline void DestroyGlobalWeakHandle(OBJECTHANDLE handle) +{ + GCHandleUtilities::GetGCHandleManager()->DestroyHandleOfType(handle, HNDTYPE_WEAK_DEFAULT); +} + +inline void DestroyGlobalShortWeakHandle(OBJECTHANDLE handle) +{ + GCHandleUtilities::GetGCHandleManager()->DestroyHandleOfType(handle, HNDTYPE_WEAK_SHORT); +} + +inline void DestroyGlobalLongWeakHandle(OBJECTHANDLE handle) +{ + GCHandleUtilities::GetGCHandleManager()->DestroyHandleOfType(handle, HNDTYPE_WEAK_LONG); +} + +inline void DestroyGlobalStrongHandle(OBJECTHANDLE handle) +{ + GCHandleUtilities::GetGCHandleManager()->DestroyHandleOfType(handle, HNDTYPE_STRONG); +} + +inline void DestroyGlobalPinningHandle(OBJECTHANDLE handle) +{ + GCHandleUtilities::GetGCHandleManager()->DestroyHandleOfType(handle, HNDTYPE_PINNED); +} + +inline void DestroyGlobalRefcountedHandle(OBJECTHANDLE handle) +{ + GCHandleUtilities::GetGCHandleManager()->DestroyHandleOfType(handle, HNDTYPE_REFCOUNTED); +} + +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; + SO_TOLERANT; + } + 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<IWeakReference*>(pExtraInfo); + if (pWinRTWeakReference != nullptr) + { + pWinRTWeakReference->Release(); + } + + GCHandleUtilities::GetGCHandleManager()->DestroyHandleOfType(handle, HNDTYPE_WEAK_WINRT); +} +#endif + +// Handle holders/wrappers + +#ifndef FEATURE_REDHAWK +typedef Wrapper<OBJECTHANDLE, DoNothing<OBJECTHANDLE>, DestroyHandle> OHWrapper; +typedef Wrapper<OBJECTHANDLE, DoNothing<OBJECTHANDLE>, DestroyPinningHandle, NULL> PinningHandleHolder; +typedef Wrapper<OBJECTHANDLE, DoNothing<OBJECTHANDLE>, DestroyAsyncPinningHandle, NULL> AsyncPinningHandleHolder; +typedef Wrapper<OBJECTHANDLE, DoNothing<OBJECTHANDLE>, DestroyRefcountedHandle> RefCountedOHWrapper; + +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>, ResetOBJECTHANDLE> ObjectInHandleHolder; + +class RCOBJECTHANDLEHolder : public RefCountedOHWrapper +{ +public: + FORCEINLINE RCOBJECTHANDLEHolder(OBJECTHANDLE p = NULL) : RefCountedOHWrapper(p) + { + LIMITED_METHOD_CONTRACT; + } + FORCEINLINE void operator=(OBJECTHANDLE p) + { + WRAPPER_NO_CONTRACT; + + RefCountedOHWrapper::operator=(p); + } +}; + +class OBJECTHANDLEHolder : public OHWrapper +{ +public: + FORCEINLINE OBJECTHANDLEHolder(OBJECTHANDLE p = NULL) : OHWrapper(p) + { + LIMITED_METHOD_CONTRACT; + } + FORCEINLINE void operator=(OBJECTHANDLE p) + { + WRAPPER_NO_CONTRACT; + + OHWrapper::operator=(p); + } +}; + +#endif // !FEATURE_REDHAWK + +#endif // !DACCESS_COMPILE + +#endif // _GCHANDLEUTILITIES_H_ + |