summaryrefslogtreecommitdiff
path: root/src/gc/env/gcenv.base.h
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 /src/gc/env/gcenv.base.h
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...)
Diffstat (limited to 'src/gc/env/gcenv.base.h')
-rw-r--r--src/gc/env/gcenv.base.h336
1 files changed, 195 insertions, 141 deletions
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");
+ }
};