[Local GC] Enable building the GC as a shared library (#13137)
authorSean Gillespie <segilles@microsoft.com>
Tue, 22 Aug 2017 17:20:36 +0000 (10:20 -0700)
committerGitHub <noreply@github.com>
Tue, 22 Aug 2017 17:20:36 +0000 (10:20 -0700)
* [Local GC] Build the GC using system headers

* Disable features to get the GC to build

* Get rid of the separate 'GC PAL' build

* Remove unused stuff

* Don't build gcenv.os.cpp when linking in a standalone gc

* Stub out CPUGroupInfo and NumaNodeInfo

* Stub out IsGCThread and friends

* Build the GC as a shared library :tada:

* Build, link, and run! :tada:

* Fix standalone GC build break

* Fixes where the GC's MethodTable and VM's MethodTable classes disagree

* Integrate a standalone GC into the CoreCLR build system (so it gets copied to the output folder). Re-enable some ifdef-ed out includes that are required for a non-standalone build of the GC.

* Bring changes to Unix and fix the Unix build. Implement some compiler intrinsic wrappers and alignment functions expected by the GC.

* Fix the Windows build

* 1. Code review feedback: use standard types for BitScanForward and
   BitScanForward64
2. Delete FEATURE_COM stuff from the build system, not needed for this
PR
3. Fix the Unix build

* Fix the Windows x86 build - the _BitScanForward64 intrinsic is not available when targeting 32-bit platforms

* Remove a number of things from gcenv.base.h that are not used

* Remove a linker workaround now that we are not linking a standalone GC into the runtime

* Remove dead code, make the lack of GC_PROFILING for standalone gc not break profiling on the non-standalone build

* Code review feedback - use add_library_clr and other cmake-related fixes

* Fix include indentation

* Remove some extraneous parameters to cmake functions (cmake is remarkably lenient...)

31 files changed:
CMakeLists.txt
clrdefinitions.cmake
clrfeatures.cmake
functions.cmake
src/CMakeLists.txt
src/dlls/mscoree/coreclr/CMakeLists.txt
src/dlls/mscoree/mscorwks_unixexports.src
src/gc/CMakeLists.txt
src/gc/WarningControl.h [new file with mode: 0644]
src/gc/env/gcenv.base.h
src/gc/env/gcenv.h [new file with mode: 0644]
src/gc/env/gcenv.object.h
src/gc/gc.h
src/gc/gcenv.ee.standalone.inl
src/gc/gcenv.inl [new file with mode: 0644]
src/gc/gcinterface.h
src/gc/gcpriv.h
src/gc/gcscan.h
src/gc/gcsvr.cpp
src/gc/gcwks.cpp
src/gc/handletablecore.cpp
src/gc/objecthandle.cpp
src/gc/objecthandle.h
src/gc/sample/GCSample.cpp
src/gc/sample/gcenv.ee.cpp
src/gc/unix/configure.cmake
src/gc/unix/events.cpp
src/gc/unix/gcenv.unix.cpp
src/vm/CMakeLists.txt
src/vm/ceemain.cpp
src/vm/proftoeeinterfaceimpl.cpp

index 38461ac..9e1d16d 100644 (file)
@@ -575,6 +575,13 @@ if(WIN32)
   add_compile_options(/Zl) # omit default library name in .OBJ
 endif(WIN32)
 
+#--------------------------------
+# Definition directives
+#  - all clr specific compile definitions should be included in this file
+#  - all clr specific feature variable should also be added in this file
+#----------------------------------
+include(clrdefinitions.cmake)
+
 #-------------------------------------
 # Include directory directives
 #-------------------------------------
@@ -584,10 +591,7 @@ include_directories("bin/obj")
 
 if(FEATURE_STANDALONE_GC)
   add_definitions(-DFEATURE_STANDALONE_GC)
-
-  if(CLR_CMAKE_PLATFORM_UNIX)
-    add_subdirectory(src/gc/unix)
-  endif(CLR_CMAKE_PLATFORM_UNIX)
+  add_subdirectory(src/gc)
 endif(FEATURE_STANDALONE_GC)
 
 if(FEATURE_STANDALONE_GC_ONLY)
@@ -600,13 +604,6 @@ if (CLR_CMAKE_PLATFORM_UNIX)
   include_directories("src/pal/src/safecrt")
 endif (CLR_CMAKE_PLATFORM_UNIX)
 
-#--------------------------------
-# Definition directives
-#  - all clr specific compile definitions should be included in this file
-#  - all clr specific feature variable should also be added in this file
-#----------------------------------
-include(clrdefinitions.cmake)
-
 # Microsoft.Dotnet.BuildTools.Coreclr version
 set(BuildToolsVersion "1.0.4-prerelease")
 set(BuildToolsDir "${CLR_DIR}/packages/Microsoft.DotNet.BuildTools.CoreCLR/${BuildToolsVersion}")
index 1848e3b..4f6b041 100644 (file)
@@ -78,8 +78,10 @@ if(WIN32)
 endif(WIN32)
 
 # Features - please keep them alphabetically sorted
+if (FEATURE_APPDOMAIN_RESOURCE_MONITORING)
+  add_definitions(-DFEATURE_APPDOMAIN_RESOURCE_MONITORING)
+endif(FEATURE_APPDOMAIN_RESOURCE_MONITORING)
 
-add_definitions(-DFEATURE_APPDOMAIN_RESOURCE_MONITORING)
 if(WIN32)
   add_definitions(-DFEATURE_APPX)
   if(NOT CLR_CMAKE_TARGET_ARCH_I386)
index f047c91..fde04d2 100644 (file)
@@ -2,6 +2,11 @@ if(CLR_CMAKE_TARGET_TIZEN_LINUX)
   set(FEATURE_EVENT_TRACE 0)
 endif()
 
+if(FEATURE_STANDALONE_GC_ONLY)
+  set(FEATURE_EVENT_TRACE 0)
+  set(FEATURE_APPDOMAIN_RESOURCE_MONITORING 0)
+endif()
+
 if(NOT DEFINED FEATURE_EVENT_TRACE)
   if (WIN32)
     set(FEATURE_EVENT_TRACE 1)
@@ -25,7 +30,6 @@ endif(NOT DEFINED FEATURE_DBGIPC)
 if(NOT DEFINED FEATURE_INTERPRETER)
   set(FEATURE_INTERPRETER 0)
 endif(NOT DEFINED FEATURE_INTERPRETER)
-
 if(NOT WIN32)
   if(NOT DEFINED FEATURE_NI_BIND_FALLBACK)
     if(NOT CLR_CMAKE_TARGET_ARCH_AMD64 AND NOT CLR_CMAKE_TARGET_ARCH_ARM64)
@@ -33,3 +37,8 @@ if(NOT WIN32)
     endif()
   endif(NOT DEFINED FEATURE_NI_BIND_FALLBACK)
 endif(NOT WIN32)
+
+if(NOT DEFINED FEATURE_APPDOMAIN_RESOURCE_MONITORING)
+  set(FEATURE_APPDOMAIN_RESOURCE_MONITORING 1)
+endif(NOT DEFINED FEATURE_APPDOMAIN_RESOURCE_MONITORING)
+
index cf4d08f..3ed9536 100644 (file)
@@ -237,3 +237,30 @@ function(verify_dependencies targetName errorMessage)
         )
     endif()
 endfunction()
