1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4//
5
6#include "common.h"
7#include "gcenv.h"
8#include "gchandletableimpl.h"
9#include "objecthandle.h"
10#include "handletablepriv.h"
11
12GCHandleStore* g_gcGlobalHandleStore;
13
14IGCHandleManager* CreateGCHandleManager()
15{
16 return new (nothrow) GCHandleManager();
17}
18
19void GCHandleStore::Uproot()
20{
21 Ref_RemoveHandleTableBucket(&_underlyingBucket);
22}
23
24bool GCHandleStore::ContainsHandle(OBJECTHANDLE handle)
25{
26 return _underlyingBucket.Contains(handle);
27}
28
29OBJECTHANDLE GCHandleStore::CreateHandleOfType(Object* object, HandleType type)
30{
31 HHANDLETABLE handletable = _underlyingBucket.pTable[GetCurrentThreadHomeHeapNumber()];
32 return ::HndCreateHandle(handletable, type, ObjectToOBJECTREF(object));
33}
34
35OBJECTHANDLE GCHandleStore::CreateHandleOfType(Object* object, HandleType type, int heapToAffinitizeTo)
36{
37 HHANDLETABLE handletable = _underlyingBucket.pTable[heapToAffinitizeTo];
38 return ::HndCreateHandle(handletable, type, ObjectToOBJECTREF(object));
39}
40
41OBJECTHANDLE GCHandleStore::CreateHandleWithExtraInfo(Object* object, HandleType type, void* pExtraInfo)
42{
43 HHANDLETABLE handletable = _underlyingBucket.pTable[GetCurrentThreadHomeHeapNumber()];
44 return ::HndCreateHandle(handletable, type, ObjectToOBJECTREF(object), reinterpret_cast<uintptr_t>(pExtraInfo));
45}
46
47OBJECTHANDLE GCHandleStore::CreateDependentHandle(Object* primary, Object* secondary)
48{
49 HHANDLETABLE handletable = _underlyingBucket.pTable[GetCurrentThreadHomeHeapNumber()];
50 OBJECTHANDLE handle = ::HndCreateHandle(handletable, HNDTYPE_DEPENDENT, ObjectToOBJECTREF(primary));
51 if (!handle)
52 {
53 return nullptr;
54 }
55
56 ::SetDependentHandleSecondary(handle, ObjectToOBJECTREF(secondary));
57 return handle;
58}
59
60void GCHandleStore::RelocateAsyncPinnedHandles(IGCHandleStore* pTarget, void (*clearIfComplete)(Object*), void (*setHandle)(Object*, OBJECTHANDLE))
61{
62 // assumption - the IGCHandleStore is an instance of GCHandleStore
63 GCHandleStore* other = static_cast<GCHandleStore*>(pTarget);
64 ::Ref_RelocateAsyncPinHandles(&_underlyingBucket, &other->_underlyingBucket, clearIfComplete, setHandle);
65}
66
67bool GCHandleStore::EnumerateAsyncPinnedHandles(async_pin_enum_fn callback, void* context)
68{
69 return !!::Ref_HandleAsyncPinHandles(callback, context);
70}
71
72GCHandleStore::~GCHandleStore()
73{
74 ::Ref_DestroyHandleTableBucket(&_underlyingBucket);
75}
76
77bool GCHandleManager::Initialize()
78{
79 return Ref_Initialize();
80}
81
82void GCHandleManager::Shutdown()
83{
84 if (g_gcGlobalHandleStore != nullptr)
85 {
86 DestroyHandleStore(g_gcGlobalHandleStore);
87 }
88
89 ::Ref_Shutdown();
90}
91
92IGCHandleStore* GCHandleManager::GetGlobalHandleStore()
93{
94 return g_gcGlobalHandleStore;
95}
96
97IGCHandleStore* GCHandleManager::CreateHandleStore(void* context)
98{
99#ifndef FEATURE_REDHAWK
100 GCHandleStore* store = new (nothrow) GCHandleStore();
101 if (store == nullptr)
102 {
103 return nullptr;
104 }
105
106 bool success = ::Ref_InitializeHandleTableBucket(&store->_underlyingBucket, context);
107 if (!success)
108 {
109 delete store;
110 return nullptr;
111 }
112
113 return store;
114#else
115 assert("CreateHandleStore is not implemented when FEATURE_REDHAWK is defined!");
116 return nullptr;
117#endif
118}
119
120void GCHandleManager::DestroyHandleStore(IGCHandleStore* store)
121{
122 delete store;
123}
124
125void* GCHandleManager::GetHandleContext(OBJECTHANDLE handle)
126{
127 return (void*)((uintptr_t)::HndGetHandleTableADIndex(::HndGetHandleTable(handle)).m_dwIndex);
128}
129
130OBJECTHANDLE GCHandleManager::CreateGlobalHandleOfType(Object* object, HandleType type)
131{
132 return ::HndCreateHandle(g_HandleTableMap.pBuckets[0]->pTable[GetCurrentThreadHomeHeapNumber()], type, ObjectToOBJECTREF(object));
133}
134
135OBJECTHANDLE GCHandleManager::CreateDuplicateHandle(OBJECTHANDLE handle)
136{
137 return ::HndCreateHandle(HndGetHandleTable(handle), HNDTYPE_DEFAULT, ::HndFetchHandle(handle));
138}
139
140void GCHandleManager::DestroyHandleOfType(OBJECTHANDLE handle, HandleType type)
141{
142 ::HndDestroyHandle(::HndGetHandleTable(handle), type, handle);
143}
144
145void GCHandleManager::DestroyHandleOfUnknownType(OBJECTHANDLE handle)
146{
147 ::HndDestroyHandleOfUnknownType(::HndGetHandleTable(handle), handle);
148}
149
150void GCHandleManager::SetExtraInfoForHandle(OBJECTHANDLE handle, HandleType type, void* pExtraInfo)
151{
152 ::HndSetHandleExtraInfo(handle, type, (uintptr_t)pExtraInfo);
153}
154
155void* GCHandleManager::GetExtraInfoFromHandle(OBJECTHANDLE handle)
156{
157 return (void*)::HndGetHandleExtraInfo(handle);
158}
159
160void GCHandleManager::StoreObjectInHandle(OBJECTHANDLE handle, Object* object)
161{
162 ::HndAssignHandle(handle, ObjectToOBJECTREF(object));
163}
164
165bool GCHandleManager::StoreObjectInHandleIfNull(OBJECTHANDLE handle, Object* object)
166{
167 return !!::HndFirstAssignHandle(handle, ObjectToOBJECTREF(object));
168}
169
170void GCHandleManager::SetDependentHandleSecondary(OBJECTHANDLE handle, Object* object)
171{
172 ::SetDependentHandleSecondary(handle, ObjectToOBJECTREF(object));
173}
174
175Object* GCHandleManager::GetDependentHandleSecondary(OBJECTHANDLE handle)
176{
177 return OBJECTREFToObject(::GetDependentHandleSecondary(handle));
178}
179
180Object* GCHandleManager::InterlockedCompareExchangeObjectInHandle(OBJECTHANDLE handle, Object* object, Object* comparandObject)
181{
182 return (Object*)::HndInterlockedCompareExchangeHandle(handle, ObjectToOBJECTREF(object), ObjectToOBJECTREF(comparandObject));
183}
184
185HandleType GCHandleManager::HandleFetchType(OBJECTHANDLE handle)
186{
187 uint32_t type = ::HandleFetchType(handle);
188 assert(type >= HNDTYPE_WEAK_SHORT && type <= HNDTYPE_WEAK_WINRT);
189 return static_cast<HandleType>(type);
190}
191
192void GCHandleManager::TraceRefCountedHandles(HANDLESCANPROC callback, uintptr_t param1, uintptr_t param2)
193{
194 ::Ref_TraceRefCountHandles(callback, param1, param2);
195}
196
197