summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Gillespie <segilles@microsoft.com>2017-07-20 21:53:46 -0700
committerGitHub <noreply@github.com>2017-07-20 21:53:46 -0700
commit0372174871c1e27f483c9877c2c5181720be8722 (patch)
tree16cbb72c8c7b95c9fff92e4e1fec329ae431a2e2
parentfa3d1cdd5583d5b278dd1a9c246ff30ca6966973 (diff)
downloadcoreclr-0372174871c1e27f483c9877c2c5181720be8722.tar.gz
coreclr-0372174871c1e27f483c9877c2c5181720be8722.tar.bz2
coreclr-0372174871c1e27f483c9877c2c5181720be8722.zip
[Local GC] Refactor usage of GC-internal functions in the DAC (#12458)
* Refactor usage of GC-internal functions in the DAC * Fix one debugger test failure, one to go
-rw-r--r--src/debug/daccess/daccess.cpp11
-rw-r--r--src/debug/daccess/dacdbiimpl.cpp2
-rw-r--r--src/debug/daccess/dacimpl.h7
-rw-r--r--src/debug/daccess/gcinterface.dac.h49
-rw-r--r--src/debug/daccess/request.cpp6
-rw-r--r--src/gc/gc.h2
-rw-r--r--src/gc/gccommon.cpp3
-rw-r--r--src/gc/gcinterface.dac.h61
-rw-r--r--src/gc/gcinterface.dacvars.def1
-rw-r--r--src/gc/handletable.cpp6
-rw-r--r--src/gc/handletable.h10
-rw-r--r--src/gc/handletablepriv.h13
-rw-r--r--src/gc/objecthandle.cpp17
-rw-r--r--src/gc/objecthandle.h5
-rw-r--r--src/inc/dacvars.h1
-rw-r--r--src/vm/CMakeLists.txt14
-rw-r--r--src/vm/gchandleutilities.h5
17 files changed, 164 insertions, 49 deletions
diff --git a/src/debug/daccess/daccess.cpp b/src/debug/daccess/daccess.cpp
index 14ce251bfc..9d371ceff7 100644
--- a/src/debug/daccess/daccess.cpp
+++ b/src/debug/daccess/daccess.cpp
@@ -29,6 +29,7 @@
#endif
#include "dwbucketmanager.hpp"
+#include "gcinterface.dac.h"
// To include definiton of IsThrowableThreadAbortException
// #include <exstatecommon.h>
@@ -7932,8 +7933,6 @@ STDAPI OutOfProcessExceptionEventDebuggerLaunchCallback(__in PDWORD pContext,
// DacHandleEnum
-// TODO(Local GC) - The DAC should not include GC headers
-#include "../../gc/handletablepriv.h"
#include "comcallablewrapper.h"
DacHandleWalker::DacHandleWalker()
@@ -7987,7 +7986,7 @@ HRESULT DacHandleWalker::Init(UINT32 typemask)
{
SUPPORTS_DAC;
- mMap = &g_HandleTableMap;
+ mMap = g_gcDacGlobals->handle_table_map;
mTypeMask = typemask;
return S_OK;
@@ -8065,7 +8064,7 @@ bool DacHandleWalker::FetchMoreHandles(HANDLESCANPROC callback)
{
for (int i = 0; i < max_slots; ++i)
{
- HHANDLETABLE hTable = mMap->pBuckets[mIndex]->pTable[i];
+ DPTR(dac_handle_table) hTable = mMap->pBuckets[mIndex]->pTable[i];
if (hTable)
{
// Yikes! The handle table callbacks don't produce the handle type or
@@ -8079,8 +8078,8 @@ bool DacHandleWalker::FetchMoreHandles(HANDLESCANPROC callback)
{
if (mask & 1)
{
- HandleTable *pTable = (HandleTable *)hTable;
- PTR_AppDomain pDomain = SystemDomain::GetAppDomainAtIndex(pTable->uADIndex);
+ dac_handle_table *pTable = hTable;
+ PTR_AppDomain pDomain = SystemDomain::GetAppDomainAtIndex(ADIndex(pTable->uADIndex));
param.AppDomain = TO_CDADDR(pDomain.GetAddr());
param.Type = handleType;
diff --git a/src/debug/daccess/dacdbiimpl.cpp b/src/debug/daccess/dacdbiimpl.cpp
index f48ecc0bd0..f274e703a2 100644
--- a/src/debug/daccess/dacdbiimpl.cpp
+++ b/src/debug/daccess/dacdbiimpl.cpp
@@ -5716,7 +5716,7 @@ BOOL DacDbiInterfaceImpl::IsVmObjectHandleValid(VMPTR_OBJECTHANDLE vmHandle)
// SEH exceptions will be caught
EX_TRY
{
- OBJECTREF objRef = HndFetchHandle((OBJECTHANDLE)vmHandle.GetDacPtr());
+ OBJECTREF objRef = ObjectFromHandle((OBJECTHANDLE)vmHandle.GetDacPtr());
// NULL is certainly valid...
if (objRef != NULL)
diff --git a/src/debug/daccess/dacimpl.h b/src/debug/daccess/dacimpl.h
index c3a1c46f68..c37face4e6 100644
--- a/src/debug/daccess/dacimpl.h
+++ b/src/debug/daccess/dacimpl.h
@@ -14,10 +14,7 @@
#ifndef __DACIMPL_H__
#define __DACIMPL_H__
-// This header include will need to be removed as part of GitHub#12170.
-// The only reason it's here now is that this header references the GC-private
-// structure "HandleTableMap".
-#include "../../gc/objecthandle.h"
+#include "gcinterface.dac.h"
#if defined(_TARGET_ARM_) || defined(FEATURE_CORESYSTEM) // @ARMTODO: STL breaks the build with current VC headers
//---------------------------------------------------------------------------------------
@@ -2242,7 +2239,7 @@ private:
ULONG32 m_instanceAge;
// Handle table walking variables.
- HandleTableMap *mMap;
+ dac_handle_table_map *mMap;
int mIndex;
UINT32 mTypeMask;
int mGenerationFilter;
diff --git a/src/debug/daccess/gcinterface.dac.h b/src/debug/daccess/gcinterface.dac.h
index 031ec36f30..c7765ef364 100644
--- a/src/debug/daccess/gcinterface.dac.h
+++ b/src/debug/daccess/gcinterface.dac.h
@@ -1,5 +1,54 @@
// 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 __DACCESS_GCINTERFACE_DAC_H__
+#define __DACCESS_GCINTERFACE_DAC_H__
#include "../../gc/gcinterface.dac.h"
+
+// The following six function prototypes are for functions that are used by the DAC
+// to inspect the handle table in detail. The semantics of these functions MUST be
+// versioned along with the rest of this interface - any changes in semantics
+// must be accompanied with a major versino bump.
+//
+// Please do not add any additional functions to this list; we'd like to keep it
+// to an absolute minimum.
+#ifdef DACCESS_COMPILE
+// for DAC builds, OBJECTHANDLE is a uintptr_t.
+GC_DAC_VISIBLE
+OBJECTREF GetDependentHandleSecondary(OBJECTHANDLE handle);
+
+GC_DAC_VISIBLE_NO_MANGLE
+void HndScanHandlesForGC(
+ DPTR(dac_handle_table) hTable,
+ HANDLESCANPROC scanProc,
+ uintptr_t param1,
+ uintptr_t param2,
+ const uint32_t *types,
+ uint32_t typeCount,
+ uint32_t condemned,
+ uint32_t maxGen,
+ uint32_t flags);
+
+GC_DAC_VISIBLE_NO_MANGLE
+void HndEnumHandles(
+ DPTR(dac_handle_table) hTable,
+ const uint32_t *puType,
+ uint32_t uTypeCount,
+ HANDLESCANPROC pfnEnum,
+ uintptr_t lParam1,
+ uintptr_t lParam2,
+ bool fAsync);
+
+GC_DAC_VISIBLE
+OBJECTREF HndFetchHandle(OBJECTHANDLE handle);
+
+GC_DAC_VISIBLE
+struct ADIndex HndGetHandleADIndex(OBJECTHANDLE handle);
+
+GC_DAC_VISIBLE
+uintptr_t HndGetHandleExtraInfo(OBJECTHANDLE handle);
+
+#endif // DACCESS_COMPILE
+
+#endif // __DACCESS_GCINTERFACE_DAC_H__
diff --git a/src/debug/daccess/request.cpp b/src/debug/daccess/request.cpp
index ebaa1f833f..806c288bbb 100644
--- a/src/debug/daccess/request.cpp
+++ b/src/debug/daccess/request.cpp
@@ -13,8 +13,6 @@
#include "stdafx.h"
#include <win32threadpool.h>
-// TODO(Local GC) - The DAC should not include GC headers
-#include <../../gc/handletablepriv.h>
#include "typestring.h"
#include <gccover.h>
#include <virtualcallstub.h>
@@ -3871,7 +3869,7 @@ HRESULT ClrDataAccess::GetClrWatsonBucketsWorker(Thread * pThread, GenericModeBl
if (ohThrowable != NULL)
{
// Get the object from handle and check if the throwable is preallocated or not
- OBJECTREF oThrowable = ::HndFetchHandle(ohThrowable);
+ OBJECTREF oThrowable = ObjectFromHandle(ohThrowable);
if (oThrowable != NULL)
{
// Does the throwable have buckets?
@@ -4165,7 +4163,7 @@ HRESULT ClrDataAccess::GetCCWData(CLRDATA_ADDRESS ccw, struct DacpCCWData *ccwDa
ccwData->isAggregated = pCCW->GetSimpleWrapper()->IsAggregated();
if (pCCW->GetObjectHandle() != NULL)
- ccwData->managedObject = PTR_CDADDR(::HndFetchHandle(pCCW->GetObjectHandle()));
+ ccwData->managedObject = PTR_CDADDR(ObjectFromHandle(pCCW->GetObjectHandle()));
// count the number of COM vtables
ccwData->interfaceCount = 0;
diff --git a/src/gc/gc.h b/src/gc/gc.h
index 52252b8be3..4e722c4304 100644
--- a/src/gc/gc.h
+++ b/src/gc/gc.h
@@ -249,11 +249,13 @@ void TouchPages(void * pStart, size_t cb);
void updateGCShadow(Object** ptr, Object* val);
#endif
+#ifndef DACCESS_COMPILE
// The single GC heap instance, shared with the VM.
extern IGCHeapInternal* g_theGCHeap;
// The single GC handle manager instance, shared with the VM.
extern IGCHandleManager* g_theGCHandleManager;
+#endif // DACCESS_COMPILE
#ifndef DACCESS_COMPILE
inline bool IsGCInProgress(bool bConsiderGCStart = false)
diff --git a/src/gc/gccommon.cpp b/src/gc/gccommon.cpp
index 3e45eb60d5..92c0e7b7b5 100644
--- a/src/gc/gccommon.cpp
+++ b/src/gc/gccommon.cpp
@@ -124,6 +124,8 @@ namespace SVR
extern void PopulateDacVars(GcDacVars* dacVars);
}
+extern void PopulateHandleTableDacVars(GcDacVars* dacVars);
+
//------------------------------------------------------------------
// Externally-facing GC symbols, used to initialize the GC
// -----------------------------------------------------------------
@@ -203,6 +205,7 @@ InitializeGarbageCollector(
WKS::PopulateDacVars(gcDacVars);
#endif
+ PopulateHandleTableDacVars(gcDacVars);
if (heap == nullptr)
{
return false;
diff --git a/src/gc/gcinterface.dac.h b/src/gc/gcinterface.dac.h
index 647101fa1f..93698c05a9 100644
--- a/src/gc/gcinterface.dac.h
+++ b/src/gc/gcinterface.dac.h
@@ -11,12 +11,14 @@
// GC-internal type's fields, while still maintaining the same layout.
// This interface is strictly versioned, see gcinterface.dacvars.def for more information.
-#define NUM_GC_DATA_POINTS 9
-#define MAX_COMPACT_REASONS_COUNT 11
-#define MAX_EXPAND_MECHANISMS_COUNT 6
-#define MAX_GC_MECHANISM_BITS_COUNT 2
-#define MAX_GLOBAL_GC_MECHANISMS_COUNT 6
-#define NUMBERGENERATIONS 4
+#define NUM_GC_DATA_POINTS 9
+#define MAX_COMPACT_REASONS_COUNT 11
+#define MAX_EXPAND_MECHANISMS_COUNT 6
+#define MAX_GC_MECHANISM_BITS_COUNT 2
+#define MAX_GLOBAL_GC_MECHANISMS_COUNT 6
+#define NUMBERGENERATIONS 4
+#define INITIAL_HANDLE_TABLE_ARRAY_SIZE 10
+#define HANDLE_MAX_INTERNAL_TYPES 12
// Analogue for the GC heap_segment class, containing information regarding a single
// heap segment.
@@ -49,6 +51,32 @@ public:
uint8_t** m_FillPointers[NUMBERGENERATIONS + ExtraSegCount];
};
+class dac_handle_table {
+public:
+ // On the handle table side, this is an ADIndex. They should still have
+ // the same layout.
+ //
+ // We do try to keep everything that the DAC knows about as close to the
+ // start of the struct as possible to avoid having padding members. However,
+ // HandleTable has rgTypeFlags at offset 0 for performance reasons and
+ // we don't want to disrupt that.
+ uint32_t padding[HANDLE_MAX_INTERNAL_TYPES];
+ DWORD uADIndex;
+};
+
+class dac_handle_table_bucket {
+public:
+ DPTR(DPTR(dac_handle_table)) pTable;
+ uint32_t HandleTableIndex;
+};
+
+class dac_handle_table_map {
+public:
+ DPTR(DPTR(dac_handle_table_bucket)) pBuckets;
+ DPTR(dac_handle_table_map) pNext;
+ uint32_t dwMaxIndex;
+};
+
// Possible values of the current_c_gc_state dacvar, indicating the state of
// a background GC.
enum c_gc_state
@@ -132,6 +160,23 @@ public:
};
+// The DAC links against six symbols that build as part of the VM DACCESS_COMPILE
+// build. These symbols are considered to be GC-private functions, but the DAC needs
+// to use them in order to perform some handle-related functions. These six functions
+// are adorned by this macro to make clear that their implementations must be versioned
+// alongside the rest of this file.
+//
+// Practically, this macro ensures that the target symbols aren't mangled, since the
+// DAC calls them with a signature slightly different than the one used when they
+// were defined.
+#define GC_DAC_VISIBLE
+
+#ifdef DACCESS_COMPILE
+#define GC_DAC_VISIBLE_NO_MANGLE extern "C"
+#else
+#define GC_DAC_VISIBLE_NO_MANGLE
+#endif // DACCESS_COMPILE
+
// The actual structure containing the DAC variables. When DACCESS_COMPILE is not
// defined (i.e. the normal runtime build), this structure contains pointers to the
// GC's global DAC variabels. When DACCESS_COMPILE is defined (i.e. the DAC build),
@@ -142,9 +187,7 @@ struct GcDacVars {
uint8_t minor_version_number;
size_t generation_size;
#ifdef DACCESS_COMPILE
- #define GC_DAC_VAR(type, name) DPTR(type) name;
- // ArrayDPTR doesn't allow decaying arrays to pointers, which
- // avoids some accidental errors.
+ #define GC_DAC_VAR(type, name) DPTR(type) name;
#define GC_DAC_PTR_VAR(type, name) DPTR(type*) name;
#define GC_DAC_ARRAY_VAR(type, name) DPTR(type) name;
#else
diff --git a/src/gc/gcinterface.dacvars.def b/src/gc/gcinterface.dacvars.def
index b788079dcb..89cb01206f 100644
--- a/src/gc/gcinterface.dacvars.def
+++ b/src/gc/gcinterface.dacvars.def
@@ -60,6 +60,7 @@ GC_DAC_ARRAY_VAR (size_t, interesting_data_per_heap)
GC_DAC_ARRAY_VAR (size_t, compact_reasons_per_heap)
GC_DAC_ARRAY_VAR (size_t, expand_mechanisms_per_heap)
GC_DAC_ARRAY_VAR (size_t, interesting_mechanism_bits_per_heap)
+GC_DAC_VAR (dac_handle_table_map, handle_table_map)
#undef GC_DAC_VAR
#undef GC_DAC_ARRAY_VAR
diff --git a/src/gc/handletable.cpp b/src/gc/handletable.cpp
index 8c6c835200..4942f017ac 100644
--- a/src/gc/handletable.cpp
+++ b/src/gc/handletable.cpp
@@ -263,6 +263,7 @@ ADIndex HndGetHandleTableADIndex(HHANDLETABLE hTable)
*
* Retrieves the AppDomain index associated with a handle table at creation
*/
+GC_DAC_VISIBLE
ADIndex HndGetHandleADIndex(OBJECTHANDLE handle)
{
WRAPPER_NO_CONTRACT;
@@ -570,6 +571,7 @@ uintptr_t HndCompareExchangeHandleExtraInfo(OBJECTHANDLE handle, uint32_t uType,
* Retrieves owner data from handle.
*
*/
+GC_DAC_VISIBLE
uintptr_t HndGetHandleExtraInfo(OBJECTHANDLE handle)
{
WRAPPER_NO_CONTRACT;
@@ -659,6 +661,7 @@ void HndLogSetEvent(OBJECTHANDLE handle, _UNCHECKED_OBJECTREF value)
#endif
}
+#ifndef DACCESS_COMPILE
/*
* HndWriteBarrier
*
@@ -733,6 +736,7 @@ void HndWriteBarrier(OBJECTHANDLE handle, OBJECTREF objref)
}
}
}
+#endif // DACCESS_COMPILE
/*
* HndEnumHandles
@@ -743,6 +747,7 @@ void HndWriteBarrier(OBJECTHANDLE handle, OBJECTREF objref)
* needs to enumerate all roots in the handle table.
*
*/
+GC_DAC_VISIBLE_NO_MANGLE
void HndEnumHandles(HHANDLETABLE hTable, const uint32_t *puType, uint32_t uTypeCount,
HANDLESCANPROC pfnEnum, uintptr_t lParam1, uintptr_t lParam2, bool fAsync)
{
@@ -803,6 +808,7 @@ void HndEnumHandles(HHANDLETABLE hTable, const uint32_t *puType, uint32_t uTypeC
* as it scans.
*
*/
+GC_DAC_VISIBLE_NO_MANGLE
void HndScanHandlesForGC(HHANDLETABLE hTable, HANDLESCANPROC scanProc, uintptr_t param1, uintptr_t param2,
const uint32_t *types, uint32_t typeCount, uint32_t condemned, uint32_t maxgen, uint32_t flags)
{
diff --git a/src/gc/handletable.h b/src/gc/handletable.h
index a952ad799f..70959edf3b 100644
--- a/src/gc/handletable.h
+++ b/src/gc/handletable.h
@@ -63,6 +63,8 @@ void HndDestroyHandleTable(HHANDLETABLE hTable);
void HndSetHandleTableIndex(HHANDLETABLE hTable, uint32_t uTableIndex);
uint32_t HndGetHandleTableIndex(HHANDLETABLE hTable);
ADIndex HndGetHandleTableADIndex(HHANDLETABLE hTable);
+
+GC_DAC_VISIBLE
ADIndex HndGetHandleADIndex(OBJECTHANDLE handle);
#ifndef DACCESS_COMPILE
@@ -81,6 +83,7 @@ void HndSetHandleExtraInfo(OBJECTHANDLE handle, uint32_t uType, uintp
uintptr_t HndCompareExchangeHandleExtraInfo(OBJECTHANDLE handle, uint32_t uType, uintptr_t lOldExtraInfo, uintptr_t lNewExtraInfo);
#endif // !DACCESS_COMPILE
+GC_DAC_VISIBLE
uintptr_t HndGetHandleExtraInfo(OBJECTHANDLE handle);
/*
@@ -101,6 +104,7 @@ void HndLogSetEvent(OBJECTHANDLE handle, _UNCHECKED_OBJECTREF value);
/*
* NON-GC handle enumeration
*/
+GC_DAC_VISIBLE_NO_MANGLE
void HndEnumHandles(HHANDLETABLE hTable, const uint32_t *puType, uint32_t uTypeCount,
HANDLESCANPROC pfnEnum, uintptr_t lParam1, uintptr_t lParam2, bool fAsync);
@@ -112,7 +116,7 @@ void HndEnumHandles(HHANDLETABLE hTable, const uint32_t *puType, uint32_t uTypeC
#define HNDGCF_ASYNC (0x00000002) // drop the table lock while scanning
#define HNDGCF_EXTRAINFO (0x00000004) // iterate per-handle data while scanning
-
+GC_DAC_VISIBLE_NO_MANGLE
void HndScanHandlesForGC(HHANDLETABLE hTable,
HANDLESCANPROC scanProc,
uintptr_t param1,
@@ -168,7 +172,9 @@ BOOL HndFirstAssignHandle(OBJECTHANDLE handle, OBJECTREF objref);
* on the VM side.
*
*/
-FORCEINLINE OBJECTREF HndFetchHandle(OBJECTHANDLE handle)
+GC_DAC_VISIBLE
+FORCEINLINE
+OBJECTREF HndFetchHandle(OBJECTHANDLE handle)
{
WRAPPER_NO_CONTRACT;
diff --git a/src/gc/handletablepriv.h b/src/gc/handletablepriv.h
index cda1cb08aa..f33a547a23 100644
--- a/src/gc/handletablepriv.h
+++ b/src/gc/handletablepriv.h
@@ -56,9 +56,6 @@
#define HANDLE_HANDLES_PER_BLOCK (64) // segment suballocation granularity
#define HANDLE_OPTIMIZE_FOR_64_HANDLE_BLOCKS // flag for certain optimizations
-// maximum number of internally supported handle types
-#define HANDLE_MAX_INTERNAL_TYPES (12) // should be a multiple of 4
-
// number of types allowed for public callers
#define HANDLE_MAX_PUBLIC_TYPES (HANDLE_MAX_INTERNAL_TYPES - 1) // reserve one internal type
@@ -513,6 +510,11 @@ struct HandleTable
uint32_t rgTypeFlags[HANDLE_MAX_INTERNAL_TYPES];
/*
+ * per-table AppDomain info
+ */
+ ADIndex uADIndex;
+
+ /*
* lock for this table
*/
CrstStatic Lock;
@@ -544,11 +546,6 @@ struct HandleTable
uint32_t uTableIndex;
/*
- * per-table AppDomain info
- */
- ADIndex uADIndex;
-
- /*
* one-level per-type 'quick' handle cache
*/
OBJECTHANDLE rgQuickCache[HANDLE_MAX_INTERNAL_TYPES]; // interlocked ops used here
diff --git a/src/gc/objecthandle.cpp b/src/gc/objecthandle.cpp
index d7c5d39de5..657050398b 100644
--- a/src/gc/objecthandle.cpp
+++ b/src/gc/objecthandle.cpp
@@ -28,7 +28,7 @@
#include "nativeoverlapped.h"
#endif // FEATURE_REDHAWK
-GVAL_IMPL(HandleTableMap, g_HandleTableMap);
+HandleTableMap g_HandleTableMap;
// Array of contexts used while scanning dependent handles for promotion. There are as many contexts as GC
// heaps and they're allocated by Ref_Initialize and initialized during each GC by GcDhInitialScan.
@@ -1894,9 +1894,24 @@ bool HandleTableBucket::Contains(OBJECTHANDLE handle)
#endif // !DACCESS_COMPILE
+GC_DAC_VISIBLE
OBJECTREF GetDependentHandleSecondary(OBJECTHANDLE handle)
{
WRAPPER_NO_CONTRACT;
return UNCHECKED_OBJECTREF_TO_OBJECTREF((_UNCHECKED_OBJECTREF)HndGetHandleExtraInfo(handle));
}
+
+void PopulateHandleTableDacVars(GcDacVars* gcDacVars)
+{
+ static_assert(offsetof(HandleTableMap, pBuckets) == offsetof(dac_handle_table_map, pBuckets), "handle table map DAC layout mismatch");
+ static_assert(offsetof(HandleTableMap, pNext) == offsetof(dac_handle_table_map, pNext), "handle table map DAC layout mismatch");
+ static_assert(offsetof(HandleTableMap, dwMaxIndex) == offsetof(dac_handle_table_map, dwMaxIndex), "handle table map DAC layout mismatch");
+ static_assert(offsetof(HandleTableBucket, pTable) == offsetof(dac_handle_table_bucket, pTable), "handle table bucket DAC layout mismatch");
+ static_assert(offsetof(HandleTableBucket, HandleTableIndex) == offsetof(dac_handle_table_bucket, HandleTableIndex), "handle table bucket DAC layout mismatch");
+ static_assert(offsetof(HandleTable, uADIndex) == offsetof(dac_handle_table, uADIndex), "handle table DAC layout mismatch");
+
+#ifndef DACCESS_COMPILE
+ gcDacVars->handle_table_map = reinterpret_cast<dac_handle_table_map*>(&g_HandleTableMap);
+#endif // DACCESS_COMPILE
+}
diff --git a/src/gc/objecthandle.h b/src/gc/objecthandle.h
index 6b8bcb70ed..4ed7f2d1a4 100644
--- a/src/gc/objecthandle.h
+++ b/src/gc/objecthandle.h
@@ -32,9 +32,7 @@ struct HandleTableMap
uint32_t dwMaxIndex;
};
-GVAL_DECL(HandleTableMap, g_HandleTableMap);
-
-#define INITIAL_HANDLE_TABLE_ARRAY_SIZE 10
+extern HandleTableMap g_HandleTableMap;
// struct containing g_SystemInfo.dwNumberOfProcessors HHANDLETABLEs and current table index
// instead of just single HHANDLETABLE for on-fly balancing while adding handles on multiproc machines
@@ -61,6 +59,7 @@ struct HandleTableBucket
(flag == VHT_STRONG) || \
(flag == VHT_PINNED))
+GC_DAC_VISIBLE
OBJECTREF GetDependentHandleSecondary(OBJECTHANDLE handle);
#ifndef DACCESS_COMPILE
diff --git a/src/inc/dacvars.h b/src/inc/dacvars.h
index 9fe2382d86..affed8af82 100644
--- a/src/inc/dacvars.h
+++ b/src/inc/dacvars.h
@@ -242,7 +242,6 @@ DEFINE_DACVAR(ULONG, SIZE_T, dac__g_runtimeVirtualSize, ::g_runtimeVirtualSize)
DEFINE_DACVAR(ULONG, SyncBlockCache *, SyncBlockCache__s_pSyncBlockCache, SyncBlockCache::s_pSyncBlockCache)
-DEFINE_DACVAR(ULONG, HandleTableMap, dac__g_HandleTableMap, ::g_HandleTableMap)
DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pStressLog, ::g_pStressLog)
DEFINE_DACVAR(ULONG, SIZE_T, dac__s_gsCookie, ::s_gsCookie)
diff --git a/src/vm/CMakeLists.txt b/src/vm/CMakeLists.txt
index 8bb2292816..c2cb52e3bd 100644
--- a/src/vm/CMakeLists.txt
+++ b/src/vm/CMakeLists.txt
@@ -124,16 +124,10 @@ set(VM_SOURCES_DAC_AND_WKS_COMMON
)
set( GC_SOURCES_DAC_AND_WKS_COMMON
- ../gc/gcconfig.cpp
- ../gc/gccommon.cpp
- ../gc/gcscan.cpp
- ../gc/gcsvr.cpp
- ../gc/gcwks.cpp
../gc/handletable.cpp
../gc/handletablecore.cpp
../gc/handletablescan.cpp
- ../gc/objecthandle.cpp
- ../gc/softwarewritewatch.cpp)
+ ../gc/objecthandle.cpp)
if(FEATURE_READYTORUN)
list(APPEND VM_SOURCES_DAC_AND_WKS_COMMON
@@ -270,9 +264,15 @@ set(VM_SOURCES_WKS
set(GC_SOURCES_WKS
${GC_SOURCES_DAC_AND_WKS_COMMON}
+ ../gc/gcconfig.cpp
+ ../gc/gccommon.cpp
+ ../gc/gcscan.cpp
+ ../gc/gcsvr.cpp
+ ../gc/gcwks.cpp
../gc/gchandletable.cpp
../gc/gceesvr.cpp
../gc/gceewks.cpp
+ ../gc/softwarewritewatch.cpp
../gc/handletablecache.cpp)
if(FEATURE_EVENT_TRACE)
diff --git a/src/vm/gchandleutilities.h b/src/vm/gchandleutilities.h
index 762a37b524..08d27141e5 100644
--- a/src/vm/gchandleutilities.h
+++ b/src/vm/gchandleutilities.h
@@ -40,12 +40,13 @@ inline OBJECTREF ObjectFromHandle(OBJECTHANDLE handle)
{
_ASSERTE(handle);
-#ifdef _DEBUG_IMPL
+#if defined(_DEBUG_IMPL) && !defined(DACCESS_COMPILE)
+ // not allowed to dispatch virtually on a IGCHandleManager when compiling for DAC
DWORD context = (DWORD)GCHandleUtilities::GetGCHandleManager()->GetHandleContext(handle);
OBJECTREF objRef = ObjectToOBJECTREF(*(Object**)handle);
ValidateObjectAndAppDomain(objRef, ADIndex(context));
-#endif // _DEBUG_IMPL
+#endif // defined(_DEBUG_IMPL) && !defined(DACCESS_COMPILE)
// Wrap the raw OBJECTREF and return it
return UNCHECKED_OBJECTREF_TO_OBJECTREF(*PTR_UNCHECKED_OBJECTREF(handle));