+
+function(add_library_clr)
+    if(NOT WIN32)
+      add_library(${ARGV} ${VERSION_FILE_PATH})
+    else()
+      add_library(${ARGV})
+    endif(NOT WIN32)
+    add_dependencies(${ARGV0} GeneratedEventingFiles)
+    list(FIND CLR_CROSS_COMPONENTS_LIST ${ARGV0} INDEX)  
+    if (DEFINED CLR_CROSS_COMPONENTS_LIST AND ${INDEX} EQUAL -1)  
+     set_target_properties(${ARGV0} PROPERTIES EXCLUDE_FROM_ALL 1)  
+    endif()  
+endfunction()
+
+function(add_executable_clr)
+    if(NOT WIN32)
+      add_executable(${ARGV} ${VERSION_FILE_PATH})
+    else()
+      add_executable(${ARGV})
+    endif(NOT WIN32)
+    add_dependencies(${ARGV0} GeneratedEventingFiles)
+    list(FIND CLR_CROSS_COMPONENTS_LIST ${ARGV0} INDEX)  
+    if (DEFINED CLR_CROSS_COMPONENTS_LIST AND ${INDEX} EQUAL -1)  
+     set_target_properties(${ARGV0} PROPERTIES EXCLUDE_FROM_ALL 1)  
+    endif()  
+endfunction()
+
index ba17dc0..900ba96 100644 (file)
@@ -155,9 +155,6 @@ add_subdirectory(utilcode)
 add_subdirectory(gcinfo)
 add_subdirectory(coreclr)
 add_subdirectory(jit)
-if(FEATURE_STANDALONE_GC)
-  add_subdirectory(gc)
-endif(FEATURE_STANDALONE_GC)
 add_subdirectory(vm)
 add_subdirectory(md)
 add_subdirectory(debug)
index 81aaad4..8796cc1 100644 (file)
@@ -73,10 +73,6 @@ if(FEATURE_MERGE_JIT_AND_ENGINE)
     set(CLRJIT_STATIC clrjit_static)
 endif(FEATURE_MERGE_JIT_AND_ENGINE)
 
-if(FEATURE_STANDALONE_GC_ONLY)
-    set(STANDALONE_GC gc_standalone)
-endif(FEATURE_STANDALONE_GC_ONLY)
-
 # IMPORTANT! Please do not rearrange the order of the libraries. The linker on Linux is
 # order dependent and changing the order can result in undefined symbols in the shared 
 # library.
@@ -87,7 +83,6 @@ set(CORECLR_LIBRARIES
     debug-pal
     ${LIB_UNWINDER}
     cee_wks
-    ${STANDALONE_GC}
     ${END_LIBRARY_GROUP} # End group of libraries that have circular references
     mdcompiler_wks
     mdruntime_wks
@@ -133,12 +128,6 @@ else()
     )
 endif(WIN32)
 
-if(CLR_CMAKE_PLATFORM_UNIX AND FEATURE_STANDALONE_GC)
-    list(APPEND CORECLR_LIBRARIES
-        gc_unix
-    )
-endif(CLR_CMAKE_PLATFORM_UNIX AND FEATURE_STANDALONE_GC)
-
 if(CLR_CMAKE_PLATFORM_UNIX AND FEATURE_EVENT_TRACE)
     list(APPEND CORECLR_LIBRARIES
         eventprovider
index e9a994c..1076d17 100644 (file)
@@ -112,5 +112,3 @@ SetThreadAffinityMask
 GetThreadGroupAffinity
 GetCurrentProcessorNumberEx
 
-; Function for initializing a standalone GC
-InitializeGarbageCollector
index 4de3f4e..21eb660 100644 (file)
@@ -1,15 +1,5 @@
 set(CMAKE_INCLUDE_CURRENT_DIR ON)
 
-include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR})
-include_directories(BEFORE ${CLR_DIR}/src/vm)
-include_directories(BEFORE ${CLR_DIR}/src/vm/${ARCH_SOURCES_DIR})
-
-add_definitions(-DBUILD_AS_STANDALONE)
-
-if(CLR_CMAKE_PLATFORM_UNIX)
-  add_compile_options(-fPIC)
-endif(CLR_CMAKE_PLATFORM_UNIX)
-
 set( GC_SOURCES
   gcconfig.cpp
   gccommon.cpp
@@ -26,12 +16,48 @@ set( GC_SOURCES
   gceewks.cpp
   handletablecache.cpp)
 
-if(NOT CLR_CMAKE_PLATFORM_UNIX)
-set ( GC_SOURCES
-  ${GC_SOURCES}
-  windows/gcenv.windows.cpp)
-endif(NOT CLR_CMAKE_PLATFORM_UNIX)
+if(CLR_CMAKE_PLATFORM_UNIX)
+  include(unix/configure.cmake)
+  set ( GC_SOURCES
+    ${GC_SOURCES}
+    unix/gcenv.unix.cpp
+    unix/events.cpp
+    unix/cgroup.cpp)
+else()
+  set ( GC_SOURCES
+    ${GC_SOURCES}
+    windows/gcenv.windows.cpp)
+endif(CLR_CMAKE_PLATFORM_UNIX)
+
+if(WIN32)
+  set (GC_LINK_LIBRARIES
+    ${STATIC_MT_CRT_LIB}
+    ${STATIC_MT_VCRT_LIB}
+    kernel32.lib)
+else()
+  set (GC_LINK_LIBRARIES)
+endif(WIN32)
 
 convert_to_absolute_path(GC_SOURCES ${GC_SOURCES})
 
-add_library_clr(gc_standalone STATIC ${GC_SOURCES})
+add_library_clr(gc SHARED ${GC_SOURCES})
+target_link_libraries(gc ${GC_LINK_LIBRARIES})
+install_clr(gc)
+
+if(CLR_CMAKE_PLATFORM_UNIX)
+  add_compile_options(-fPIC)
+  # dprintf causes many warnings
+  add_compile_options(-Wno-format)
+endif(CLR_CMAKE_PLATFORM_UNIX)
+
+add_definitions(-DBUILD_AS_STANDALONE)
+if(CLR_CMAKE_PLATFORM_DARWIN)
+  # The implementation of GCToOSInterface on MacOS makes use of non-POSIX
+  # pthreads APIs, which by default are not included in the pthreads header
+  # unless we define this macro.
+  add_definitions(-D_DARWIN_C_SOURCE)
+endif(CLR_CMAKE_PLATFORM_DARWIN)
+
+include_directories(${CMAKE_CURRENT_SOURCE_DIR})
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/env)
+
diff --git a/src/gc/WarningControl.h b/src/gc/WarningControl.h
new file mode 100644 (file)
index 0000000..e69de29
index 1e9406c..98a4235 100644 (file)
@@ -7,10 +7,11 @@
 // Sets up basic environment for CLR GC
 //
 
-#define FEATURE_REDHAWK 1
-#define FEATURE_CONSERVATIVE_GC 1
+#ifdef _MSC_VER
+#include <intrin.h>
+#endif // _MSC_VER
 
-#define GCENV_INCLUDED
+#define FEATURE_REDHAWK 1
 
 #define REDHAWK_PALIMPORT extern "C"
 #define REDHAWK_PALAPI __stdcall
 #else // __clang__
 #define __forceinline inline
 #endif // __clang__
-#endif // !_MSC_VER
+// [LOCALGC TODO] is there a better place for this?
+#define NOINLINE __attribute__((noinline))
+#else // !_MSC_VER
+#define NOINLINE __declspec(noinline)
+#endif // _MSC_VER
 
 #ifndef SIZE_T_MAX
 #define SIZE_T_MAX ((size_t)-1)
@@ -39,6 +44,7 @@
 
 typedef int BOOL;
 typedef uint32_t DWORD;
