From: Aditya Mandaleeka Date: Thu, 23 Mar 2017 23:23:05 +0000 (-0700) Subject: Create a GCHandleTable interface with Init/Shutdown. X-Git-Tag: accepted/tizen/base/20180629.140029~1488^2~7 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=8d02c0786825a27d67fb2af150f751dbda360bef;p=platform%2Fupstream%2Fcoreclr.git Create a GCHandleTable interface with Init/Shutdown. --- diff --git a/src/gc/CMakeLists.txt b/src/gc/CMakeLists.txt index cba1aa9..59c18ff 100644 --- a/src/gc/CMakeLists.txt +++ b/src/gc/CMakeLists.txt @@ -31,6 +31,7 @@ set( GC_SOURCES_DAC_AND_WKS_COMMON set( GC_SOURCES_WKS ${GC_SOURCES_DAC_AND_WKS_COMMON} + gchandletable.cpp gceesvr.cpp gceewks.cpp handletablecache.cpp) diff --git a/src/gc/gc.h b/src/gc/gc.h index 478e8cd..ecb791f 100644 --- a/src/gc/gc.h +++ b/src/gc/gc.h @@ -111,6 +111,8 @@ extern "C" uint32_t* g_gc_card_table; extern "C" uint8_t* g_gc_lowest_address; extern "C" uint8_t* g_gc_highest_address; +::IGCHandleTable* CreateGCHandleTable(); + namespace WKS { ::IGCHeapInternal* CreateGCHeap(); class GCHeap; @@ -262,6 +264,9 @@ extern void FinalizeWeakReference(Object * obj); // 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) { diff --git a/src/gc/gccommon.cpp b/src/gc/gccommon.cpp index c176051..8f6d1ac 100644 --- a/src/gc/gccommon.cpp +++ b/src/gc/gccommon.cpp @@ -21,6 +21,7 @@ SVAL_IMPL_INIT(uint32_t,IGCHeap,gcHeapType,IGCHeap::GC_HEAP_INVALID); SVAL_IMPL_INIT(uint32_t,IGCHeap,maxGeneration,2); IGCHeapInternal* g_theGCHeap; +IGCHandleTable* g_theGCHandleTable; #ifdef FEATURE_STANDALONE_GC IGCToCLR* g_theGCToCLR; @@ -145,7 +146,7 @@ namespace SVR 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; @@ -153,6 +154,14 @@ bool InitializeGarbageCollector(IGCToCLR* clrToGC, IGCHeap** gcHeap, GcDacVars* 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); @@ -169,7 +178,6 @@ bool InitializeGarbageCollector(IGCToCLR* clrToGC, IGCHeap** gcHeap, GcDacVars* #else heap = WKS::CreateGCHeap(); WKS::PopulateDacVars(gcDacVars); - #endif if (heap == nullptr) @@ -187,6 +195,7 @@ bool InitializeGarbageCollector(IGCToCLR* clrToGC, IGCHeap** gcHeap, GcDacVars* assert(clrToGC == nullptr); #endif + *gcHandleTable = handleTable; *gcHeap = heap; return true; } diff --git a/src/gc/gceesvr.cpp b/src/gc/gceesvr.cpp index aacae48..2e6dbe2 100644 --- a/src/gc/gceesvr.cpp +++ b/src/gc/gceesvr.cpp @@ -12,9 +12,11 @@ #include "gc.h" #include "gcscan.h" +#include "gchandletableimpl.h" #define SERVER_GC 1 + namespace SVR { #include "gcimpl.h" #include "gcee.cpp" diff --git a/src/gc/gceewks.cpp b/src/gc/gceewks.cpp index 72a7d3b..f23038f 100644 --- a/src/gc/gceewks.cpp +++ b/src/gc/gceewks.cpp @@ -10,6 +10,7 @@ #include "gc.h" #include "gcscan.h" +#include "gchandletableimpl.h" #ifdef SERVER_GC #undef SERVER_GC diff --git a/src/gc/gchandletable.cpp b/src/gc/gchandletable.cpp new file mode 100644 index 0000000..a4c3352 --- /dev/null +++ b/src/gc/gchandletable.cpp @@ -0,0 +1,24 @@ +// 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(); +} diff --git a/src/gc/gchandletableimpl.h b/src/gc/gchandletableimpl.h new file mode 100644 index 0000000..233e326 --- /dev/null +++ b/src/gc/gchandletableimpl.h @@ -0,0 +1,18 @@ +// 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_ diff --git a/src/gc/gcinterface.h b/src/gc/gcinterface.h index 7aae605..77425b1 100644 --- a/src/gc/gcinterface.h +++ b/src/gc/gcinterface.h @@ -171,11 +171,12 @@ struct segment_info 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 @@ -384,6 +385,13 @@ typedef void (* record_surv_fn)(uint8_t* begin, uint8_t* end, ptrdiff_t reloc, v 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 { diff --git a/src/gc/sample/CMakeLists.txt b/src/gc/sample/CMakeLists.txt index 29fd32f..5fe7887 100644 --- a/src/gc/sample/CMakeLists.txt +++ b/src/gc/sample/CMakeLists.txt @@ -10,6 +10,7 @@ set(SOURCES gcenv.ee.cpp ../gccommon.cpp ../gceewks.cpp + ../gchandletable.cpp ../gcscan.cpp ../gcwks.cpp ../handletable.cpp diff --git a/src/gc/sample/GCSample.cpp b/src/gc/sample/GCSample.cpp index 2c32048..5d5371c 100644 --- a/src/gc/sample/GCSample.cpp +++ b/src/gc/sample/GCSample.cpp @@ -126,17 +126,12 @@ int __cdecl main(int argc, char* argv[]) 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; } @@ -145,6 +140,12 @@ int __cdecl main(int argc, char* argv[]) return -1; // + // Initialize handle table + // + if (!pGCHandleTable->Initialize()) + return -1; + + // // Initialize current thread // ThreadStore::AttachCurrentThread(); diff --git a/src/vm/ceemain.cpp b/src/vm/ceemain.cpp index c07b24e..602ccc9 100644 --- a/src/vm/ceemain.cpp +++ b/src/vm/ceemain.cpp @@ -862,11 +862,14 @@ void EEStartupHelper(COINITIEE fFlags) #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(); @@ -874,8 +877,6 @@ void EEStartupHelper(COINITIEE fFlags) g_pEEShutDownEvent = new CLREvent(); g_pEEShutDownEvent->CreateManualEvent(FALSE); - - #ifdef FEATURE_IPCMAN // Initialize CCLRSecurityAttributeManager CCLRSecurityAttributeManager::ProcessInit(); @@ -885,7 +886,6 @@ void EEStartupHelper(COINITIEE fFlags) GCInterface::m_MemoryPressureLock.Init(CrstGCMemoryPressure); - #endif // CROSSGEN_COMPILE // Setup the domains. Threads are started in a default domain. @@ -908,9 +908,6 @@ void EEStartupHelper(COINITIEE fFlags) // 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. @@ -1014,7 +1011,14 @@ void EEStartupHelper(COINITIEE fFlags) } #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(); @@ -1852,7 +1856,7 @@ part2: #ifdef SHOULD_WE_CLEANUP if (!g_fFastExitProcess) { - Ref_Shutdown(); // shut down the handle table + GCHeapUtilities::GetGCHandleTable()->Shutdown(); } #endif /* SHOULD_WE_CLEANUP */ @@ -2455,15 +2459,17 @@ void InitializeGarbageCollector() 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 @@ -2471,9 +2477,6 @@ void InitializeGarbageCollector() // 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); } /*****************************************************************************/ diff --git a/src/vm/gcheaputilities.cpp b/src/vm/gcheaputilities.cpp index b260c3d..aa90341 100644 --- a/src/vm/gcheaputilities.cpp +++ b/src/vm/gcheaputilities.cpp @@ -22,6 +22,8 @@ uint32_t* g_card_bundle_table = nullptr; // 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); diff --git a/src/vm/gcheaputilities.h b/src/vm/gcheaputilities.h index 0680763..1e92012 100644 --- a/src/vm/gcheaputilities.h +++ b/src/vm/gcheaputilities.h @@ -26,6 +26,7 @@ GPTR_DECL(uint32_t,g_card_table); // 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; @@ -71,6 +72,15 @@ public: 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() {