Create a GCHandleTable interface with Init/Shutdown.
authorAditya Mandaleeka <adityam@microsoft.com>
Thu, 23 Mar 2017 23:23:05 +0000 (16:23 -0700)
committerAditya Mandaleeka <adityam@microsoft.com>
Wed, 29 Mar 2017 19:05:39 +0000 (12:05 -0700)
13 files changed:
src/gc/CMakeLists.txt
src/gc/gc.h
src/gc/gccommon.cpp
src/gc/gceesvr.cpp
src/gc/gceewks.cpp
src/gc/gchandletable.cpp [new file with mode: 0644]
src/gc/gchandletableimpl.h [new file with mode: 0644]
src/gc/gcinterface.h
src/gc/sample/CMakeLists.txt
src/gc/sample/GCSample.cpp
src/vm/ceemain.cpp
src/vm/gcheaputilities.cpp
src/vm/gcheaputilities.h

index cba1aa9..59c18ff 100644 (file)
@@ -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)
index 478e8cd..ecb791f 100644 (file)
@@ -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)
 {
index c176051..8f6d1ac 100644 (file)
@@ -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;
 }
index aacae48..2e6dbe2 100644 (file)
 
 #include "gc.h"
 #include "gcscan.h"
+#include "gchandletableimpl.h"
 
 #define SERVER_GC 1
 
+
 namespace SVR { 
 #include "gcimpl.h"
 #include "gcee.cpp"
index 72a7d3b..f23038f 100644 (file)
@@ -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 (file)
index 0000000..a4c3352
--- /dev/null
@@ -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 (file)
index 0000000..233e326
--- /dev/null
@@ -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_
index 7aae605..77425b1 100644 (file)
@@ -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 {
index 29fd32f..5fe7887 100644 (file)
@@ -10,6 +10,7 @@ set(SOURCES
     gcenv.ee.cpp
     ../gccommon.cpp
     ../gceewks.cpp
+    ../gchandletable.cpp
     ../gcscan.cpp
     ../gcwks.cpp
     ../handletable.cpp
index 2c32048..5d5371c 100644 (file)
@@ -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();
index c07b24e..602ccc9 100644 (file)
@@ -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);
 }
 
 /*****************************************************************************/
index b260c3d..aa90341 100644 (file)
@@ -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);
 
index 0680763..1e92012 100644 (file)
@@ -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()
     {