+typedef uint64_t DWORD64;
 
 // -----------------------------------------------------------------------------------------------------------
 // HRESULT subset.
@@ -59,12 +65,8 @@ inline HRESULT HRESULT_FROM_WIN32(unsigned long x)
 }
 
 #define S_OK                    0x0
-#define S_FALSE                 0x1
 #define E_FAIL                  0x80004005
 #define E_OUTOFMEMORY           0x8007000E
-#define E_UNEXPECTED            0x8000FFFF
-#define E_NOTIMPL               0x80004001
-#define E_INVALIDARG            0x80070057
 #define COR_E_EXECUTIONENGINE   0x80131506
 
 #define NOERROR                 0x0
@@ -100,6 +102,8 @@ inline HRESULT HRESULT_FROM_WIN32(unsigned long x)
 #define _vsnprintf_s(string, sizeInBytes, count, format, args) vsnprintf(string, sizeInBytes, format, args)
 #define sprintf_s snprintf
 #define swprintf_s swprintf
+#define _snprintf_s(string, sizeInBytes, count, format, ...) \
+  snprintf(string, sizeInBytes, format, ## __VA_ARGS__)
 #endif
 
 #ifdef UNICODE
@@ -161,8 +165,8 @@ typedef DWORD (WINAPI *PTHREAD_START_ROUTINE)(void* lpThreadParameter);
  #elif defined(_X86_)
   
   #define YieldProcessor() __asm { rep nop }
-
-  __forceinline void MemoryBarrier()
+  #define MemoryBarrier() MemoryBarrierImpl()
+  __forceinline void MemoryBarrierImpl()
   {
       int32_t Barrier;
       __asm {
@@ -175,7 +179,145 @@ typedef DWORD (WINAPI *PTHREAD_START_ROUTINE)(void* lpThreadParameter);
  #endif
 #else // _MSC_VER
 
+// Only clang defines __has_builtin, so we first test for a GCC define
+// before using __has_builtin.
+
+#if defined(__i386__) || defined(__x86_64__)
+
+#if (__GNUC__ > 4 && __GNUC_MINOR > 7) || __has_builtin(__builtin_ia32_pause)
+ // clang added this intrinsic in 3.8
+ // gcc added this intrinsic by 4.7.1
+ #define YieldProcessor __builtin_ia32_pause
+#endif // __has_builtin(__builtin_ia32_pause)
+
+#if defined(__GNUC__) || __has_builtin(__builtin_ia32_mfence)
+ // clang has had this intrinsic since at least 3.0
+ // gcc has had this intrinsic since forever
+ #define MemoryBarrier __builtin_ia32_mfence
+#endif // __has_builtin(__builtin_ia32_mfence)
+
+// If we don't have intrinsics, we can do some inline asm instead.
+#ifndef YieldProcessor
+ #define YieldProcessor() asm volatile ("pause")
+#endif // YieldProcessor
+
+#ifndef MemoryBarrier
+ #define MemoryBarrier() asm volatile ("mfence")
+#endif // MemoryBarrier
+
+#endif // defined(__i386__) || defined(__x86_64__)
+
+#endif // _MSC_VER
+
+#ifndef YieldProcessor
+ #error "Don't know how to YieldProcessor on this architecture"
+#endif
+
+#ifndef MemoryBarrier
+ #error "Don't know how to MemoryBarrier on this architecture"
+#endif
+
+#ifdef _MSC_VER
+#pragma intrinsic(_BitScanForward)
+#if WIN64
+ #pragma intrinsic(_BitScanForward64)
+#endif
+#endif // _MSC_VER
+
+// Cross-platform wrapper for the _BitScanForward compiler intrinsic.
+inline uint8_t BitScanForward(uint32_t *bitIndex, uint32_t mask)
+{
+#ifdef _MSC_VER
+    return _BitScanForward((unsigned long*)bitIndex, mask);
+#else // _MSC_VER
+    unsigned char ret = FALSE;
+    int iIndex = __builtin_ffsl(mask);
+    if (iIndex != 0)
+    {
+        *bitIndex = (uint32_t)(iIndex - 1);
+        ret = TRUE;
+    }
+
+    return ret;
 #endif // _MSC_VER
+}
+
+// Cross-platform wrapper for the _BitScanForward64 compiler intrinsic.
+inline uint8_t BitScanForward64(uint32_t *bitIndex, uint64_t mask)
+{
+#ifdef _MSC_VER
+ #if _WIN32
+    // MSVC targeting a 32-bit target does not support this intrinsic.
+    // We can fake it using two successive invocations of _BitScanForward.
+    uint32_t hi = (mask >> 32) & 0xFFFFFFFF;
+    uint32_t lo = mask & 0xFFFFFFFF;
+    uint32_t fakeBitIndex = 0;
+    if (BitScanForward(&fakeBitIndex, hi))
+    {
+        *bitIndex = fakeBitIndex + 32;
+    }
+
+    return BitScanForward(bitIndex, lo);
+ #else
+    return _BitScanForward64((unsigned long*)bitIndex, mask);
+ #endif // _WIN32
+#else
+    unsigned char ret = FALSE;
+    int iIndex = __builtin_ffsll(mask);
+    if (iIndex != 0)
+    {
+        *bitIndex = (uint32_t)(iIndex - 1);
+        ret = TRUE;
+    }
+
+    return ret;
+#endif // _MSC_VER
+}
+
+// Aligns a size_t to the specified alignment. Alignment must be a power
+// of two.
+inline size_t ALIGN_UP(size_t val, size_t alignment)
+{
+    // alignment factor must be power of two
+    assert((alignment & (alignment - 1)) == 0);
+    size_t result = (val + (alignment - 1)) & ~(alignment - 1);
+    assert(result >= val);
+    return result;
+}
+
+// Aligns a pointer to the specified alignment. Alignment must be a power
+// of two.
+inline uint8_t* ALIGN_UP(uint8_t* ptr, size_t alignment)
+{
+    size_t as_size_t = reinterpret_cast<size_t>(ptr);
+    return reinterpret_cast<uint8_t*>(ALIGN_UP(as_size_t, alignment));
+}
+
+// Aligns a size_t to the specified alignment by rounding down. Alignment must
+// be a power of two.
+inline size_t ALIGN_DOWN(size_t val, size_t alignment)
+{
+    // alignment factor must be power of two.
+    assert((alignment & (alignment - 1)) == 0);
+    size_t result = val & ~(alignment - 1);
+    return result;
+}
+
+// Aligns a pointer to the specified alignment by rounding down. Alignment
+// must be a power of two.
+inline uint8_t* ALIGN_DOWN(uint8_t* ptr, size_t alignment)
+{
+    size_t as_size_t = reinterpret_cast<size_t>(ptr);
+    return reinterpret_cast<uint8_t*>(ALIGN_DOWN(as_size_t, alignment));
+}
+
+// Aligns a void pointer to the specified alignment by rounding down. Alignment
+// must be a power of two.
+inline void* ALIGN_DOWN(void* ptr, size_t alignment)
+{
+    size_t as_size_t = reinterpret_cast<size_t>(ptr);
+    return reinterpret_cast<void*>(ALIGN_DOWN(as_size_t, alignment));
+}
 
 typedef struct _PROCESSOR_NUMBER {
     uint16_t Group;
@@ -241,75 +383,25 @@ typedef struct _PROCESSOR_NUMBER {
 //
 // Data access macros
 //
-#ifdef DACCESS_COMPILE
-#include "daccess.h"
-#else // DACCESS_COMPILE
 typedef uintptr_t TADDR;
-
 #define PTR_TO_TADDR(ptr) ((TADDR)(ptr))
 
 #define DPTR(type) type*
 #define SPTR(type) type*
-
-#define GVAL_DECL(type, var) \
-    extern type var
-#define GVAL_IMPL(type, var) \
-    type var
-#define GVAL_IMPL_INIT(type, var, init) \
-    type var = init
-
-#define GPTR_DECL(type, var) \
-    extern type* var
-#define GPTR_IMPL(type, var) \
-    type* var
-#define GPTR_IMPL_INIT(type, var, init) \
-    type* var = init
-
-#define SPTR_DECL(type, var) \
-    static type* var
-#define SPTR_IMPL(type, cls, var) \
-    type * cls::var
-#define SPTR_IMPL_NS(type, ns, cls, var) \
-    type * cls::var
-#define SPTR_IMPL_NS_INIT(type, ns, cls, var, init) \
-    type * cls::var = init
-
-#define SVAL_DECL(type, var) \
-    static type var
-#define SVAL_IMPL_NS(type, ns, cls, var) \
-    type cls::var
-#define SVAL_IMPL_NS_INIT(type, ns, cls, var, init) \
-    type cls::var = init
-
-#define GARY_DECL(type, var, size) \
-    extern type var[size]
-#define GARY_IMPL(type, var, size) \
-    type var[size]
-
-struct _DacGlobals;
-#endif // DACCESS_COMPILE
-
 typedef DPTR(size_t)    PTR_size_t;
 typedef DPTR(uint8_t)   PTR_uint8_t;
 
 // -----------------------------------------------------------------------------------------------------------
 
 #define DATA_ALIGNMENT sizeof(uintptr_t)
-
 #define RAW_KEYWORD(x) x
-
 #define DECLSPEC_ALIGN(x)   __declspec(align(x))
-
 #ifndef _ASSERTE
 #define _ASSERTE(_expr) ASSERT(_expr)
 #endif
-
 #define CONSISTENCY_CHECK(_expr) ASSERT(_expr)
-
 #define PREFIX_ASSUME(cond) ASSERT(cond)
-
 #define EEPOLICY_HANDLE_FATAL_ERROR(error) ASSERT(!"EEPOLICY_HANDLE_FATAL_ERROR")
-
 #define UI64(_literal) _literal##ULL
 
 class ObjHeader;
@@ -331,7 +423,7 @@ typedef PTR_PTR_Object PTR_UNCHECKED_OBJECTREF;
 #define ObjectToOBJECTREF(_obj) (OBJECTREF)(_obj)
 #define OBJECTREFToObject(_obj) (Object*)(_obj)
 
-#define VALIDATEOBJECTREF(_objref) _objref;
+#define VALIDATEOBJECTREF(_objref) (void)_objref;
 
 #define VOLATILE(T) T volatile
 
@@ -451,24 +543,13 @@ void VolatileStore(T* pt, T val)
 #endif
 }
 
-extern GCSystemInfo g_SystemInfo;
-
-extern MethodTable * g_pFreeObjectMethodTable;
-
-extern int32_t g_TrapReturningThreads;
-
-//
-// Locks
-//
-
-struct gc_alloc_context;
 class Thread;
 
-Thread * GetThread();
-
-typedef void (CALLBACK *HANDLESCANPROC)(PTR_UNCHECKED_OBJECTREF pref, uintptr_t *pExtraInfo, uintptr_t param1, uintptr_t param2);
-
-bool IsGCSpecialThread();
+inline bool IsGCSpecialThread()
+{
+    // [LOCALGC TODO] this is not correct
+    return false;
+}
 
 inline bool dbgOnly_IsSpecialEEThread()
 {
@@ -498,42 +579,11 @@ namespace ETW
     } GC_ROOT_KIND;
 };
 
-//
-// Logging
-//
-
-void LogSpewAlways(const char *fmt, ...);
-
-#define DEFAULT_GC_PRN_LVL 3
-
-// -----------------------------------------------------------------------------------------------------------
-
-bool IsGCThread();
-
-class CLRConfig
+inline bool IsGCThread()
 {
-public:
-    enum CLRConfigTypes
-    {
-        UNSUPPORTED_GCLogEnabled,
-        UNSUPPORTED_GCLogFile,
-        UNSUPPORTED_GCLogFileSize,
-        UNSUPPORTED_GCConfigLogEnabled,
-        UNSUPPORTED_GCConfigLogFile,
-        UNSUPPORTED_BGCSpinCount,
-        UNSUPPORTED_BGCSpin,
-        EXTERNAL_GCStressStart,
-        INTERNAL_GCStressStartAtJit,
-        INTERNAL_DbgDACSkipVerifyDlls,
-        Config_COUNT
-    };
-
-    typedef CLRConfigTypes ConfigDWORDInfo;
-    typedef CLRConfigTypes ConfigStringInfo;
-
-    static uint32_t GetConfigValue(ConfigDWORDInfo eType);
-    static HRESULT GetConfigValue(ConfigStringInfo /*eType*/, __out_z TCHAR * * outVal);
-};
+    // [LOCALGC TODO] this is not correct
+    return false;
+}
 
 inline bool FitsInU1(uint64_t val)
 {
@@ -577,46 +627,50 @@ public:
     DWORD GetTotalNumSizedRefHandles() { return 0; }
 };
 
-#ifdef STRESS_HEAP
-namespace GCStressPolicy
+class NumaNodeInfo
 {
-    static volatile int32_t s_cGcStressDisables;
+public:
+    static bool CanEnableGCNumaAware()
+    {
+        // [LOCALGC TODO] enable NUMA node support
+        return false;
+    }
 
-    inline bool IsEnabled() { return s_cGcStressDisables == 0; }
-    inline void GlobalDisable() { Interlocked::Increment(&s_cGcStressDisables); }
-    inline void GlobalEnable() { Interlocked::Decrement(&s_cGcStressDisables); }
-}
+    static void GetGroupForProcessor(uint16_t processor_number, uint16_t * group_number, uint16_t * group_processor_number)
+    {
+        // [LOCALGC TODO] enable NUMA node support
+        assert(!"should not be called");
+    }
 
-enum gcs_trigger_points
-{
-    cfg_any,
+    static bool GetNumaProcessorNodeEx(PPROCESSOR_NUMBER proc_no, uint16_t * node_no)
+    {
+        // [LOCALGC TODO] enable NUMA node support
+        assert(!"should not be called");
+        return false;
+    }
 };
 
-template <enum gcs_trigger_points tp>
-class GCStress
+class CPUGroupInfo
 {
 public:
-    static inline bool IsEnabled()
+    static bool CanEnableGCCPUGroups()
     {
-        return g_pConfig->GetGCStressLevel() != 0;
+        // [LOCALGC TODO] enable CPU group support
+        return false;
     }
-};
-#endif // STRESS_HEAP
 
-class NumaNodeInfo
-{
-public:
-    static bool CanEnableGCNumaAware();
-    static void GetGroupForProcessor(uint16_t processor_number, uint16_t * group_number, uint16_t * group_processor_number);
-    static bool GetNumaProcessorNodeEx(PPROCESSOR_NUMBER proc_no, uint16_t * node_no);
-};
+    static uint32_t GetNumActiveProcessors()
+    {
+        // [LOCALGC TODO] enable CPU group support
+        assert(!"should not be called");
+        return 0;
+    }
 
-class CPUGroupInfo
-{
-public:
-    static bool CanEnableGCCPUGroups();
-    static uint32_t GetNumActiveProcessors();
-    static void GetGroupForProcessor(uint16_t processor_number, uint16_t * group_number, uint16_t * group_processor_number);
+    static void GetGroupForProcessor(uint16_t processor_number, uint16_t * group_number, uint16_t * group_processor_number)
+    {
+        // [LOCALGC TODO] enable CPU group support
+        assert(!"should not be called");
+    }
 };
 
 
diff --git a/src/gc/env/gcenv.h b/src/gc/env/gcenv.h
new file mode 100644 (file)
index 0000000..c69f5f9
--- /dev/null
@@ -0,0 +1,72 @@
+// 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.
+
+#if defined(_DEBUG)
+#ifndef _DEBUG_IMPL
+#define _DEBUG_IMPL 1
+#endif
+#define ASSERT(_expr) assert(_expr)
+#else
+#define ASSERT(_expr)
+#endif
+
+#ifndef _ASSERTE
+#define _ASSERTE(_expr) ASSERT(_expr)
+#endif
+
+#include "gcenv.structs.h"
+#include "gcenv.base.h"
+#include "gcenv.os.h"
+#include "gcenv.interlocked.h"
+#include "gcenv.interlocked.inl"
+#include "gcenv.object.h"
+#include "gcenv.sync.h"
+#include "gcinterface.h"
+#include "gcenv.ee.h"
+
+#define MAX_LONGPATH 1024
+
+#ifdef _MSC_VER
+#define SUPPRESS_WARNING_4127   \
+    __pragma(warning(push))     \
+    __pragma(warning(disable:4127)) /* conditional expression is constant*/
+#define POP_WARNING_STATE       \
+    __pragma(warning(pop))
+#else // _MSC_VER
+#define SUPPRESS_WARNING_4127
+#define POP_WARNING_STATE
+#endif // _MSC_VER
+
+#define WHILE_0             \
+    SUPPRESS_WARNING_4127   \
+    while(0)                \
+    POP_WARNING_STATE       \
+
+#define LL_INFO10 4
+
+#define STRESS_LOG_VA(msg)                                              do { } WHILE_0
+#define STRESS_LOG0(facility, level, msg)                               do { } WHILE_0
+#define STRESS_LOG1(facility, level, msg, data1)                        do { } WHILE_0
+#define STRESS_LOG2(facility, level, msg, data1, data2)                 do { } WHILE_0
+#define STRESS_LOG3(facility, level, msg, data1, data2, data3)          do { } WHILE_0
+#define STRESS_LOG4(facility, level, msg, data1, data2, data3, data4)   do { } WHILE_0
+#define STRESS_LOG5(facility, level, msg, data1, data2, data3, data4, data5)   do { } WHILE_0
+#define STRESS_LOG6(facility, level, msg, data1, data2, data3, data4, data5, data6)   do { } WHILE_0
+#define STRESS_LOG7(facility, level, msg, data1, data2, data3, data4, data5, data6, data7)   do { } WHILE_0
+#define STRESS_LOG_PLUG_MOVE(plug_start, plug_end, plug_delta)          do { } WHILE_0
+#define STRESS_LOG_ROOT_PROMOTE(root_addr, objPtr, methodTable)         do { } WHILE_0
+#define STRESS_LOG_ROOT_RELOCATE(root_addr, old_value, new_value, methodTable) do { } WHILE_0
+#define STRESS_LOG_GC_START(gcCount, Gen, collectClasses)               do { } WHILE_0
+#define STRESS_LOG_GC_END(gcCount, Gen, collectClasses)                 do { } WHILE_0
+#define STRESS_LOG_OOM_STACK(size)   do { } while(0)
+#define STRESS_LOG_RESERVE_MEM(numChunks) do {} while (0)
+#define STRESS_LOG_GC_STACK
+
+#define LOG(x)
+
+#define SVAL_IMPL_INIT(type, cls, var, init) \
+    type cls::var = init
+
+#include "etmdummy.h"
+#define ETW_EVENT_ENABLED(e,f) false
index db8995a..4261c1a 100644 (file)
@@ -33,9 +33,11 @@ public:
 
 static_assert(sizeof(ObjHeader) == sizeof(uintptr_t), "this assumption is made by the VM!");
 
-#define MTFlag_ContainsPointers 1
-#define MTFlag_HasFinalizer 2
-#define MTFlag_IsArray 4
+#define MTFlag_ContainsPointers 0x0100
+#define MTFlag_HasFinalizer     0x0010
+#define MTFlag_IsArray          0x0008
+#define MTFlag_Collectible      0x1000
+#define MTFlag_HasComponentSize 0x8000
 
 class MethodTable
 {
@@ -64,6 +66,11 @@ public:
         return m_componentSize;
     }
 
+    bool Collectible()
+    {
+        return (m_flags & MTFlag_Collectible) != 0;
+    }
+
     bool ContainsPointers()
     {
         return (m_flags & MTFlag_ContainsPointers) != 0;
@@ -71,12 +78,19 @@ public:
 
     bool ContainsPointersOrCollectible()
     {
-        return ContainsPointers();
+        return ContainsPointers() || Collectible();
     }
 
     bool HasComponentSize()
     {
-        return m_componentSize != 0;
+        // Note that we can't just check m_componentSize != 0 here. The VM 
+        // may still construct a method table that does not have a component 
+        // size, according to this method, but still has a number in the low 
+        // 16 bits of the method table flags parameter.
+        //
+        // The solution here is to do what the VM does and check the
+        // HasComponentSize flag so that we're on the same page.
+        return (m_flags & MTFlag_HasComponentSize) != 0;
     }
 
     bool HasFinalizer()
@@ -104,6 +118,12 @@ public:
     {
         return true;
     }
+
+    uint8_t* GetLoaderAllocatorObjectForGC()
+    {
+        // [LOCALGC TODO] this is not correct
+        return nullptr;
+    }
 };
 
 class Object
index 4e722c4..e16fccb 100644 (file)
@@ -197,11 +197,6 @@ struct alloc_context : gc_alloc_context
 };
 
 class IGCHeapInternal : public IGCHeap {
-    friend struct ::_DacGlobals;
-#ifdef DACCESS_COMPILE
-    friend class ClrDataAccess;
-#endif
-    
 public:
 
     virtual ~IGCHeapInternal() {}
index c66acf0..0dcf05d 100644 (file)
 #define __GCTOENV_EE_STANDALONE_INL__
 
 #include "gcinterface.h"
+#include "env/gcenv.ee.h"
 
 // The singular interface instance. All calls in GCToEEInterface
 // will be fowarded to this interface instance.
 extern IGCToCLR* g_theGCToCLR;
 
-namespace
-{
-
-#include "env/gcenv.ee.h"
-
-// A note about this:
-// In general, we don't want to pretend to be smarter than the compiler
-// and force it to inline things. However, inlining is here is required
-// for correctness as it stands today (though it will not always be required).
-//
-// The reason for this is because:
-//   1) This file (and the GCToEEInterface class) define symbols that are inline
-//      and static, so the symbol GCToEEInterface::XYZ defines a symbol with weak
-//      linkage when the function is not inlined,
-//   2) src/vm/gcenv.ee.cpp all define symbols that are not inline and instance methods
-//      of GCToEEInterface, with external linkage.
-//   3) When it comes time to link the GC and the VM, the linker observes the duplicate
-//      symbols and discards the one with weak linkage.
-//   4) All of the calls within the GC to the functions in this file are replaced by
-//      the linker to calls to the implementation of a pure virtual IGCToCLR. The
-//      functions implementing IGCToCLR have an extra argument (this).
-//   5) Now, all calls to these functions from within the GC are doomed because of the
-//      functions that actually get called expect this to be in rdi, where the compiler
-//      has placed the first argument instead.
-//
-// For now, by forcing the compiler to inline these functions, the compiler won't actually
-// emit symbols for them and we'll avoid the linker havoc.
-#ifdef _MSC_VER
- #define ALWAYS_INLINE __forceinline
-#else
- #define ALWAYS_INLINE __attribute__((always_inline)) inline
-#endif
-
 // When we are building the GC in a standalone environment, we
 // will be dispatching virtually against g_theGCToCLR to call
 // into the EE. This class provides an identical API to the existing
 // GCToEEInterface, but only forwards the call onto the global
 // g_theGCToCLR instance.
-ALWAYS_INLINE void GCToEEInterface::SuspendEE(SUSPEND_REASON reason)
+inline void GCToEEInterface::SuspendEE(SUSPEND_REASON reason)
 {
     assert(g_theGCToCLR != nullptr);
     g_theGCToCLR->SuspendEE(reason);
 }
 
-ALWAYS_INLINE void GCToEEInterface::RestartEE(bool bFinishedGC)
+inline void GCToEEInterface::RestartEE(bool bFinishedGC)
 {
     assert(g_theGCToCLR != nullptr);
     g_theGCToCLR->RestartEE(bFinishedGC);
 }
 
-ALWAYS_INLINE void GCToEEInterface::GcScanRoots(promote_func* fn, int condemned, int max_gen, ScanContext* sc)
+inline void GCToEEInterface::GcScanRoots(promote_func* fn, int condemned, int max_gen, ScanContext* sc)
 {
     assert(g_theGCToCLR != nullptr);
     g_theGCToCLR->GcScanRoots(fn, condemned, max_gen, sc);
 }
 
-ALWAYS_INLINE void GCToEEInterface::GcStartWork(int condemned, int max_gen)
+inline void GCToEEInterface::GcStartWork(int condemned, int max_gen)
 {
     assert(g_theGCToCLR != nullptr);
     g_theGCToCLR->GcStartWork(condemned, max_gen);
 }
 
-ALWAYS_INLINE void GCToEEInterface::AfterGcScanRoots(int condemned, int max_gen, ScanContext* sc)
+inline void GCToEEInterface::AfterGcScanRoots(int condemned, int max_gen, ScanContext* sc)
 {
     assert(g_theGCToCLR != nullptr);
     g_theGCToCLR->AfterGcScanRoots(condemned, max_gen, sc);
 }
 
-ALWAYS_INLINE void GCToEEInterface::GcBeforeBGCSweepWork()
+inline void GCToEEInterface::GcBeforeBGCSweepWork()
 {
     assert(g_theGCToCLR != nullptr);
     g_theGCToCLR->GcBeforeBGCSweepWork();
 }
 
-ALWAYS_INLINE void GCToEEInterface::GcDone(int condemned)
+inline void GCToEEInterface::GcDone(int condemned)
 {
     assert(g_theGCToCLR != nullptr);
     g_theGCToCLR->GcDone(condemned);
 }
 
-ALWAYS_INLINE bool GCToEEInterface::RefCountedHandleCallbacks(Object * pObject)
+inline bool GCToEEInterface::RefCountedHandleCallbacks(Object * pObject)
 {
     assert(g_theGCToCLR != nullptr);
     return g_theGCToCLR->RefCountedHandleCallbacks(pObject);
 }
 
-ALWAYS_INLINE void GCToEEInterface::SyncBlockCacheWeakPtrScan(HANDLESCANPROC scanProc, uintptr_t lp1, uintptr_t lp2)
+inline void GCToEEInterface::SyncBlockCacheWeakPtrScan(HANDLESCANPROC scanProc, uintptr_t lp1, uintptr_t lp2)
 {
     assert(g_theGCToCLR != nullptr);
     g_theGCToCLR->SyncBlockCacheWeakPtrScan(scanProc, lp1, lp2);
 }
 
-ALWAYS_INLINE void GCToEEInterface::SyncBlockCacheDemote(int max_gen)
+inline void GCToEEInterface::SyncBlockCacheDemote(int max_gen)
 {
     assert(g_theGCToCLR != nullptr);
     g_theGCToCLR->SyncBlockCacheDemote(max_gen);
 }
 
-ALWAYS_INLINE void GCToEEInterface::SyncBlockCachePromotionsGranted(int max_gen)
+inline void GCToEEInterface::SyncBlockCachePromotionsGranted(int max_gen)
 {
     assert(g_theGCToCLR != nullptr);
     g_theGCToCLR->SyncBlockCachePromotionsGranted(max_gen);
 }
 
-ALWAYS_INLINE bool GCToEEInterface::IsPreemptiveGCDisabled(Thread * pThread)
+inline bool GCToEEInterface::IsPreemptiveGCDisabled(Thread * pThread)
 {
     assert(g_theGCToCLR != nullptr);
     return g_theGCToCLR->IsPreemptiveGCDisabled(pThread);
 }
 
 
-ALWAYS_INLINE void GCToEEInterface::EnablePreemptiveGC(Thread * pThread)
+inline void GCToEEInterface::EnablePreemptiveGC(Thread * pThread)
 {
     assert(g_theGCToCLR != nullptr);
     g_theGCToCLR->EnablePreemptiveGC(pThread);
 }
 
-ALWAYS_INLINE void GCToEEInterface::DisablePreemptiveGC(Thread * pThread)
+inline void GCToEEInterface::DisablePreemptiveGC(Thread * pThread)
 {
     assert(g_theGCToCLR != nullptr);
     g_theGCToCLR->DisablePreemptiveGC(pThread);
 }
 
-ALWAYS_INLINE Thread* GCToEEInterface::GetThread()
+inline Thread* GCToEEInterface::GetThread()
 {
     assert(g_theGCToCLR != nullptr);
     return g_theGCToCLR->GetThread();
 }
 
-ALWAYS_INLINE bool GCToEEInterface::TrapReturningThreads()
+inline bool GCToEEInterface::TrapReturningThreads()
 {
     assert(g_theGCToCLR != nullptr);
     return g_theGCToCLR->TrapReturningThreads();
 }
 
-ALWAYS_INLINE gc_alloc_context * GCToEEInterface::GetAllocContext(Thread * pThread)
+inline gc_alloc_context * GCToEEInterface::GetAllocContext(Thread * pThread)
 {
     assert(g_theGCToCLR != nullptr);
     return g_theGCToCLR->GetAllocContext(pThread);
 }
 
-ALWAYS_INLINE bool GCToEEInterface::CatchAtSafePoint(Thread * pThread)
+inline bool GCToEEInterface::CatchAtSafePoint(Thread * pThread)
 {
     assert(g_theGCToCLR != nullptr);
     return g_theGCToCLR->CatchAtSafePoint(pThread);
 }
 
-ALWAYS_INLINE void GCToEEInterface::GcEnumAllocContexts(enum_alloc_context_func* fn, void* param)
+inline void GCToEEInterface::GcEnumAllocContexts(enum_alloc_context_func* fn, void* param)
 {
     assert(g_theGCToCLR != nullptr);
     g_theGCToCLR->GcEnumAllocContexts(fn, param);
 }
 
-ALWAYS_INLINE Thread* GCToEEInterface::CreateBackgroundThread(GCBackgroundThreadFunction threadStart, void* arg)
+inline Thread* GCToEEInterface::CreateBackgroundThread(GCBackgroundThreadFunction threadStart, void* arg)
 {
     assert(g_theGCToCLR != nullptr);
     return g_theGCToCLR->CreateBackgroundThread(threadStart, arg);
 }
 
-ALWAYS_INLINE void GCToEEInterface::DiagGCStart(int gen, bool isInduced)
+inline void GCToEEInterface::DiagGCStart(int gen, bool isInduced)
 {
     assert(g_theGCToCLR != nullptr);
     g_theGCToCLR->DiagGCStart(gen, isInduced);
 }
 
-ALWAYS_INLINE void GCToEEInterface::DiagUpdateGenerationBounds()
+inline void GCToEEInterface::DiagUpdateGenerationBounds()
 {
     assert(g_theGCToCLR != nullptr);
     g_theGCToCLR->DiagUpdateGenerationBounds();
 }
 
-ALWAYS_INLINE void GCToEEInterface::DiagGCEnd(size_t index, int gen, int reason, bool fConcurrent)
+inline void GCToEEInterface::DiagGCEnd(size_t index, int gen, int reason, bool fConcurrent)
 {
     assert(g_theGCToCLR != nullptr);
     g_theGCToCLR->DiagGCEnd(index, gen, reason, fConcurrent);
 }
 
-ALWAYS_INLINE void GCToEEInterface::DiagWalkFReachableObjects(void* gcContext)
+inline void GCToEEInterface::DiagWalkFReachableObjects(void* gcContext)
 {
     assert(g_theGCToCLR != nullptr);
     g_theGCToCLR->DiagWalkFReachableObjects(gcContext);
 }
 
-ALWAYS_INLINE void GCToEEInterface::DiagWalkSurvivors(void* gcContext)
+inline void GCToEEInterface::DiagWalkSurvivors(void* gcContext)
 {
     assert(g_theGCToCLR != nullptr);
     g_theGCToCLR->DiagWalkSurvivors(gcContext);
 }
 
-ALWAYS_INLINE void GCToEEInterface::DiagWalkLOHSurvivors(void* gcContext)
+inline void GCToEEInterface::DiagWalkLOHSurvivors(void* gcContext)
 {
     assert(g_theGCToCLR != nullptr);
     g_theGCToCLR->DiagWalkLOHSurvivors(gcContext);
 }
 
-ALWAYS_INLINE void GCToEEInterface::DiagWalkBGCSurvivors(void* gcContext)
+inline void GCToEEInterface::DiagWalkBGCSurvivors(void* gcContext)
 {
     assert(g_theGCToCLR != nullptr);
     return g_theGCToCLR->DiagWalkBGCSurvivors(gcContext);
 }
 
-ALWAYS_INLINE void GCToEEInterface::StompWriteBarrier(WriteBarrierParameters* args)
+inline void GCToEEInterface::StompWriteBarrier(WriteBarrierParameters* args)
 {
     assert(g_theGCToCLR != nullptr);
     g_theGCToCLR->StompWriteBarrier(args);
 }
 
-ALWAYS_INLINE void GCToEEInterface::EnableFinalization(bool foundFinalizers)
+inline void GCToEEInterface::EnableFinalization(bool foundFinalizers)
 {
     assert(g_theGCToCLR != nullptr);
     g_theGCToCLR->EnableFinalization(foundFinalizers);
 }
 
-ALWAYS_INLINE void GCToEEInterface::HandleFatalError(unsigned int exitCode)
+inline void GCToEEInterface::HandleFatalError(unsigned int exitCode)
 {
     assert(g_theGCToCLR != nullptr);
     g_theGCToCLR->HandleFatalError(exitCode);
 }
 
-ALWAYS_INLINE bool GCToEEInterface::ShouldFinalizeObjectForUnload(AppDomain* pDomain, Object* obj)
+inline bool GCToEEInterface::ShouldFinalizeObjectForUnload(AppDomain* pDomain, Object* obj)
 {
     assert(g_theGCToCLR != nullptr);
     return g_theGCToCLR->ShouldFinalizeObjectForUnload(pDomain, obj);
 }
 
-ALWAYS_INLINE bool GCToEEInterface::ForceFullGCToBeBlocking()
+inline bool GCToEEInterface::ForceFullGCToBeBlocking()
 {
     assert(g_theGCToCLR != nullptr);
     return g_theGCToCLR->ForceFullGCToBeBlocking();
 }
 
-ALWAYS_INLINE bool GCToEEInterface::EagerFinalized(Object* obj)
+inline bool GCToEEInterface::EagerFinalized(Object* obj)
 {
     assert(g_theGCToCLR != nullptr);
     return g_theGCToCLR->EagerFinalized(obj);
 }
 
-ALWAYS_INLINE MethodTable* GCToEEInterface::GetFreeObjectMethodTable()
+inline MethodTable* GCToEEInterface::GetFreeObjectMethodTable()
 {
     assert(g_theGCToCLR != nullptr);
     return g_theGCToCLR->GetFreeObjectMethodTable();
 }
 
-ALWAYS_INLINE bool GCToEEInterface::GetBooleanConfigValue(const char* key, bool* value)
+inline bool GCToEEInterface::GetBooleanConfigValue(const char* key, bool* value)
 {
     assert(g_theGCToCLR != nullptr);
     return g_theGCToCLR->GetBooleanConfigValue(key, value);
 }
 
-ALWAYS_INLINE bool GCToEEInterface::GetIntConfigValue(const char* key, int64_t* value)
+inline bool GCToEEInterface::GetIntConfigValue(const char* key, int64_t* value)
 {
     assert(g_theGCToCLR != nullptr);
     return g_theGCToCLR->GetIntConfigValue(key, value);
 }
 
-ALWAYS_INLINE bool GCToEEInterface::GetStringConfigValue(const char* key, const char** value)
+inline bool GCToEEInterface::GetStringConfigValue(const char* key, const char** value)
 {
     assert(g_theGCToCLR != nullptr);
     return g_theGCToCLR->GetStringConfigValue(key, value);
 }
 
-ALWAYS_INLINE void GCToEEInterface::FreeStringConfigValue(const char* value)
+inline void GCToEEInterface::FreeStringConfigValue(const char* value)
 {
     assert(g_theGCToCLR != nullptr);
     g_theGCToCLR->FreeStringConfigValue(value);
 }
 
-#undef ALWAYS_INLINE
-
-} // anonymous namespace
-
 #endif // __GCTOENV_EE_STANDALONE_INL__
diff --git a/src/gc/gcenv.inl b/src/gc/gcenv.inl
new file mode 100644 (file)
index 0000000..f3d7d32
--- /dev/null
@@ -0,0 +1,9 @@
+// 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.
+
+#ifdef _WIN32
+#include "gcenv.windows.inl"
+#else
+#include "gcenv.unix.inl"
+#endif // _WIN32
index ec7c457..5bec721 100644 (file)
@@ -154,7 +154,10 @@ struct segment_info
 };
 
 #ifdef PROFILING_SUPPORTED
+#ifndef BUILD_AS_STANDALONE
+// [LOCALGC TODO] Enable profiling (GitHub #11515)
 #define GC_PROFILING       //Turn on profiling
+#endif // BUILD_AS_STANDALONE
 #endif // PROFILING_SUPPORTED
 
 #define LARGE_OBJECT_SIZE ((size_t)(85000))
index f6defba..c9c6fa3 100644 (file)
@@ -1016,12 +1016,6 @@ enum interesting_data_point
 //class definition of the internal class
 class gc_heap
 {
-    friend struct ::_DacGlobals;
-#ifdef DACCESS_COMPILE
-    friend class ::ClrDataAccess;
-    friend class ::DacHeapWalker;
-#endif //DACCESS_COMPILE
-
     friend class GCHeap;
 #ifdef FEATURE_PREMORTEM_FINALIZATION
     friend class CFinalize;
@@ -3627,7 +3621,7 @@ protected:
 }; // class gc_heap
 
 #define ASSERT_OFFSETS_MATCH(field) \
-  static_assert_no_msg(offsetof(dac_gc_heap, field) == offsetof(gc_heap, field))
+  static_assert(offsetof(dac_gc_heap, field) == offsetof(gc_heap, field), #field " offset mismatch")
 
 #ifdef MULTIPLE_HEAPS
 ASSERT_OFFSETS_MATCH(alloc_allocated);
index c7060f3..b183a78 100644 (file)
@@ -33,8 +33,6 @@ struct DhContext
 
 class GCScan
 {
-    friend struct ::_DacGlobals;
-
   public:
 
     static void GcScanSizedRefs(promote_func* fn, int condemned, int max_gen, ScanContext* sc);
index 6f89cab..db67aa3 100644 (file)
@@ -16,6 +16,7 @@
 #include "softwarewritewatch.h"
 #include "handletable.h"
 #include "handletable.inl"
+#include "gcenv.inl"
 
 #define SERVER_GC 1
 
index 07a4e20..3357556 100644 (file)
@@ -14,6 +14,7 @@
 #include "softwarewritewatch.h"
 #include "handletable.h"
 #include "handletable.inl"
+#include "gcenv.inl"
 
 #ifdef SERVER_GC
 #undef SERVER_GC
index 4548237..2a69afc 100644 (file)
@@ -14,6 +14,7 @@
 #include "common.h"
 
 #include "gcenv.h"
+#include "gcenv.inl"
 #include "gc.h"
 
 #ifndef FEATURE_REDHAWK
index 6570503..24db07d 100644 (file)
 
 #include "gchandletableimpl.h"
 
+#ifndef BUILD_AS_STANDALONE
 #ifdef FEATURE_COMINTEROP
 #include "comcallablewrapper.h"
 #endif // FEATURE_COMINTEROP
 #ifndef FEATURE_REDHAWK
 #include "nativeoverlapped.h"
 #endif // FEATURE_REDHAWK
+#endif // BUILD_AS_STANDALONE
 
 HandleTableMap g_HandleTableMap;
 
@@ -137,7 +139,7 @@ void CALLBACK TraceDependentHandle(_UNCHECKED_OBJECTREF *pObjRef, uintptr_t *pEx
     // At this point, it's possible that either or both of the primary and secondary
     // objects are NULL.  However, if the secondary object is non-NULL, then the primary
     // object should also be non-NULL.
-    _ASSERTE(*pExtraInfo == NULL || *pObjRef != NULL);
+    _ASSERTE(*pExtraInfo == 0 || *pObjRef != NULL);
 
     struct DIAG_DEPSCANINFO *pInfo = (struct DIAG_DEPSCANINFO*)lp2;
 
index 4ed7f2d..a6d2259 100644 (file)
  */
 #include "handletable.h"
 
-#ifdef FEATURE_COMINTEROP
-#include <weakreference.h>
-#endif // FEATURE_COMINTEROP
-
 typedef DPTR(struct HandleTableMap) PTR_HandleTableMap;
 typedef DPTR(struct HandleTableBucket) PTR_HandleTableBucket;
 typedef DPTR(PTR_HandleTableBucket) PTR_PTR_HandleTableBucket;
index 43cb238..62eec66 100644 (file)
@@ -125,7 +125,7 @@ int __cdecl main(int argc, char* argv[])
     //
     static MethodTable freeObjectMT;
     freeObjectMT.InitializeFreeObject();
-    g_pFreeObjectMethodTable = &freeObjectMT;
+    g_gc_pFreeObjectMethodTable = &freeObjectMT;
 
     //
     // Initialize GC heap
index c0265d5..de1a2ad 100644 (file)
@@ -320,15 +320,3 @@ MethodTable* GCToEEInterface::GetFreeObjectMethodTable()
 {
     return g_pFreeObjectMethodTable;
 }
-
-bool IsGCSpecialThread()
-{
-    // TODO: Implement for background GC
-    return false;
-}
-
-bool IsGCThread()
-{
-    return false;
-}
-
index 74ae70b..b118232 100644 (file)
@@ -54,4 +54,4 @@ check_cxx_source_runs("
 
 check_library_exists(c sched_getaffinity "" HAVE_SCHED_GETAFFINITY)
 
-configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)
+configure_file(${CMAKE_CURRENT_LIST_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)
index 7c665f4..694b9ba 100644 (file)
 #include <errno.h>
 #include "config.h"
 
-#ifndef __out_z
-#define __out_z
-#endif // __out_z
-
 #include "gcenv.structs.h"
 #include "gcenv.base.h"
 #include "gcenv.os.h"
index b21f13e..c176c4a 100644 (file)
@@ -6,28 +6,10 @@
 #include <cstddef>
 #include <cassert>
 #include <memory>
-
-// The CoreCLR PAL defines _POSIX_C_SOURCE to avoid calling non-posix pthread functions.
-// This isn't something we want, because we're totally fine using non-posix functions.
-#if defined(__APPLE__)
- #define _DARWIN_C_SOURCE
-#endif // definfed(__APPLE__)
-
 #include <pthread.h>
 #include <signal.h>
 #include "config.h"
 
-// clang typedefs uint64_t to be unsigned long long, which clashes with
-// PAL/MSVC's unsigned long, causing linker errors. This ugly hack
-// will go away once the GC doesn't depend on PAL headers.
-typedef unsigned long uint64_t_hack;
-#define uint64_t uint64_t_hack
-static_assert(sizeof(uint64_t) == 8, "unsigned long isn't 8 bytes");
-
-#ifndef __out_z
-#define __out_z
-#endif // __out_z
-
 #include "gcenv.structs.h"
 #include "gcenv.base.h"
 #include "gcenv.os.h"
index e9f09ff..6562de7 100644 (file)
@@ -200,7 +200,6 @@ set(VM_SOURCES_WKS
     gccover.cpp
     gcenv.ee.static.cpp
     gcenv.ee.common.cpp
-    gcenv.os.cpp
     gchelpers.cpp
     genmeth.cpp
     hosting.cpp
index ff0942a..9779813 100644 (file)
@@ -2509,6 +2509,7 @@ void LoadGarbageCollector()
 
 #endif // FEATURE_STANDALONE_GC
 
+#ifndef FEATURE_STANDALONE_GC_ONLY
 void LoadStaticGarbageCollector()
 {
     CONTRACTL{
@@ -2531,6 +2532,7 @@ void LoadStaticGarbageCollector()
     g_pGCHandleManager = pGcHandleManager;
     g_gcDacGlobals = &g_gc_dac_vars;
 }
+#endif // FEATURE_STANDALONE_GC_ONLY
 
 
 void InitializeGarbageCollector()
@@ -2567,7 +2569,9 @@ void InitializeGarbageCollector()
     else
 #endif // FEATURE_STANDALONE_GC
     {
+#ifndef FEATURE_STANDALONE_GC_ONLY
         LoadStaticGarbageCollector();
+#endif // FEATURE_STANDALONE_GC_ONLY
     }
 
     // Apparently the Windows linker removes global variables if they are never
index 8b55f06..3958bdf 100644 (file)
@@ -986,7 +986,7 @@ HRESULT AllowObjectInspection()
 
 #endif // PROFILING_SUPPORTED
 
-#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE)
+#if defined(PROFILING_SUPPORTED) || defined(FEATURE_EVENT_TRACE)
 
 //---------------------------------------------------------------------------------------
 //