set( GC_SOURCES_WKS
${GC_SOURCES_DAC_AND_WKS_COMMON}
+ gchandletable.cpp
gceesvr.cpp
gceewks.cpp
handletablecache.cpp)
extern "C" uint8_t* g_gc_lowest_address;
extern "C" uint8_t* g_gc_highest_address;
+::IGCHandleTable* CreateGCHandleTable();
+
namespace WKS {
::IGCHeapInternal* CreateGCHeap();
class GCHeap;
// The single GC heap instance, shared with the VM.
extern IGCHeapInternal* g_theGCHeap;
+// The single GC handle table instance, shared with the VM.
+extern IGCHandleTable* g_theGCHandleTable;
+
#ifndef DACCESS_COMPILE
inline bool IsGCInProgress(bool bConsiderGCStart = false)
{
SVAL_IMPL_INIT(uint32_t,IGCHeap,maxGeneration,2);
IGCHeapInternal* g_theGCHeap;
+IGCHandleTable* g_theGCHandleTable;
#ifdef FEATURE_STANDALONE_GC
IGCToCLR* g_theGCToCLR;
extern void PopulateDacVars(GcDacVars* dacVars);
}
-bool InitializeGarbageCollector(IGCToCLR* clrToGC, IGCHeap** gcHeap, GcDacVars* gcDacVars)
+bool InitializeGarbageCollector(IGCToCLR* clrToGC, IGCHeap** gcHeap, IGCHandleTable** gcHandleTable, GcDacVars* gcDacVars)
{
LIMITED_METHOD_CONTRACT;
assert(gcDacVars != nullptr);
assert(gcHeap != nullptr);
+ assert(gcHandleTable != nullptr);
+
+ IGCHandleTable* handleTable = CreateGCHandleTable();
+ if (handleTable == nullptr)
+ {
+ return false;
+ }
+
#ifdef FEATURE_SVR_GC
assert(IGCHeap::gcHeapType != IGCHeap::GC_HEAP_INVALID);
#else
heap = WKS::CreateGCHeap();
WKS::PopulateDacVars(gcDacVars);
-
#endif
if (heap == nullptr)
assert(clrToGC == nullptr);
#endif
+ *gcHandleTable = handleTable;
*gcHeap = heap;
return true;
}
#include "gc.h"
#include "gcscan.h"
+#include "gchandletableimpl.h"
#define SERVER_GC 1
+
namespace SVR {
#include "gcimpl.h"
#include "gcee.cpp"
#include "gc.h"
#include "gcscan.h"
+#include "gchandletableimpl.h"
#ifdef SERVER_GC
#undef SERVER_GC
--- /dev/null
+// 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.
+//
+
+#include "common.h"
+#include "gcenv.h"
+#include "gchandletableimpl.h"
+#include "objecthandle.h"
+
+IGCHandleTable* CreateGCHandleTable()
+{
+ return new(nothrow) GCHandleTable();
+}
+
+bool GCHandleTable::Initialize()
+{
+ return Ref_Initialize();
+}
+
+void GCHandleTable::Shutdown()
+{
+ Ref_Shutdown();
+}
--- /dev/null
+// 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 GCHANDLETABLE_H_
+#define GCHANDLETABLE_H_
+
+#include "gcinterface.h"
+
+class GCHandleTable : public IGCHandleTable
+{
+public:
+ virtual bool Initialize();
+
+ virtual void Shutdown();
+};
+
+#endif // GCHANDLETABLE_H_
class Object;
class IGCHeap;
+class IGCHandleTable;
// Initializes the garbage collector. Should only be called
// once, during EE startup. Returns true if the initialization
// was successful, false otherwise.
-bool InitializeGarbageCollector(IGCToCLR* clrToGC, IGCHeap **gcHeap, GcDacVars* gcDacVars);
+bool InitializeGarbageCollector(IGCToCLR* clrToGC, IGCHeap** gcHeap, IGCHandleTable** gcHandleTable, GcDacVars* gcDacVars);
// The runtime needs to know whether we're using workstation or server GC
// long before the GCHeap is created. This function sets the type of
typedef void (* fq_walk_fn)(bool, void*);
typedef void (* fq_scan_fn)(Object** ppObject, ScanContext *pSC, uint32_t dwFlags);
typedef void (* handle_scan_fn)(Object** pRef, Object* pSec, uint32_t flags, ScanContext* context, bool isDependent);
+class IGCHandleTable {
+public:
+
+ virtual bool Initialize() = 0;
+
+ virtual void Shutdown() = 0;
+};
// IGCHeap is the interface that the VM will use when interacting with the GC.
class IGCHeap {
gcenv.ee.cpp
../gccommon.cpp
../gceewks.cpp
+ ../gchandletable.cpp
../gcscan.cpp
../gcwks.cpp
../handletable.cpp
g_pFreeObjectMethodTable = &freeObjectMT;
//
- // Initialize handle table
- //
- if (!Ref_Initialize())
- return -1;
-
- //
// Initialize GC heap
//
GcDacVars dacVars;
IGCHeap *pGCHeap;
- if (!InitializeGarbageCollector(nullptr, &pGCHeap, &dacVars))
+ IGCHandleTable *pGCHandleTable;
+ if (!InitializeGarbageCollector(nullptr, &pGCHeap, &pGCHandleTable, &dacVars))
{
return -1;
}
return -1;
//
+ // Initialize handle table
+ //
+ if (!pGCHandleTable->Initialize())
+ return -1;
+
+ //
// Initialize current thread
//
ThreadStore::AttachCurrentThread();
#ifndef CROSSGEN_COMPILE
+ InitializeGarbageCollector();
+
// Initialize remoting
- // weak_short, weak_long, strong; no pin
- if (!Ref_Initialize())
+ if (!GCHeapUtilities::GetGCHandleTable()->Initialize())
+ {
IfFailGo(E_OUTOFMEMORY);
+ }
// Initialize contexts
Context::Initialize();
g_pEEShutDownEvent = new CLREvent();
g_pEEShutDownEvent->CreateManualEvent(FALSE);
-
-
#ifdef FEATURE_IPCMAN
// Initialize CCLRSecurityAttributeManager
CCLRSecurityAttributeManager::ProcessInit();
GCInterface::m_MemoryPressureLock.Init(CrstGCMemoryPressure);
-
#endif // CROSSGEN_COMPILE
// Setup the domains. Threads are started in a default domain.
// creation requires AppDomains to have been set up.
FinalizerThread::FinalizerThreadCreate();
- // Now we really have fully initialized the garbage collector
- SetGarbageCollectorFullyInitialized();
-
#ifndef FEATURE_PAL
// Watson initialization must precede InitializeDebugger() and InstallUnhandledExceptionFilter()
// because on CoreCLR when Waston is enabled, debugging service needs to be enabled and UEF will be used.
}
#endif
- InitializeGarbageCollector();
+ // This isn't done as part of InitializeGarbageCollector() above because it
+ // requires write barriers to have been set up on x86, which happens as part
+ // of InitJITHelpers1.
+ hr = g_pGCHeap->Initialize();
+ IfFailGo(hr);
+
+ // Now we really have fully initialized the garbage collector
+ SetGarbageCollectorFullyInitialized();
InitializePinHandleTable();
#ifdef SHOULD_WE_CLEANUP
if (!g_fFastExitProcess)
{
- Ref_Shutdown(); // shut down the handle table
+ GCHeapUtilities::GetGCHandleTable()->Shutdown();
}
#endif /* SHOULD_WE_CLEANUP */
IGCToCLR* gcToClr = nullptr;
#endif
+ IGCHandleTable *pGcHandleTable;
IGCHeap *pGCHeap;
- if (!InitializeGarbageCollector(gcToClr, &pGCHeap, &g_gc_dac_vars))
+ if (!InitializeGarbageCollector(gcToClr, &pGCHeap, &pGcHandleTable, &g_gc_dac_vars))
{
ThrowOutOfMemory();
}
assert(pGCHeap != nullptr);
g_pGCHeap = pGCHeap;
+ g_pGCHandleTable = pGcHandleTable;
g_gcDacGlobals = &g_gc_dac_vars;
// Apparently the Windows linker removes global variables if they are never
// only the DAC will read from it. This forces the linker to include
// g_gcDacGlobals.
volatile void* _dummy = g_gcDacGlobals;
-
- hr = pGCHeap->Initialize();
- IfFailThrow(hr);
}
/*****************************************************************************/
// This is the global GC heap, maintained by the VM.
GPTR_IMPL(IGCHeap, g_pGCHeap);
+IGCHandleTable* g_pGCHandleTable = nullptr;
+
GcDacVars g_gc_dac_vars;
GPTR_IMPL(GcDacVars, g_gcDacGlobals);
// GC will update it when it needs to.
extern "C" gc_alloc_context g_global_alloc_context;
+extern "C" IGCHandleTable* g_pGCHandleTable;
extern "C" uint32_t* g_card_bundle_table;
extern "C" uint8_t* g_ephemeral_low;
extern "C" uint8_t* g_ephemeral_high;
return g_pGCHeap;
}
+ // Retrieves the GC handle table.
+ static IGCHandleTable* GetGCHandleTable()
+ {
+ LIMITED_METHOD_CONTRACT;
+
+ assert(g_pGCHandleTable != nullptr);
+ return g_pGCHandleTable;
+ }
+
// Returns true if the heap has been initialized, false otherwise.
inline static bool IsGCHeapInitialized()
{