diff options
author | Sean Gillespie <segilles@microsoft.com> | 2017-05-17 15:07:34 -0700 |
---|---|---|
committer | Sean Gillespie <segilles@microsoft.com> | 2017-06-01 10:19:59 -0700 |
commit | 1a183684b1ecf63ece8a2fd80173f083c0deea52 (patch) | |
tree | 907b31b417732768b28e80adfb4d920497f0d3f0 /src/vm/ceemain.cpp | |
parent | dde63bc1aa39aabae77fb89aad583483965c523e (diff) | |
download | coreclr-1a183684b1ecf63ece8a2fd80173f083c0deea52.tar.gz coreclr-1a183684b1ecf63ece8a2fd80173f083c0deea52.tar.bz2 coreclr-1a183684b1ecf63ece8a2fd80173f083c0deea52.zip |
[Local GC] Scaffolding for loading a standalone GC (#11242)
* Configure the build system to build a CoreCLR capable of loading a standalone GC
* Proto-implementation of dynamic GC loading
* Build the GC with the VM's CMakeLists when doing a non-standalone build of the GC
* [Local GC] Introduce a new feature define, FEATURE_STANDALONE_GC_ONLY, to be used by the CI to explicitly test local GC dynamic loading code paths
* Fix the FEATURE_STANDALONE_GC_ONLY build for unix linkers
* Rebase against master
* Code review feedback: use the existing Unix exports file
Diffstat (limited to 'src/vm/ceemain.cpp')
-rw-r--r-- | src/vm/ceemain.cpp | 123 |
1 files changed, 106 insertions, 17 deletions
diff --git a/src/vm/ceemain.cpp b/src/vm/ceemain.cpp index de6059a6ec..617b022516 100644 --- a/src/vm/ceemain.cpp +++ b/src/vm/ceemain.cpp @@ -2440,6 +2440,101 @@ BOOL ExecuteDLL_ReturnOrThrow(HRESULT hr, BOOL fFromThunk) // Initialize the Garbage Collector // +// Prototype for the function that initialzes the garbage collector. +// Should only be called once: here, during EE startup. +// Returns true if the initialization was successful, false otherwise. +// +// When using a standalone GC, this function is loaded dynamically using +// GetProcAddress. +extern "C" bool InitializeGarbageCollector(IGCToCLR* clrToGC, IGCHeap** gcHeap, IGCHandleManager** gcHandleManager, GcDacVars* gcDacVars); + +#ifdef FEATURE_STANDALONE_GC + +void LoadGarbageCollector() +{ + CONTRACTL { + THROWS; + GC_NOTRIGGER; + MODE_ANY; + } CONTRACTL_END; + + TCHAR *standaloneGc = nullptr; + CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_GCStandaloneLocation, &standaloneGc); + HMODULE hMod; + if (!standaloneGc) + { +#ifdef FEATURE_STANDALONE_GC_ONLY + // if the user has set GCUseStandalone but has not given us a standalone location, + // try and load the initialization symbol from the current module. + hMod = GetModuleInst(); +#else + ThrowHR(E_FAIL); +#endif // FEATURE_STANDALONE_GC_ONLY + } + else + { + hMod = CLRLoadLibrary(standaloneGc); + } + + if (!hMod) + { + ThrowHR(E_FAIL); + } + + InitializeGarbageCollectorFunction igcf = (InitializeGarbageCollectorFunction)GetProcAddress(hMod, INITIALIZE_GC_FUNCTION_NAME); + if (!igcf) + { + ThrowHR(E_FAIL); + } + + // at this point we are committing to using the standalone GC + // given to us. + IGCToCLR* gcToClr = new (nothrow) standalone::GCToEEInterface(); + if (!gcToClr) + { + ThrowOutOfMemory(); + } + + IGCHandleManager *pGcHandleManager; + IGCHeap *pGCHeap; + if (!igcf(gcToClr, &pGCHeap, &pGcHandleManager, &g_gc_dac_vars)) + { + ThrowOutOfMemory(); + } + + assert(pGCHeap != nullptr); + assert(pGcHandleManager != nullptr); + g_pGCHeap = pGCHeap; + g_pGCHandleManager = pGcHandleManager; + g_gcDacGlobals = &g_gc_dac_vars; +} + +#endif // FEATURE_STANDALONE_GC + +void LoadStaticGarbageCollector() +{ + CONTRACTL{ + THROWS; + GC_TRIGGERS; + MODE_ANY; + } CONTRACTL_END; + + IGCHandleManager *pGcHandleManager; + IGCHeap *pGCHeap; + + if (!InitializeGarbageCollector(nullptr, &pGCHeap, &pGcHandleManager, &g_gc_dac_vars)) + { + ThrowOutOfMemory(); + } + + assert(pGCHeap != nullptr); + assert(pGcHandleManager != nullptr); + g_pGCHeap = pGCHeap; + g_pGCHandleManager = pGcHandleManager; + g_gcDacGlobals = &g_gc_dac_vars; +} + + void InitializeGarbageCollector() { CONTRACTL{ @@ -2463,25 +2558,19 @@ void InitializeGarbageCollector() g_pFreeObjectMethodTable->SetComponentSize(1); #ifdef FEATURE_STANDALONE_GC - IGCToCLR* gcToClr = new (nothrow) GCToEEInterface(); - if (!gcToClr) - ThrowOutOfMemory(); -#else - IGCToCLR* gcToClr = nullptr; -#endif - - IGCHandleManager *pGcHandleManager; - - IGCHeap *pGCHeap; - if (!InitializeGarbageCollector(gcToClr, &pGCHeap, &pGcHandleManager, &g_gc_dac_vars)) + if (CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_GCUseStandalone) +#ifdef FEATURE_STANDALONE_GC_ONLY + || true +#endif // FEATURE_STANDALONE_GC_ONLY + ) { - ThrowOutOfMemory(); + LoadGarbageCollector(); + } + else +#endif // FEATURE_STANDALONE_GC + { + LoadStaticGarbageCollector(); } - - assert(pGCHeap != nullptr); - g_pGCHeap = pGCHeap; - g_pGCHandleManager = pGcHandleManager; - g_gcDacGlobals = &g_gc_dac_vars; // Apparently the Windows linker removes global variables if they are never // read from, which is a problem for g_gcDacGlobals since it's expected that |