summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Gillespie <segilles@microsoft.com>2017-08-22 10:20:36 -0700
committerGitHub <noreply@github.com>2017-08-22 10:20:36 -0700
commit8acf6c9f7e33b1bfe77205cd2e61f2c60e8c00ce (patch)
tree5f7e55f04b5182a6ef1bd537ef76accd5a494782
parent2766385624a9c5b73d32bed85519c044447701ff (diff)
downloadcoreclr-8acf6c9f7e33b1bfe77205cd2e61f2c60e8c00ce.tar.gz
coreclr-8acf6c9f7e33b1bfe77205cd2e61f2c60e8c00ce.tar.bz2
coreclr-8acf6c9f7e33b1bfe77205cd2e61f2c60e8c00ce.zip
[Local GC] Enable building the GC as a shared library (#13137)
* [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...)
-rw-r--r--CMakeLists.txt19
-rw-r--r--clrdefinitions.cmake4
-rw-r--r--clrfeatures.cmake11
-rw-r--r--functions.cmake27
-rw-r--r--src/CMakeLists.txt3
-rw-r--r--src/dlls/mscoree/coreclr/CMakeLists.txt11
-rw-r--r--src/dlls/mscoree/mscorwks_unixexports.src2
-rw-r--r--src/gc/CMakeLists.txt58
-rw-r--r--src/gc/WarningControl.h0
-rw-r--r--src/gc/env/gcenv.base.h336
-rw-r--r--src/gc/env/gcenv.h72
-rw-r--r--src/gc/env/gcenv.object.h30
-rw-r--r--src/gc/gc.h5
-rw-r--r--src/gc/gcenv.ee.standalone.inl114
-rw-r--r--src/gc/gcenv.inl9
-rw-r--r--src/gc/gcinterface.h3
-rw-r--r--src/gc/gcpriv.h8
-rw-r--r--src/gc/gcscan.h2
-rw-r--r--src/gc/gcsvr.cpp1
-rw-r--r--src/gc/gcwks.cpp1
-rw-r--r--src/gc/handletablecore.cpp1
-rw-r--r--src/gc/objecthandle.cpp4
-rw-r--r--src/gc/objecthandle.h4
-rw-r--r--src/gc/sample/GCSample.cpp2
-rw-r--r--src/gc/sample/gcenv.ee.cpp12
-rw-r--r--src/gc/unix/configure.cmake2
-rw-r--r--src/gc/unix/events.cpp4
-rw-r--r--src/gc/unix/gcenv.unix.cpp18
-rw-r--r--src/vm/CMakeLists.txt1
-rw-r--r--src/vm/ceemain.cpp4
-rw-r--r--src/vm/proftoeeinterfaceimpl.cpp2
31 files changed, 447 insertions, 323 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 38461acaee..9e1d16dffb 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -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}")
diff --git a/clrdefinitions.cmake b/clrdefinitions.cmake
index 1848e3b550..4f6b0414bb 100644
--- a/clrdefinitions.cmake
+++ b/clrdefinitions.cmake
@@ -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)
diff --git a/clrfeatures.cmake b/clrfeatures.cmake
index f047c91f7a..fde04d2af2 100644
--- a/clrfeatures.cmake
+++ b/clrfeatures.cmake
@@ -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)
+
diff --git a/functions.cmake b/functions.cmake
index cf4d08faaf..3ed9536621 100644
--- a/functions.cmake
+++ b/functions.cmake
@@ -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()
+
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index ba17dc05ce..900ba96f53 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -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)
diff --git a/src/dlls/mscoree/coreclr/CMakeLists.txt b/src/dlls/mscoree/coreclr/CMakeLists.txt
index 81aaad45f0..8796cc16a5 100644
--- a/src/dlls/mscoree/coreclr/CMakeLists.txt
+++ b/src/dlls/mscoree/coreclr/CMakeLists.txt
@@ -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
diff --git a/src/dlls/mscoree/mscorwks_unixexports.src b/src/dlls/mscoree/mscorwks_unixexports.src
index e9a994c904..1076d175c4 100644
--- a/src/dlls/mscoree/mscorwks_unixexports.src
+++ b/src/dlls/mscoree/mscorwks_unixexports.src
@@ -112,5 +112,3 @@ SetThreadAffinityMask
GetThreadGroupAffinity
GetCurrentProcessorNumberEx
-; Function for initializing a standalone GC
-InitializeGarbageCollector
diff --git a/src/gc/CMakeLists.txt b/src/gc/CMakeLists.txt
index 4de3f4e412..21eb66070a 100644
--- a/src/gc/CMakeLists.txt
+++ b/src/gc/CMakeLists.txt
@@ -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
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/gc/WarningControl.h
diff --git a/src/gc/env/gcenv.base.h b/src/gc/env/gcenv.base.h
index 1e9406c296..98a4235301 100644
--- a/src/gc/env/gcenv.base.h
+++ b/src/gc/env/gcenv.base.h
@@ -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
@@ -22,7 +23,11 @@
#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
index 0000000000..c69f5f92fd
--- /dev/null
+++ b/src/gc/env/gcenv.h
@@ -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
diff --git a/src/gc/env/gcenv.object.h b/src/gc/env/gcenv.object.h
index db8995a118..4261c1a148 100644
--- a/src/gc/env/gcenv.object.h
+++ b/src/gc/env/gcenv.object.h
@@ -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
diff --git a/src/gc/gc.h b/src/gc/gc.h
index 4e722c4304..e16fccb91e 100644
--- a/src/gc/gc.h
+++ b/src/gc/gc.h
@@ -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() {}
diff --git a/src/gc/gcenv.ee.standalone.inl b/src/gc/gcenv.ee.standalone.inl
index c66acf0a61..0dcf05da4d 100644
--- a/src/gc/gcenv.ee.standalone.inl
+++ b/src/gc/gcenv.ee.standalone.inl
@@ -6,280 +6,244 @@
#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
index 0000000000..f3d7d32922
--- /dev/null
+++ b/src/gc/gcenv.inl
@@ -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
diff --git a/src/gc/gcinterface.h b/src/gc/gcinterface.h
index ec7c457a6f..5bec7212e8 100644
--- a/src/gc/gcinterface.h
+++ b/src/gc/gcinterface.h
@@ -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))
diff --git a/src/gc/gcpriv.h b/src/gc/gcpriv.h
index f6defba116..c9c6fa32f9 100644
--- a/src/gc/gcpriv.h
+++ b/src/gc/gcpriv.h
@@ -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);
diff --git a/src/gc/gcscan.h b/src/gc/gcscan.h
index c7060f3f51..b183a78d44 100644
--- a/src/gc/gcscan.h
+++ b/src/gc/gcscan.h
@@ -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);
diff --git a/src/gc/gcsvr.cpp b/src/gc/gcsvr.cpp
index 6f89cab132..db67aa3eef 100644
--- a/src/gc/gcsvr.cpp
+++ b/src/gc/gcsvr.cpp
@@ -16,6 +16,7 @@
#include "softwarewritewatch.h"
#include "handletable.h"
#include "handletable.inl"
+#include "gcenv.inl"
#define SERVER_GC 1
diff --git a/src/gc/gcwks.cpp b/src/gc/gcwks.cpp
index 07a4e20199..335755608d 100644
--- a/src/gc/gcwks.cpp
+++ b/src/gc/gcwks.cpp
@@ -14,6 +14,7 @@
#include "softwarewritewatch.h"
#include "handletable.h"
#include "handletable.inl"
+#include "gcenv.inl"
#ifdef SERVER_GC
#undef SERVER_GC
diff --git a/src/gc/handletablecore.cpp b/src/gc/handletablecore.cpp
index 4548237eda..2a69afc01d 100644
--- a/src/gc/handletablecore.cpp
+++ b/src/gc/handletablecore.cpp
@@ -14,6 +14,7 @@
#include "common.h"
#include "gcenv.h"
+#include "gcenv.inl"
#include "gc.h"
#ifndef FEATURE_REDHAWK
diff --git a/src/gc/objecthandle.cpp b/src/gc/objecthandle.cpp
index 657050398b..24db07dfb1 100644
--- a/src/gc/objecthandle.cpp
+++ b/src/gc/objecthandle.cpp
@@ -21,12 +21,14 @@
#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;
diff --git a/src/gc/objecthandle.h b/src/gc/objecthandle.h
index 4ed7f2d1a4..a6d2259009 100644
--- a/src/gc/objecthandle.h
+++ b/src/gc/objecthandle.h
@@ -17,10 +17,6 @@
*/
#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;
diff --git a/src/gc/sample/GCSample.cpp b/src/gc/sample/GCSample.cpp
index 43cb23878e..62eec6698f 100644
--- a/src/gc/sample/GCSample.cpp
+++ b/src/gc/sample/GCSample.cpp
@@ -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
diff --git a/src/gc/sample/gcenv.ee.cpp b/src/gc/sample/gcenv.ee.cpp
index c0265d5fcf..de1a2ad5ee 100644
--- a/src/gc/sample/gcenv.ee.cpp
+++ b/src/gc/sample/gcenv.ee.cpp
@@ -320,15 +320,3 @@ MethodTable* GCToEEInterface::GetFreeObjectMethodTable()
{
return g_pFreeObjectMethodTable;
}
-
-bool IsGCSpecialThread()
-{
- // TODO: Implement for background GC
- return false;
-}
-
-bool IsGCThread()
-{
- return false;
-}
-
diff --git a/src/gc/unix/configure.cmake b/src/gc/unix/configure.cmake
index 74ae70b1a4..b118232b35 100644
--- a/src/gc/unix/configure.cmake
+++ b/src/gc/unix/configure.cmake
@@ -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)
diff --git a/src/gc/unix/events.cpp b/src/gc/unix/events.cpp
index 7c665f4aaa..694b9ba17c 100644
--- a/src/gc/unix/events.cpp
+++ b/src/gc/unix/events.cpp
@@ -11,10 +11,6 @@
#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"
diff --git a/src/gc/unix/gcenv.unix.cpp b/src/gc/unix/gcenv.unix.cpp
index b21f13eb55..c176c4a350 100644
--- a/src/gc/unix/gcenv.unix.cpp
+++ b/src/gc/unix/gcenv.unix.cpp
@@ -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"
diff --git a/src/vm/CMakeLists.txt b/src/vm/CMakeLists.txt
index e9f09ff65a..6562de784a 100644
--- a/src/vm/CMakeLists.txt
+++ b/src/vm/CMakeLists.txt
@@ -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
diff --git a/src/vm/ceemain.cpp b/src/vm/ceemain.cpp
index ff0942a104..9779813a3e 100644
--- a/src/vm/ceemain.cpp
+++ b/src/vm/ceemain.cpp
@@ -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
diff --git a/src/vm/proftoeeinterfaceimpl.cpp b/src/vm/proftoeeinterfaceimpl.cpp
index 8b55f06bd8..3958bdf354 100644
--- a/src/vm/proftoeeinterfaceimpl.cpp
+++ b/src/vm/proftoeeinterfaceimpl.cpp
@@ -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)
//---------------------------------------------------------------------------------------
//