From 011ad7674302e2a070d8cd14bb09dac122cdac92 Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Thu, 15 Oct 2015 07:14:05 -0700 Subject: [PATCH] Cleanup GC-EE Interface - Add proper abstractions for threading methods to GCToEEInterface - Split sample gcenv into multiple files to avoid redundant content - Add handle table methods needed by .NET Native WinRT implementation Part of dotnet/coreclr#1550 Commit migrated from https://github.com/dotnet/coreclr/commit/38034a26ff4e40e98d1af32abe5baef2c3eeea52 --- src/coreclr/src/gc/env/{gcenv.h => gcenv.base.h} | 461 +++------------------ src/coreclr/src/gc/env/gcenv.object.h | 149 +++++++ src/coreclr/src/gc/env/gcenv.sync.h | 158 +++++++ src/coreclr/src/gc/env/gcenv.unix.cpp | 87 +--- src/coreclr/src/gc/env/gcenv.windows.cpp | 141 ++----- src/coreclr/src/gc/gc.cpp | 47 +-- src/coreclr/src/gc/gc.h | 8 +- src/coreclr/src/gc/gcee.cpp | 60 ++- src/coreclr/src/gc/gcimpl.h | 15 +- src/coreclr/src/gc/gcscan.cpp | 13 +- src/coreclr/src/gc/handletable.cpp | 24 ++ src/coreclr/src/gc/handletable.h | 1 + src/coreclr/src/gc/objecthandle.cpp | 109 +++-- src/coreclr/src/gc/objecthandle.h | 8 +- src/coreclr/src/gc/sample/GCSample.cpp | 2 +- src/coreclr/src/gc/sample/GCSample.vcxproj | 3 +- src/coreclr/src/gc/sample/GCSample.vcxproj.filters | 15 +- src/coreclr/src/gc/sample/gcenv.cpp | 155 +++++++ src/coreclr/src/gc/sample/gcenv.h | 128 ++++++ src/coreclr/src/vm/gcenv.cpp | 45 ++ src/coreclr/src/vm/gcenv.h | 28 ++ src/coreclr/src/vm/jitinterface.cpp | 2 +- 22 files changed, 976 insertions(+), 683 deletions(-) rename src/coreclr/src/gc/env/{gcenv.h => gcenv.base.h} (71%) create mode 100644 src/coreclr/src/gc/env/gcenv.object.h create mode 100644 src/coreclr/src/gc/env/gcenv.sync.h create mode 100644 src/coreclr/src/gc/sample/gcenv.cpp create mode 100644 src/coreclr/src/gc/sample/gcenv.h diff --git a/src/coreclr/src/gc/env/gcenv.h b/src/coreclr/src/gc/env/gcenv.base.h similarity index 71% rename from src/coreclr/src/gc/env/gcenv.h rename to src/coreclr/src/gc/env/gcenv.base.h index 6a9c421..74288a2 100644 --- a/src/coreclr/src/gc/env/gcenv.h +++ b/src/coreclr/src/gc/env/gcenv.base.h @@ -10,6 +10,8 @@ #define FEATURE_REDHAWK 1 #define FEATURE_CONSERVATIVE_GC 1 +#define GCENV_INCLUDED + #ifndef _MSC_VER #define __stdcall #define __forceinline inline @@ -508,137 +510,10 @@ void FastInterlockAnd(uint32_t volatile *p, uint32_t msk); #define CALLER_LIMITS_SPINNING 0 bool __SwitchToThread (uint32_t dwSleepMSec, uint32_t dwSwitchCount); -//------------------------------------------------------------------------------------------------- -// -// Low-level types describing GC object layouts. -// - -// Bits stolen from the sync block index that the GC/HandleTable knows about (currently these are at the same -// positions as the mainline runtime but we can change this below when it becomes apparent how Redhawk will -// handle sync blocks). -#define BIT_SBLK_GC_RESERVE 0x20000000 -#define BIT_SBLK_FINALIZER_RUN 0x40000000 - -// The sync block index header (small structure that immediately precedes every object in the GC heap). Only -// the GC uses this so far, and only to store a couple of bits of information. -class ObjHeader -{ -private: -#if defined(_WIN64) - uint32_t m_uAlignpad; -#endif // _WIN64 - uint32_t m_uSyncBlockValue; - -public: - uint32_t GetBits() { return m_uSyncBlockValue; } - void SetBit(uint32_t uBit) { FastInterlockOr(&m_uSyncBlockValue, uBit); } - void ClrBit(uint32_t uBit) { FastInterlockAnd(&m_uSyncBlockValue, ~uBit); } - void SetGCBit() { m_uSyncBlockValue |= BIT_SBLK_GC_RESERVE; } - void ClrGCBit() { m_uSyncBlockValue &= ~BIT_SBLK_GC_RESERVE; } -}; - -#define MTFlag_ContainsPointers 1 -#define MTFlag_HasFinalizer 2 - -class MethodTable -{ -public: - uint32_t m_baseSize; - uint16_t m_componentSize; - uint16_t m_flags; - -public: - void InitializeFreeObject() - { - m_baseSize = 3 * sizeof(void *); - m_componentSize = 1; - m_flags = 0; - } - - uint32_t GetBaseSize() - { - return m_baseSize; - } - - uint16_t RawGetComponentSize() - { - return m_componentSize; - } - - bool ContainsPointers() - { - return (m_flags & MTFlag_ContainsPointers) != 0; - } - - bool ContainsPointersOrCollectible() - { - return ContainsPointers(); - } - - bool HasComponentSize() - { - return m_componentSize != 0; - } - - bool HasFinalizer() - { - return (m_flags & MTFlag_HasFinalizer) != 0; - } - - bool HasCriticalFinalizer() - { - return false; - } - - bool SanityCheck() - { - return true; - } -}; -#define EEType MethodTable - -class Object -{ - MethodTable * m_pMethTab; - -public: - ObjHeader * GetHeader() - { - return ((ObjHeader *)this) - 1; - } - - MethodTable * RawGetMethodTable() const - { - return m_pMethTab; - } - - void RawSetMethodTable(MethodTable * pMT) - { - m_pMethTab = pMT; - } - - void SetMethodTable(MethodTable * pMT) - { - m_pMethTab = pMT; - } -}; -#define MIN_OBJECT_SIZE (2*sizeof(BYTE*) + sizeof(ObjHeader)) - -class ArrayBase : public Object -{ - DWORD m_dwLength; - -public: - DWORD GetNumComponents() - { - return m_dwLength; - } - - static SIZE_T GetOffsetOfNumComponents() - { - return offsetof(ArrayBase, m_dwLength); - } -}; +class ObjHeader; +class MethodTable; +class Object; +class ArrayBase; // Various types used to refer to object references or handles. This will get more complex if we decide // Redhawk wants to wrap object references in the debug build. @@ -763,62 +638,10 @@ ClrVirtualProtect( // struct alloc_context; - -class Thread -{ - uint32_t m_fPreemptiveGCDisabled; - uintptr_t m_alloc_context[16]; // Reserve enough space to fix allocation context - - friend class ThreadStore; - Thread * m_pNext; - -public: - Thread() - { - } - - bool PreemptiveGCDisabled() - { - return !!m_fPreemptiveGCDisabled; - } - - void EnablePreemptiveGC() - { - m_fPreemptiveGCDisabled = false; - } - - void DisablePreemptiveGC() - { - m_fPreemptiveGCDisabled = true; - } - - alloc_context* GetAllocContext() - { - return (alloc_context *)&m_alloc_context; - } - - void SetGCSpecial(bool fGCSpecial) - { - } - - bool CatchAtSafePoint() - { - // This is only called by the GC on a background GC worker thread that's explicitly interested in letting - // a foreground GC proceed at that point. So it's always safe to return true. - return true; - } -}; +class Thread; Thread * GetThread(); -class ThreadStore -{ -public: - static Thread * GetThreadList(Thread * pThread); - - static void AttachCurrentThread(bool fAcquireThreadStoreLock); -}; - struct ScanContext; typedef void promote_func(PTR_PTR_Object, ScanContext*, unsigned); @@ -864,21 +687,40 @@ public: // post-gc callback. static void GcDone(int condemned); + // Promote refcounted handle callback + static bool RefCountedHandleCallbacks(Object * pObject); + // Sync block cache management static void SyncBlockCacheWeakPtrScan(HANDLESCANPROC scanProc, LPARAM lp1, LPARAM lp2) { } static void SyncBlockCacheDemote(int max_gen) { } static void SyncBlockCachePromotionsGranted(int max_gen) { } + + // Thread functions + static bool IsPreemptiveGCDisabled(Thread * pThread); + static void EnablePreemptiveGC(Thread * pThread); + static void DisablePreemptiveGC(Thread * pThread); + static void SetGCSpecial(Thread * pThread); + static alloc_context * GetAllocContext(Thread * pThread); + static bool CatchAtSafePoint(Thread * pThread); + + // ThreadStore functions + static void AttachCurrentThread(); // does not acquire thread store lock + static Thread * GetThreadList(Thread * pThread); }; class FinalizerThread { public: + static bool Initialize(); static void EnableFinalization(); - static bool HaveExtraWorkForFinalizer() - { - return false; - } + static bool HaveExtraWorkForFinalizer(); + + static bool IsCurrentThreadFinalizer(); + static void Wait(DWORD timeout, bool allowReentrantWait = false); + static bool WatchDog(); + static void SignalFinalizationDone(bool fFinalizer); + static void SetFinalizerThread(Thread * pThread); }; typedef uint32_t (__stdcall *BackgroundCallback)(void* pCallbackContext); @@ -1014,65 +856,6 @@ inline void StompWriteBarrierResize(BOOL bReqUpperBoundsCheck) { } -// ----------------------------------------------------------------------------------------------------------- -// Config file enumulation -// - -class EEConfig -{ -public: - enum HeapVerifyFlags { - HEAPVERIFY_NONE = 0, - HEAPVERIFY_GC = 1, // Verify the heap at beginning and end of GC - HEAPVERIFY_BARRIERCHECK = 2, // Verify the brick table - HEAPVERIFY_SYNCBLK = 4, // Verify sync block scanning - - // the following options can be used to mitigate some of the overhead introduced - // by heap verification. some options might cause heap verifiction to be less - // effective depending on the scenario. - - HEAPVERIFY_NO_RANGE_CHECKS = 0x10, // Excludes checking if an OBJECTREF is within the bounds of the managed heap - HEAPVERIFY_NO_MEM_FILL = 0x20, // Excludes filling unused segment portions with fill pattern - HEAPVERIFY_POST_GC_ONLY = 0x40, // Performs heap verification post-GCs only (instead of before and after each GC) - HEAPVERIFY_DEEP_ON_COMPACT = 0x80 // Performs deep object verfication only on compacting GCs. - }; - - enum GCStressFlags { - GCSTRESS_NONE = 0, - GCSTRESS_ALLOC = 1, // GC on all allocs and 'easy' places - GCSTRESS_TRANSITION = 2, // GC on transitions to preemtive GC - GCSTRESS_INSTR_JIT = 4, // GC on every allowable JITed instr - GCSTRESS_INSTR_NGEN = 8, // GC on every allowable NGEN instr - GCSTRESS_UNIQUE = 16, // GC only on a unique stack trace - }; - - int GetHeapVerifyLevel() { return 0; } - bool IsHeapVerifyEnabled() { return GetHeapVerifyLevel() != 0; } - - GCStressFlags GetGCStressLevel() const { return GCSTRESS_NONE; } - bool IsGCStressMix() const { return false; } - - int GetGCtraceStart() const { return 0; } - int GetGCtraceEnd () const { return 0; }//1000000000; } - int GetGCtraceFac () const { return 0; } - int GetGCprnLvl () const { return 0; } - bool IsGCBreakOnOOMEnabled() const { return false; } - int GetGCgen0size () const { return 0; } - int GetSegmentSize () const { return 0; } - int GetGCconcurrent() const { return 1; } - int GetGCLatencyMode() const { return 1; } - int GetGCForceCompact() const { return 0; } - int GetGCRetainVM () const { return 0; } - int GetGCTrimCommit() const { return 0; } - int GetGCLOHCompactionMode() const { return 0; } - - bool GetGCAllowVeryLargeObjects () const { return false; } - - bool GetGCConservative() const { return true; } -}; - -extern EEConfig * g_pConfig; - class CLRConfig { public: @@ -1124,163 +907,6 @@ public: } }; - -// ----------------------------------------------------------------------------------------------------------- -// -// Helper classes expected by the GC -// - -class EEThreadId -{ -public: - EEThreadId(UINT32 uiId) : m_uiId(uiId) {} - bool IsSameThread() - { - return m_uiId == GetCurrentThreadId(); - } - -private: - UINT32 m_uiId; -}; - -#define CRST_REENTRANCY 0 -#define CRST_UNSAFE_SAMELEVEL 0 -#define CRST_UNSAFE_ANYMODE 0 -#define CRST_DEBUGGER_THREAD 0 -#define CRST_DEFAULT 0 - -#define CrstHandleTable 0 - -typedef int CrstFlags; -typedef int CrstType; - -class CrstStatic -{ - CRITICAL_SECTION m_cs; -#ifdef _DEBUG - UINT32 m_holderThreadId; -#endif - -public: - bool InitNoThrow(CrstType eType, CrstFlags eFlags = CRST_DEFAULT) - { - UnsafeInitializeCriticalSection(&m_cs); - return true; - } - - void Destroy() - { - UnsafeDeleteCriticalSection(&m_cs); - } - - void Enter() - { - UnsafeEEEnterCriticalSection(&m_cs); -#ifdef _DEBUG - m_holderThreadId = GetCurrentThreadId(); -#endif - } - - void Leave() - { -#ifdef _DEBUG - m_holderThreadId = 0; -#endif - UnsafeEELeaveCriticalSection(&m_cs); - } - -#ifdef _DEBUG - EEThreadId GetHolderThreadId() - { - return m_holderThreadId; - } - - bool OwnedByCurrentThread() - { - return GetHolderThreadId().IsSameThread(); - } -#endif -}; - -class CLREventStatic -{ -public: - void CreateManualEvent(bool bInitialState); - void CreateAutoEvent(bool bInitialState); - void CreateOSManualEvent(bool bInitialState); - void CreateOSAutoEvent(bool bInitialState); - void CloseEvent(); - bool IsValid() const; - bool Set(); - bool Reset(); - uint32_t Wait(uint32_t dwMilliseconds, bool bAlertable); - -private: - HANDLE m_hEvent; - bool m_fInitialized; -}; - -class CrstHolder -{ - CrstStatic * m_pLock; - -public: - CrstHolder(CrstStatic * pLock) - : m_pLock(pLock) - { - m_pLock->Enter(); - } - - ~CrstHolder() - { - m_pLock->Leave(); - } -}; - -class CrstHolderWithState -{ - CrstStatic * m_pLock; - bool m_fAcquired; - -public: - CrstHolderWithState(CrstStatic * pLock, bool fAcquire = true) - : m_pLock(pLock), m_fAcquired(fAcquire) - { - if (fAcquire) - m_pLock->Enter(); - } - - ~CrstHolderWithState() - { - if (m_fAcquired) - m_pLock->Leave(); - } - - void Acquire() - { - if (!m_fAcquired) - { - m_pLock->Enter(); - m_fAcquired = true; - } - } - - void Release() - { - if (m_fAcquired) - { - m_pLock->Leave(); - m_fAcquired = false; - } - } - - CrstStatic * GetValue() - { - return m_pLock; - } -}; - - template class NewHolder { @@ -1355,3 +981,30 @@ public: AppDomain *DefaultDomain() { return NULL; } DWORD GetTotalNumSizedRefHandles() { return 0; } }; + +#ifdef STRESS_HEAP +namespace GCStressPolicy +{ + static volatile int32_t s_cGcStressDisables; + + inline bool IsEnabled() { return s_cGcStressDisables == 0; } + inline void GlobalDisable() { FastInterlockIncrement(&s_cGcStressDisables); } + inline void GlobalEnable() { FastInterlockDecrement(&s_cGcStressDisables); } +} + +enum gcs_trigger_points +{ + cfg_any, +}; + +template +class GCStress +{ +public: + static inline bool IsEnabled() + { + return g_pConfig->GetGCStressLevel() != 0; + } +}; +#endif // STRESS_HEAP + diff --git a/src/coreclr/src/gc/env/gcenv.object.h b/src/coreclr/src/gc/env/gcenv.object.h new file mode 100644 index 0000000..327f5e4 --- /dev/null +++ b/src/coreclr/src/gc/env/gcenv.object.h @@ -0,0 +1,149 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +//------------------------------------------------------------------------------------------------- +// +// Low-level types describing GC object layouts. +// + +// Bits stolen from the sync block index that the GC/HandleTable knows about (currently these are at the same +// positions as the mainline runtime but we can change this below when it becomes apparent how Redhawk will +// handle sync blocks). +#define BIT_SBLK_GC_RESERVE 0x20000000 +#define BIT_SBLK_FINALIZER_RUN 0x40000000 + +// The sync block index header (small structure that immediately precedes every object in the GC heap). Only +// the GC uses this so far, and only to store a couple of bits of information. +class ObjHeader +{ +private: +#if defined(_WIN64) + uint32_t m_uAlignpad; +#endif // _WIN64 + uint32_t m_uSyncBlockValue; + +public: + uint32_t GetBits() { return m_uSyncBlockValue; } + void SetBit(uint32_t uBit) { FastInterlockOr(&m_uSyncBlockValue, uBit); } + void ClrBit(uint32_t uBit) { FastInterlockAnd(&m_uSyncBlockValue, ~uBit); } + void SetGCBit() { m_uSyncBlockValue |= BIT_SBLK_GC_RESERVE; } + void ClrGCBit() { m_uSyncBlockValue &= ~BIT_SBLK_GC_RESERVE; } +}; + +#define MTFlag_ContainsPointers 1 +#define MTFlag_HasFinalizer 2 +#define MTFlag_IsArray 4 + +class MethodTable +{ +public: + uint16_t m_componentSize; + uint16_t m_flags; + uint32_t m_baseSize; + + MethodTable * m_pRelatedType; + +public: + void InitializeFreeObject() + { + m_baseSize = 3 * sizeof(void *); + m_componentSize = 1; + m_flags = 0; + } + + uint32_t GetBaseSize() + { + return m_baseSize; + } + + uint16_t RawGetComponentSize() + { + return m_componentSize; + } + + bool ContainsPointers() + { + return (m_flags & MTFlag_ContainsPointers) != 0; + } + + bool ContainsPointersOrCollectible() + { + return ContainsPointers(); + } + + bool HasComponentSize() + { + return m_componentSize != 0; + } + + bool HasFinalizer() + { + return (m_flags & MTFlag_HasFinalizer) != 0; + } + + bool HasCriticalFinalizer() + { + return false; + } + + bool IsArray() + { + return (m_flags & MTFlag_IsArray) != 0; + } + + MethodTable * GetParent() + { + _ASSERTE(!IsArray()); + return m_pRelatedType; + } + + bool SanityCheck() + { + return true; + } +}; + +class Object +{ + MethodTable * m_pMethTab; + +public: + ObjHeader * GetHeader() + { + return ((ObjHeader *)this) - 1; + } + + MethodTable * RawGetMethodTable() const + { + return m_pMethTab; + } + + void RawSetMethodTable(MethodTable * pMT) + { + m_pMethTab = pMT; + } + + void SetMethodTable(MethodTable * pMT) + { + m_pMethTab = pMT; + } +}; +#define MIN_OBJECT_SIZE (2*sizeof(BYTE*) + sizeof(ObjHeader)) + +class ArrayBase : public Object +{ + DWORD m_dwLength; + +public: + DWORD GetNumComponents() + { + return m_dwLength; + } + + static SIZE_T GetOffsetOfNumComponents() + { + return offsetof(ArrayBase, m_dwLength); + } +}; diff --git a/src/coreclr/src/gc/env/gcenv.sync.h b/src/coreclr/src/gc/env/gcenv.sync.h new file mode 100644 index 0000000..e3abacb --- /dev/null +++ b/src/coreclr/src/gc/env/gcenv.sync.h @@ -0,0 +1,158 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +// ----------------------------------------------------------------------------------------------------------- +// +// Helper classes expected by the GC +// +class EEThreadId +{ +public: + EEThreadId(UINT32 uiId) : m_uiId(uiId) {} + bool IsSameThread() + { + return m_uiId == GetCurrentThreadId(); + } + +private: + UINT32 m_uiId; +}; + +#define CRST_REENTRANCY 0 +#define CRST_UNSAFE_SAMELEVEL 0 +#define CRST_UNSAFE_ANYMODE 0 +#define CRST_DEBUGGER_THREAD 0 +#define CRST_DEFAULT 0 + +#define CrstHandleTable 0 + +typedef int CrstFlags; +typedef int CrstType; + +class CrstStatic +{ + CRITICAL_SECTION m_cs; +#ifdef _DEBUG + UINT32 m_holderThreadId; +#endif + +public: + bool InitNoThrow(CrstType eType, CrstFlags eFlags = CRST_DEFAULT) + { + UnsafeInitializeCriticalSection(&m_cs); + return true; + } + + void Destroy() + { + UnsafeDeleteCriticalSection(&m_cs); + } + + void Enter() + { + UnsafeEEEnterCriticalSection(&m_cs); +#ifdef _DEBUG + m_holderThreadId = GetCurrentThreadId(); +#endif + } + + void Leave() + { +#ifdef _DEBUG + m_holderThreadId = 0; +#endif + UnsafeEELeaveCriticalSection(&m_cs); + } + +#ifdef _DEBUG + EEThreadId GetHolderThreadId() + { + return m_holderThreadId; + } + + bool OwnedByCurrentThread() + { + return GetHolderThreadId().IsSameThread(); + } +#endif +}; + +class CrstHolder +{ + CrstStatic * m_pLock; + +public: + CrstHolder(CrstStatic * pLock) + : m_pLock(pLock) + { + m_pLock->Enter(); + } + + ~CrstHolder() + { + m_pLock->Leave(); + } +}; + +class CrstHolderWithState +{ + CrstStatic * m_pLock; + bool m_fAcquired; + +public: + CrstHolderWithState(CrstStatic * pLock, bool fAcquire = true) + : m_pLock(pLock), m_fAcquired(fAcquire) + { + if (fAcquire) + m_pLock->Enter(); + } + + ~CrstHolderWithState() + { + if (m_fAcquired) + m_pLock->Leave(); + } + + void Acquire() + { + if (!m_fAcquired) + { + m_pLock->Enter(); + m_fAcquired = true; + } + } + + void Release() + { + if (m_fAcquired) + { + m_pLock->Leave(); + m_fAcquired = false; + } + } + + CrstStatic * GetValue() + { + return m_pLock; + } +}; + +class CLREventStatic +{ +public: + void CreateManualEvent(bool bInitialState); + void CreateAutoEvent(bool bInitialState); + void CreateOSManualEvent(bool bInitialState); + void CreateOSAutoEvent(bool bInitialState); + void CloseEvent(); + bool IsValid() const; + bool Set(); + bool Reset(); + uint32_t Wait(uint32_t dwMilliseconds, bool bAlertable); + +private: + HANDLE m_hEvent; + bool m_fInitialized; +}; diff --git a/src/coreclr/src/gc/env/gcenv.unix.cpp b/src/coreclr/src/gc/env/gcenv.unix.cpp index d0e6b91..0ababb5 100644 --- a/src/coreclr/src/gc/env/gcenv.unix.cpp +++ b/src/coreclr/src/gc/env/gcenv.unix.cpp @@ -116,52 +116,52 @@ void GetProcessMemoryLoad(LPMEMORYSTATUSEX pMSEX) } } -void CLREventStatic::CreateManualEvent(bool bInitialState) -{ +void CLREventStatic::CreateManualEvent(bool bInitialState) +{ // TODO: Implement m_fInitialized = true; } -void CLREventStatic::CreateAutoEvent(bool bInitialState) -{ +void CLREventStatic::CreateAutoEvent(bool bInitialState) +{ // TODO: Implement m_fInitialized = true; } -void CLREventStatic::CreateOSManualEvent(bool bInitialState) -{ +void CLREventStatic::CreateOSManualEvent(bool bInitialState) +{ CreateManualEvent(bInitialState); } -void CLREventStatic::CreateOSAutoEvent (bool bInitialState) -{ +void CLREventStatic::CreateOSAutoEvent (bool bInitialState) +{ CreateAutoEvent(bInitialState); } -void CLREventStatic::CloseEvent() -{ +void CLREventStatic::CloseEvent() +{ if (m_fInitialized) - { + { // TODO: Implement m_fInitialized = false; } } -bool CLREventStatic::IsValid() const -{ +bool CLREventStatic::IsValid() const +{ return m_fInitialized; } -bool CLREventStatic::Set() -{ +bool CLREventStatic::Set() +{ if (!m_fInitialized) return false; // TODO: Implement return true; } -bool CLREventStatic::Reset() -{ +bool CLREventStatic::Reset() +{ if (!m_fInitialized) return false; // TODO: Implement @@ -314,8 +314,6 @@ ClrVirtualProtect( MethodTable * g_pFreeObjectMethodTable; -EEConfig * g_pConfig; - GCSystemInfo g_SystemInfo; void InitializeSystemInfo() @@ -370,63 +368,12 @@ void DestroyThread(Thread * pThread) // TODO: Implement } -void GCToEEInterface::SuspendEE(GCToEEInterface::SUSPEND_REASON reason) -{ - GCHeap::GetGCHeap()->SetGCInProgress(TRUE); - - // TODO: Implement -} - -void GCToEEInterface::RestartEE(bool bFinishedGC) -{ - // TODO: Implement - - GCHeap::GetGCHeap()->SetGCInProgress(FALSE); -} - -void GCToEEInterface::ScanStackRoots(Thread * pThread, promote_func* fn, ScanContext* sc) -{ - // TODO: Implement - Scan stack roots on given thread -} - -void GCToEEInterface::ScanStaticGCRefsOpportunistically(promote_func* fn, ScanContext* sc) -{ -} - -void GCToEEInterface::GcStartWork(int condemned, int max_gen) -{ -} - -void GCToEEInterface::AfterGcScanRoots(int condemned, int max_gen, ScanContext* sc) -{ -} - -void GCToEEInterface::GcBeforeBGCSweepWork() -{ -} - -void GCToEEInterface::GcDone(int condemned) -{ -} - void FinalizerThread::EnableFinalization() { // Signal to finalizer thread that there are objects to finalize // TODO: Implement for finalization } -bool PalStartBackgroundGCThread(BackgroundCallback callback, void* pCallbackContext) -{ - // TODO: Implement for background GC - return false; -} - -bool IsGCSpecialThread() -{ - // TODO: Implement for background GC - return false; -} - bool PalHasCapability(PalCapability capability) { // TODO: Implement for background GC diff --git a/src/coreclr/src/gc/env/gcenv.windows.cpp b/src/coreclr/src/gc/env/gcenv.windows.cpp index 9d05fcb..aba1a82 100644 --- a/src/coreclr/src/gc/env/gcenv.windows.cpp +++ b/src/coreclr/src/gc/env/gcenv.windows.cpp @@ -102,56 +102,56 @@ void GetProcessMemoryLoad(LPMEMORYSTATUSEX pMSEX) } } -void CLREventStatic::CreateManualEvent(bool bInitialState) -{ - m_hEvent = CreateEventW(NULL, TRUE, bInitialState, NULL); +void CLREventStatic::CreateManualEvent(bool bInitialState) +{ + m_hEvent = CreateEventW(NULL, TRUE, bInitialState, NULL); m_fInitialized = true; } -void CLREventStatic::CreateAutoEvent(bool bInitialState) -{ - m_hEvent = CreateEventW(NULL, FALSE, bInitialState, NULL); +void CLREventStatic::CreateAutoEvent(bool bInitialState) +{ + m_hEvent = CreateEventW(NULL, FALSE, bInitialState, NULL); m_fInitialized = true; } -void CLREventStatic::CreateOSManualEvent(bool bInitialState) -{ - m_hEvent = CreateEventW(NULL, TRUE, bInitialState, NULL); +void CLREventStatic::CreateOSManualEvent(bool bInitialState) +{ + m_hEvent = CreateEventW(NULL, TRUE, bInitialState, NULL); m_fInitialized = true; } -void CLREventStatic::CreateOSAutoEvent (bool bInitialState) -{ - m_hEvent = CreateEventW(NULL, FALSE, bInitialState, NULL); +void CLREventStatic::CreateOSAutoEvent(bool bInitialState) +{ + m_hEvent = CreateEventW(NULL, FALSE, bInitialState, NULL); m_fInitialized = true; } -void CLREventStatic::CloseEvent() -{ +void CLREventStatic::CloseEvent() +{ if (m_fInitialized && m_hEvent != INVALID_HANDLE_VALUE) - { + { CloseHandle(m_hEvent); m_hEvent = INVALID_HANDLE_VALUE; } } -bool CLREventStatic::IsValid() const -{ - return m_fInitialized && m_hEvent != INVALID_HANDLE_VALUE; +bool CLREventStatic::IsValid() const +{ + return m_fInitialized && m_hEvent != INVALID_HANDLE_VALUE; } -bool CLREventStatic::Set() -{ +bool CLREventStatic::Set() +{ if (!m_fInitialized) return false; - return !!SetEvent(m_hEvent); + return !!SetEvent(m_hEvent); } -bool CLREventStatic::Reset() -{ +bool CLREventStatic::Reset() +{ if (!m_fInitialized) return false; - return !!ResetEvent(m_hEvent); + return !!ResetEvent(m_hEvent); } uint32_t CLREventStatic::Wait(uint32_t dwMilliseconds, bool bAlertable) @@ -161,7 +161,7 @@ uint32_t CLREventStatic::Wait(uint32_t dwMilliseconds, bool bAlertable) if (m_fInitialized) { bool disablePreemptive = false; - Thread * pCurThread = GetThread(); + Thread * pCurThread = GetThread(); if (NULL != pCurThread) { @@ -172,7 +172,7 @@ uint32_t CLREventStatic::Wait(uint32_t dwMilliseconds, bool bAlertable) } } - result = WaitForSingleObjectEx(m_hEvent, dwMilliseconds, bAlertable); + result = WaitForSingleObjectEx(m_hEvent, dwMilliseconds, bAlertable); if (disablePreemptive) { @@ -228,8 +228,6 @@ ClrVirtualProtect( MethodTable * g_pFreeObjectMethodTable; -EEConfig * g_pConfig; - GCSystemInfo g_SystemInfo; void InitializeSystemInfo() @@ -246,99 +244,14 @@ int32_t g_TrapReturningThreads; bool g_fFinalizerRunOnShutDown; -__declspec(thread) Thread * pCurrentThread; - -Thread * GetThread() -{ - return pCurrentThread; -} - -Thread * g_pThreadList = NULL; - -Thread * ThreadStore::GetThreadList(Thread * pThread) -{ - if (pThread == NULL) - return g_pThreadList; - - return pThread->m_pNext; -} - -void ThreadStore::AttachCurrentThread(bool fAcquireThreadStoreLock) -{ - // TODO: Locks - - Thread * pThread = new Thread(); - pThread->GetAllocContext()->init(); - pCurrentThread = pThread; - - pThread->m_pNext = g_pThreadList; - g_pThreadList = pThread; -} - void DestroyThread(Thread * pThread) { // TODO: Implement } -void GCToEEInterface::SuspendEE(GCToEEInterface::SUSPEND_REASON reason) -{ - GCHeap::GetGCHeap()->SetGCInProgress(TRUE); - - // TODO: Implement -} - -void GCToEEInterface::RestartEE(bool bFinishedGC) -{ - // TODO: Implement - - GCHeap::GetGCHeap()->SetGCInProgress(FALSE); -} - -void GCToEEInterface::ScanStackRoots(Thread * pThread, promote_func* fn, ScanContext* sc) -{ - // TODO: Implement - Scan stack roots on given thread -} - -void GCToEEInterface::ScanStaticGCRefsOpportunistically(promote_func* fn, ScanContext* sc) -{ -} - -void GCToEEInterface::GcStartWork(int condemned, int max_gen) -{ -} - -void GCToEEInterface::AfterGcScanRoots(int condemned, int max_gen, ScanContext* sc) -{ -} - -void GCToEEInterface::GcBeforeBGCSweepWork() -{ -} - -void GCToEEInterface::GcDone(int condemned) -{ -} - -void FinalizerThread::EnableFinalization() -{ - // Signal to finalizer thread that there are objects to finalize - // TODO: Implement for finalization -} - -bool PalStartBackgroundGCThread(BackgroundCallback callback, void* pCallbackContext) -{ - // TODO: Implement for background GC - return false; -} - -bool IsGCSpecialThread() -{ - // TODO: Implement for background GC - return false; -} - bool PalHasCapability(PalCapability capability) { // TODO: Implement for background GC return false; } + diff --git a/src/coreclr/src/gc/gc.cpp b/src/coreclr/src/gc/gc.cpp index f77f482..9dc6e13 100644 --- a/src/coreclr/src/gc/gc.cpp +++ b/src/coreclr/src/gc/gc.cpp @@ -1442,12 +1442,12 @@ void WaitLongerNoInstru (int i) { // every 8th attempt: Thread *pCurThread = GetThread(); - BOOL bToggleGC = FALSE; + bool bToggleGC = false; if (pCurThread) { - bToggleGC = pCurThread->PreemptiveGCDisabled(); + bToggleGC = GCToEEInterface::IsPreemptiveGCDisabled(pCurThread); if (bToggleGC) - pCurThread->EnablePreemptiveGC(); + GCToEEInterface::EnablePreemptiveGC(pCurThread); } // if we're waiting for gc to finish, we should block immediately @@ -1473,10 +1473,10 @@ void WaitLongerNoInstru (int i) { if (bToggleGC || g_TrapReturningThreads) { - pCurThread->DisablePreemptiveGC(); + GCToEEInterface::DisablePreemptiveGC(pCurThread); if (!bToggleGC) { - pCurThread->EnablePreemptiveGC(); + GCToEEInterface::EnablePreemptiveGC(pCurThread); } } } @@ -1609,13 +1609,13 @@ void WaitLonger (int i // every 8th attempt: Thread *pCurThread = GetThread(); - BOOL bToggleGC = FALSE; + bool bToggleGC = false; if (pCurThread) { - bToggleGC = pCurThread->PreemptiveGCDisabled(); + bToggleGC = GCToEEInterface::IsPreemptiveGCDisabled(pCurThread); if (bToggleGC) { - pCurThread->EnablePreemptiveGC(); + GCToEEInterface::EnablePreemptiveGC(pCurThread); } else { @@ -1657,7 +1657,7 @@ void WaitLonger (int i #ifdef SYNCHRONIZATION_STATS (spin_lock->num_disable_preemptive_w)++; #endif //SYNCHRONIZATION_STATS - pCurThread->DisablePreemptiveGC(); + GCToEEInterface::DisablePreemptiveGC(pCurThread); } } } @@ -1735,13 +1735,13 @@ static void leave_spin_lock (GCSpinLock * spin_lock) BOOL gc_heap::enable_preemptive (Thread* current_thread) { - BOOL cooperative_mode = FALSE; + bool cooperative_mode = false; if (current_thread) { - cooperative_mode = current_thread->PreemptiveGCDisabled(); + cooperative_mode = GCToEEInterface::IsPreemptiveGCDisabled(current_thread); if (cooperative_mode) { - current_thread->EnablePreemptiveGC(); + GCToEEInterface::EnablePreemptiveGC(current_thread); } } @@ -1754,7 +1754,7 @@ void gc_heap::disable_preemptive (Thread* current_thread, BOOL restore_cooperati { if (restore_cooperative) { - current_thread->DisablePreemptiveGC(); + GCToEEInterface::DisablePreemptiveGC(current_thread); } } } @@ -24371,7 +24371,7 @@ DWORD __stdcall gc_heap::bgc_thread_stub (void* arg) // since now GC threads can be managed threads. ClrFlsSetThreadType (ThreadType_GC); assert (heap->bgc_thread != NULL); - heap->bgc_thread->SetGCSpecial(true); + GCToEEInterface::SetGCSpecial(heap->bgc_thread); STRESS_LOG_RESERVE_MEM (GC_STRESSLOG_MULTIPLY); // We commit the thread's entire stack to ensure we're robust in low memory conditions. @@ -24607,10 +24607,10 @@ void gc_heap::allow_fgc() { assert (bgc_thread == GetThread()); - if (bgc_thread->PreemptiveGCDisabled() && bgc_thread->CatchAtSafePoint()) + if (GCToEEInterface::IsPreemptiveGCDisabled(bgc_thread) && GCToEEInterface::CatchAtSafePoint(bgc_thread)) { - bgc_thread->EnablePreemptiveGC(); - bgc_thread->DisablePreemptiveGC(); + GCToEEInterface::EnablePreemptiveGC(bgc_thread); + GCToEEInterface::DisablePreemptiveGC(bgc_thread); } } @@ -33419,11 +33419,6 @@ void GCHeap::Relocate (Object** ppObject, ScanContext* sc, STRESS_LOG_ROOT_RELOCATE(ppObject, object, pheader, ((!(flags & GC_CALL_INTERIOR)) ? ((Object*)object)->GetGCSafeMethodTable() : 0)); } -/*static*/ BOOL GCHeap::IsLargeObject(MethodTable *mt) -{ - return mt->GetBaseSize() >= LARGE_OBJECT_SIZE; -} - /*static*/ BOOL GCHeap::IsObjectInFixedHeap(Object *pObj) { // For now we simply look at the size of the object to determine if it in the @@ -34432,9 +34427,9 @@ void gc_heap::do_pre_gc() { #ifdef BACKGROUND_GC full_gc_counts[gc_type_background]++; -#ifdef STRESS_HEAP +#if defined(STRESS_HEAP) && !defined(FEATURE_REDHAWK) GCHeap::gc_stress_fgcs_in_bgc = 0; -#endif // STRESS_HEAP +#endif // STRESS_HEAP && !FEATURE_REDHAWK #endif // BACKGROUND_GC } else @@ -35397,7 +35392,7 @@ void CFinalize::EnterFinalizeLock() { _ASSERTE(dbgOnly_IsSpecialEEThread() || GetThread() == 0 || - GetThread()->PreemptiveGCDisabled()); + GCToEEInterface::IsPreemptiveGCDisabled(GetThread())); retry: if (FastInterlockExchange (&lock, 0) >= 0) @@ -35424,7 +35419,7 @@ void CFinalize::LeaveFinalizeLock() { _ASSERTE(dbgOnly_IsSpecialEEThread() || GetThread() == 0 || - GetThread()->PreemptiveGCDisabled()); + GCToEEInterface::IsPreemptiveGCDisabled(GetThread())); #ifdef _DEBUG lockowner_threadid = (DWORD) -1; diff --git a/src/coreclr/src/gc/gc.h b/src/coreclr/src/gc/gc.h index 7ccf5d5..f571cbc 100644 --- a/src/coreclr/src/gc/gc.h +++ b/src/coreclr/src/gc/gc.h @@ -598,13 +598,6 @@ public: // static if since restricting for all heaps is fine virtual size_t GetValidSegmentSize(BOOL large_seg = FALSE) = 0; - - static BOOL IsLargeObject(MethodTable *mt) { - WRAPPER_NO_CONTRACT; - - return mt->GetBaseSize() >= LARGE_OBJECT_SIZE; - } - static unsigned GetMaxGeneration() { LIMITED_METHOD_DAC_CONTRACT; return max_generation; @@ -622,6 +615,7 @@ public: #ifdef FEATURE_BASICFREEZE // frozen segment management functions virtual segment_handle RegisterFrozenSegment(segment_info *pseginfo) = 0; + virtual void UnregisterFrozenSegment(segment_handle seg) = 0; #endif //FEATURE_BASICFREEZE // debug support diff --git a/src/coreclr/src/gc/gcee.cpp b/src/coreclr/src/gc/gcee.cpp index 169b217..196eb49 100644 --- a/src/coreclr/src/gc/gcee.cpp +++ b/src/coreclr/src/gc/gcee.cpp @@ -675,16 +675,16 @@ void gc_heap::fire_etw_pin_object_event (BYTE* object, BYTE** ppObject) DWORD gc_heap::user_thread_wait (CLREvent *event, BOOL no_mode_change, int time_out_ms) { Thread* pCurThread = NULL; - BOOL mode = FALSE; + bool mode = false; DWORD dwWaitResult = NOERROR; if (!no_mode_change) { pCurThread = GetThread(); - mode = pCurThread ? pCurThread->PreemptiveGCDisabled() : FALSE; + mode = pCurThread ? GCToEEInterface::IsPreemptiveGCDisabled(pCurThread) : false; if (mode) { - pCurThread->EnablePreemptiveGC(); + GCToEEInterface::EnablePreemptiveGC(pCurThread); } } @@ -692,7 +692,7 @@ DWORD gc_heap::user_thread_wait (CLREvent *event, BOOL no_mode_change, int time_ if (!no_mode_change && mode) { - pCurThread->DisablePreemptiveGC(); + GCToEEInterface::DisablePreemptiveGC(pCurThread); } return dwWaitResult; @@ -787,7 +787,7 @@ DWORD WINAPI gc_heap::rh_bgc_thread_stub(void * pContext) // should not be acquired as part of this operation. This is necessary because this thread is created in // the context of a garbage collection and the lock is already held by the GC. ASSERT(GCHeap::GetGCHeap()->IsGCInProgress()); - ThreadStore::AttachCurrentThread(false); + GCToEEInterface::AttachCurrentThread(); // Inform the GC which Thread* we are. pStartContext->m_pRealContext->bgc_thread = GetThread(); @@ -798,4 +798,54 @@ DWORD WINAPI gc_heap::rh_bgc_thread_stub(void * pContext) #endif // BACKGROUND_GC && FEATURE_REDHAWK +#ifdef FEATURE_BASICFREEZE +segment_handle GCHeap::RegisterFrozenSegment(segment_info *pseginfo) +{ + heap_segment * seg = new (nothrow) heap_segment; + if (!seg) + { + return NULL; + } + + BYTE* base_mem = (BYTE*)pseginfo->pvMem; + heap_segment_mem(seg) = base_mem + pseginfo->ibFirstObject; + heap_segment_allocated(seg) = base_mem + pseginfo->ibAllocated; + heap_segment_committed(seg) = base_mem + pseginfo->ibCommit; + heap_segment_reserved(seg) = base_mem + pseginfo->ibReserved; + heap_segment_next(seg) = 0; + heap_segment_used(seg) = heap_segment_allocated(seg); + heap_segment_plan_allocated(seg) = 0; + seg->flags = heap_segment_flags_readonly; + +#if defined (MULTIPLE_HEAPS) && !defined (ISOLATED_HEAPS) + gc_heap* heap = gc_heap::g_heaps[0]; + heap_segment_heap(seg) = heap; +#else + gc_heap* heap = pGenGCHeap; +#endif //MULTIPLE_HEAPS && !ISOLATED_HEAPS + + if (heap->insert_ro_segment(seg) == FALSE) + { + delete seg; + return NULL; + } + + return reinterpret_cast< segment_handle >(seg); +} + +void GCHeap::UnregisterFrozenSegment(segment_handle seg) +{ +#if defined (MULTIPLE_HEAPS) && !defined (ISOLATED_HEAPS) + gc_heap* heap = gc_heap::g_heaps[0]; +#else + gc_heap* heap = pGenGCHeap; +#endif //MULTIPLE_HEAPS && !ISOLATED_HEAPS + + heap->remove_ro_segment(reinterpret_cast(seg)); +} +#endif // FEATURE_BASICFREEZE + + #endif // !DACCESS_COMPILE + + diff --git a/src/coreclr/src/gc/gcimpl.h b/src/coreclr/src/gc/gcimpl.h index 86de9ca..53cf9c8 100644 --- a/src/coreclr/src/gc/gcimpl.h +++ b/src/coreclr/src/gc/gcimpl.h @@ -135,10 +135,8 @@ public: int GetHomeHeapNumber (); bool IsThreadUsingAllocationContextHeap(alloc_context* acontext, int thread_number); int GetNumberOfHeaps (); - void HideAllocContext(alloc_context*); - void RevealAllocContext(alloc_context*); - - static BOOL IsLargeObject(MethodTable *mt); + void HideAllocContext(alloc_context*); + void RevealAllocContext(alloc_context*); BOOL IsObjectInFixedHeap(Object *pObj); @@ -160,7 +158,7 @@ public: DWORD flags=0); // Find the relocation address for an object - PER_HEAP_ISOLATED void Relocate (Object** object, + PER_HEAP_ISOLATED void Relocate (Object** object, ScanContext* sc, DWORD flags=0); @@ -180,7 +178,7 @@ public: BOOL IsHeapPointer (void* object, BOOL small_heap_only = FALSE); #ifdef VERIFY_HEAP - void ValidateObjectMember (Object *obj); + void ValidateObjectMember (Object *obj); #endif //_DEBUG PER_HEAP size_t ApproxTotalBytesInUse(BOOL small_heap_only = FALSE); @@ -226,7 +224,7 @@ public: BOOL FinalizeAppDomain(AppDomain *pDomain, BOOL fRunFinalizers); BOOL ShouldRestartFinalizerWatchDog(); - void SetCardsAfterBulkCopy( Object**, size_t); + void SetCardsAfterBulkCopy( Object**, size_t); #if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) void WalkObject (Object* obj, walk_fn fn, void* context); #endif // defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) @@ -255,6 +253,7 @@ public: // FIX #ifdef FEATURE_BASICFREEZE // frozen segment management functions virtual segment_handle RegisterFrozenSegment(segment_info *pseginfo); + virtual void UnregisterFrozenSegment(segment_handle seg); #endif // FEATURE_BASICFREEZE void WaitUntilConcurrentGCComplete (); // Use in managd threads @@ -267,7 +266,7 @@ public: // FIX void TemporaryEnableConcurrentGC(); void TemporaryDisableConcurrentGC(); BOOL IsConcurrentGCEnabled(); - + PER_HEAP_ISOLATED CLREvent *WaitForGCEvent; // used for syncing w/GC PER_HEAP_ISOLATED CFinalize* m_Finalize; diff --git a/src/coreclr/src/gc/gcscan.cpp b/src/coreclr/src/gc/gcscan.cpp index c5f4837..7729ffa 100644 --- a/src/coreclr/src/gc/gcscan.cpp +++ b/src/coreclr/src/gc/gcscan.cpp @@ -178,11 +178,12 @@ VOID CNameSpace::GcScanRoots(promote_func* fn, int condemned, int max_gen, } Thread* pThread = NULL; - while ((pThread = ThreadStore::GetThreadList(pThread)) != NULL) + while ((pThread = GCToEEInterface::GetThreadList(pThread)) != NULL) { STRESS_LOG2(LF_GC|LF_GCROOTS, LL_INFO100, "{ Starting scan of Thread %p ID = %x\n", pThread, pThread->GetThreadId()); - if (GCHeap::GetGCHeap()->IsThreadUsingAllocationContextHeap(pThread->GetAllocContext(), sc->thread_number)) + if (GCHeap::GetGCHeap()->IsThreadUsingAllocationContextHeap( + GCToEEInterface::GetAllocContext(pThread), sc->thread_number)) { sc->thread_under_crawl = pThread; #ifdef FEATURE_EVENT_TRACE @@ -324,9 +325,9 @@ void CNameSpace::GcFixAllocContexts (void* arg, void *heap) if (GCHeap::UseAllocationContexts()) { Thread *thread = NULL; - while ((thread = ThreadStore::GetThreadList(thread)) != NULL) + while ((thread = GCToEEInterface::GetThreadList(thread)) != NULL) { - GCHeap::GetGCHeap()->FixAllocContext(thread->GetAllocContext(), FALSE, arg, heap); + GCHeap::GetGCHeap()->FixAllocContext(GCToEEInterface::GetAllocContext(thread), FALSE, arg, heap); } } } @@ -338,9 +339,9 @@ void CNameSpace::GcEnumAllocContexts (enum_alloc_context_func* fn) if (GCHeap::UseAllocationContexts()) { Thread *thread = NULL; - while ((thread = ThreadStore::GetThreadList(thread)) != NULL) + while ((thread = GCToEEInterface::GetThreadList(thread)) != NULL) { - (*fn) (thread->GetAllocContext()); + (*fn) (GCToEEInterface::GetAllocContext(thread)); } } } diff --git a/src/coreclr/src/gc/handletable.cpp b/src/coreclr/src/gc/handletable.cpp index c3d566f..59aa60a 100644 --- a/src/coreclr/src/gc/handletable.cpp +++ b/src/coreclr/src/gc/handletable.cpp @@ -669,6 +669,30 @@ void HndSetHandleExtraInfo(OBJECTHANDLE handle, UINT uType, LPARAM lExtraInfo) *pUserData = lExtraInfo; } } + +/* +* HndCompareExchangeHandleExtraInfo +* +* Stores owner data with handle. +* +*/ +LPARAM HndCompareExchangeHandleExtraInfo(OBJECTHANDLE handle, UINT uType, LPARAM lOldExtraInfo, LPARAM lNewExtraInfo) +{ + WRAPPER_NO_CONTRACT; + + // fetch the user data slot for this handle if we have the right type + LPARAM *pUserData = HandleValidateAndFetchUserDataPointer(handle, uType); + + // is there a slot? + if (pUserData) + { + // yes - attempt to store the info + return (LPARAM)FastInterlockCompareExchangePointer((PVOID*)pUserData, (PVOID)lNewExtraInfo, (PVOID)lOldExtraInfo); + } + + _ASSERTE(!"Shouldn't be trying to call HndCompareExchangeHandleExtraInfo on handle types without extra info"); + return NULL; +} #endif // !DACCESS_COMPILE /* diff --git a/src/coreclr/src/gc/handletable.h b/src/coreclr/src/gc/handletable.h index 10ca946..41ff462 100644 --- a/src/coreclr/src/gc/handletable.h +++ b/src/coreclr/src/gc/handletable.h @@ -84,6 +84,7 @@ void HndDestroyHandles(HHANDLETABLE hTable, UINT uType, const OBJECTH * owner data associated with handles */ void HndSetHandleExtraInfo(OBJECTHANDLE handle, UINT uType, LPARAM lExtraInfo); +LPARAM HndCompareExchangeHandleExtraInfo(OBJECTHANDLE handle, UINT uType, LPARAM lOldExtraInfo, LPARAM lNewExtraInfo); #endif // !DACCESS_COMPILE LPARAM HndGetHandleExtraInfo(OBJECTHANDLE handle); diff --git a/src/coreclr/src/gc/objecthandle.cpp b/src/coreclr/src/gc/objecthandle.cpp index 8e07e9e..b62407a 100644 --- a/src/coreclr/src/gc/objecthandle.cpp +++ b/src/coreclr/src/gc/objecthandle.cpp @@ -46,7 +46,7 @@ struct VARSCANINFO { LPARAM lEnableMask; // mask of types to trace HANDLESCANPROC pfnTrace; // tracing function to use - LPARAM lp2; // second parameter + LPARAM lp2; // second parameter }; @@ -73,7 +73,7 @@ void CALLBACK VariableTraceDispatcher(_UNCHECKED_OBJECTREF *pObjRef, LPARAM *pEx } } -#ifdef FEATURE_COMINTEROP +#if defined(FEATURE_COMINTEROP) || defined(FEATURE_REDHAWK) /* * Scan callback for tracing ref-counted handles. * @@ -97,12 +97,7 @@ void CALLBACK PromoteRefCounted(_UNCHECKED_OBJECTREF *pObjRef, LPARAM *pExtraInf if (!HndIsNullOrDestroyedHandle(pObj) && !GCHeap::GetGCHeap()->IsPromoted(pObj)) { - //@todo optimize the access to the ref-count - ComCallWrapper* pWrap = ComCallWrapper::GetWrapperForObject((OBJECTREF)pObj); - _ASSERTE(pWrap != NULL); - - BOOL fIsActive = pWrap->IsWrapperActive(); - if (fIsActive) + if (GCToEEInterface::RefCountedHandleCallbacks(pObj)) { _ASSERTE(lp2); promote_func* callback = (promote_func*) lp2; @@ -113,7 +108,7 @@ void CALLBACK PromoteRefCounted(_UNCHECKED_OBJECTREF *pObjRef, LPARAM *pExtraInf // Assert this object wasn't relocated since we are passing a temporary object's address. _ASSERTE(pOldObj == pObj); } -#endif // FEATURE_COMINTEROP +#endif // FEATURE_COMINTEROP || FEATURE_REDHAWK void CALLBACK TraceDependentHandle(_UNCHECKED_OBJECTREF *pObjRef, LPARAM *pExtraInfo, LPARAM lp1, LPARAM lp2) { @@ -446,14 +441,28 @@ void CALLBACK ScanPointerForProfilerAndETW(_UNCHECKED_OBJECTREF *pObjRef, LPARAM break; case HNDTYPE_VARIABLE: -#if 0 // this feature appears to be unused for now - rootFlags |= COR_PRF_GC_ROOT_VARIABLE; +#ifdef FEATURE_REDHAWK + { + // Set the appropriate ETW flags for the current strength of this variable handle + UINT nVarHandleType = GetVariableHandleType(handle); + if (((nVarHandleType & VHT_WEAK_SHORT) != 0) || + ((nVarHandleType & VHT_WEAK_LONG) != 0)) + { + rootFlags |= kEtwGCRootFlagsWeakRef; + } + if ((nVarHandleType & VHT_PINNED) != 0) + { + rootFlags |= kEtwGCRootFlagsPinning; + } + + // No special ETW flag for strong handles (VHT_STRONG) + } #else _ASSERTE(!"Variable handle encountered"); #endif break; -#ifdef FEATURE_COMINTEROP +#if defined(FEATURE_COMINTEROP) && !defined(FEATURE_REDHAWK) case HNDTYPE_REFCOUNTED: rootFlags |= kEtwGCRootFlagsRefCounted; if (*pRef != NULL) @@ -463,7 +472,7 @@ void CALLBACK ScanPointerForProfilerAndETW(_UNCHECKED_OBJECTREF *pObjRef, LPARAM rootFlags |= kEtwGCRootFlagsWeakRef; } break; -#endif // FEATURE_COMINTEROP +#endif // FEATURE_COMINTEROP || FEATURE_REDHAWK } _UNCHECKED_OBJECTREF pSec = NULL; @@ -948,6 +957,17 @@ OBJECTHANDLE CreateVariableHandle(HHANDLETABLE hTable, OBJECTREF object, UINT ty return HndCreateHandle(hTable, HNDTYPE_VARIABLE, object, (LPARAM)type); } +/* +* GetVariableHandleType. +* +* Retrieves the dynamic type of a variable-strength handle. +*/ +UINT GetVariableHandleType(OBJECTHANDLE handle) +{ + WRAPPER_NO_CONTRACT; + + return (UINT)HndGetHandleExtraInfo(handle); +} /* * UpdateVariableHandleType. @@ -981,6 +1001,23 @@ void UpdateVariableHandleType(OBJECTHANDLE handle, UINT type) HndSetHandleExtraInfo(handle, HNDTYPE_VARIABLE, (LPARAM)type); } +/* +* CompareExchangeVariableHandleType. +* +* Changes the dynamic type of a variable-strength handle. Unlike UpdateVariableHandleType we assume that the +* types have already been validated. +*/ +UINT CompareExchangeVariableHandleType(OBJECTHANDLE handle, UINT oldType, UINT newType) +{ + WRAPPER_NO_CONTRACT; + + // verify that we are being asked to get/set valid types + _ASSERTE(IS_VALID_VHT_VALUE(oldType) && IS_VALID_VHT_VALUE(newType)); + + // attempt to store the type in the handle's extra info + return (UINT)HndCompareExchangeHandleExtraInfo(handle, HNDTYPE_VARIABLE, (LPARAM)oldType, (LPARAM)newType); +} + /* * TraceVariableHandles. @@ -1122,7 +1159,7 @@ void Ref_TraceNormalRoots(UINT condemned, UINT maxgen, ScanContext* sc, Ref_prom // promote objects pointed to by variable handles whose dynamic type is VHT_STRONG TraceVariableHandles(PromoteObject, LPARAM(sc), LPARAM(fn), VHT_STRONG, condemned, maxgen, flags); -#ifdef FEATURE_COMINTEROP +#if defined(FEATURE_COMINTEROP) || defined(FEATURE_REDHAWK) // don't scan ref-counted handles during concurrent phase as the clean-up of CCWs can race with AD unload and cause AV's if (!sc->concurrent) { @@ -1141,7 +1178,7 @@ void Ref_TraceNormalRoots(UINT condemned, UINT maxgen, ScanContext* sc, Ref_prom walk = walk->pNext; } } -#endif // FEATURE_COMINTEROP +#endif // FEATURE_COMINTEROP || FEATURE_REDHAWK } #ifdef FEATURE_COMINTEROP @@ -1184,9 +1221,9 @@ void Ref_CheckReachable(UINT condemned, UINT maxgen, LPARAM lp1) UINT types[] = { HNDTYPE_WEAK_LONG, -#ifdef FEATURE_COMINTEROP +#if defined(FEATURE_COMINTEROP) || defined(FEATURE_REDHAWK) HNDTYPE_REFCOUNTED, -#endif // FEATURE_COMINTEROP +#endif // FEATURE_COMINTEROP || FEATURE_REDHAWK }; // check objects pointed to by short weak handles @@ -1534,8 +1571,10 @@ void Ref_UpdatePointers(UINT condemned, UINT maxgen, ScanContext* sc, Ref_promot HNDTYPE_WEAK_SHORT, HNDTYPE_WEAK_LONG, HNDTYPE_STRONG, -#ifdef FEATURE_COMINTEROP +#if defined(FEATURE_COMINTEROP) || defined(FEATURE_REDHAWK) HNDTYPE_REFCOUNTED, +#endif // FEATURE_COMINTEROP || FEATURE_REDHAWK +#ifdef FEATURE_COMINTEROP HNDTYPE_WEAK_WINRT, #endif // FEATURE_COMINTEROP HNDTYPE_SIZEDREF, @@ -1547,12 +1586,12 @@ void Ref_UpdatePointers(UINT condemned, UINT maxgen, ScanContext* sc, Ref_promot HandleTableMap *walk = &g_HandleTableMap; while (walk) { for (UINT i = 0; i < INITIAL_HANDLE_TABLE_ARRAY_SIZE; i ++) - if (walk->pBuckets[i] != NULL) - { - HHANDLETABLE hTable = walk->pBuckets[i]->pTable[getSlotNumber(sc)]; - if (hTable) - HndScanHandlesForGC(hTable, UpdatePointer, LPARAM(sc), LPARAM(fn), types, _countof(types), condemned, maxgen, flags); - } + if (walk->pBuckets[i] != NULL) + { + HHANDLETABLE hTable = walk->pBuckets[i]->pTable[getSlotNumber(sc)]; + if (hTable) + HndScanHandlesForGC(hTable, UpdatePointer, LPARAM(sc), LPARAM(fn), types, _countof(types), condemned, maxgen, flags); + } walk = walk->pNext; } @@ -1578,10 +1617,12 @@ void Ref_ScanPointersForProfilerAndETW(UINT maxgen, LPARAM lp1) HNDTYPE_WEAK_SHORT, HNDTYPE_WEAK_LONG, HNDTYPE_STRONG, -#ifdef FEATURE_COMINTEROP +#if defined(FEATURE_COMINTEROP) || defined(FEATURE_REDHAWK) HNDTYPE_REFCOUNTED, +#endif // FEATURE_COMINTEROP || FEATURE_REDHAWK +#ifdef FEATURE_COMINTEROP HNDTYPE_WEAK_WINRT, -#endif // FEATURE_COMINTEROP, +#endif // FEATURE_COMINTEROP HNDTYPE_PINNED, // HNDTYPE_VARIABLE, HNDTYPE_ASYNCPINNED, @@ -1671,8 +1712,10 @@ void Ref_AgeHandles(UINT condemned, UINT maxgen, LPARAM lp1) HNDTYPE_PINNED, HNDTYPE_VARIABLE, -#ifdef FEATURE_COMINTEROP +#if defined(FEATURE_COMINTEROP) || defined(FEATURE_REDHAWK) HNDTYPE_REFCOUNTED, +#endif // FEATURE_COMINTEROP || FEATURE_REDHAWK +#ifdef FEATURE_COMINTEROP HNDTYPE_WEAK_WINRT, #endif // FEATURE_COMINTEROP HNDTYPE_ASYNCPINNED, @@ -1712,8 +1755,10 @@ void Ref_RejuvenateHandles(UINT condemned, UINT maxgen, LPARAM lp1) HNDTYPE_PINNED, HNDTYPE_VARIABLE, -#ifdef FEATURE_COMINTEROP +#if defined(FEATURE_COMINTEROP) || defined(FEATURE_REDHAWK) HNDTYPE_REFCOUNTED, +#endif // FEATURE_COMINTEROP || FEATURE_REDHAWK +#ifdef FEATURE_COMINTEROP HNDTYPE_WEAK_WINRT, #endif // FEATURE_COMINTEROP HNDTYPE_ASYNCPINNED, @@ -1752,8 +1797,10 @@ void Ref_VerifyHandleTable(UINT condemned, UINT maxgen, ScanContext* sc) HNDTYPE_PINNED, HNDTYPE_VARIABLE, -#ifdef FEATURE_COMINTEROP +#if defined(FEATURE_COMINTEROP) || defined(FEATURE_REDHAWK) HNDTYPE_REFCOUNTED, +#endif // FEATURE_COMINTEROP || FEATURE_REDHAWK +#ifdef FEATURE_COMINTEROP HNDTYPE_WEAK_WINRT, #endif // FEATURE_COMINTEROP HNDTYPE_ASYNCPINNED, @@ -1781,8 +1828,8 @@ int GetCurrentThreadHomeHeapNumber() { WRAPPER_NO_CONTRACT; - if (!GCHeap::IsGCHeapInitialized()) - return 0; + if (!GCHeap::IsGCHeapInitialized()) + return 0; return GCHeap::GetGCHeap()->GetHomeHeapNumber(); } diff --git a/src/coreclr/src/gc/objecthandle.h b/src/coreclr/src/gc/objecthandle.h index 6371c7a..5267d7b 100644 --- a/src/coreclr/src/gc/objecthandle.h +++ b/src/coreclr/src/gc/objecthandle.h @@ -119,7 +119,7 @@ */ #define HNDTYPE_VARIABLE (4) -#ifdef FEATURE_COMINTEROP +#if defined(FEATURE_COMINTEROP) || defined(FEATURE_REDHAWK) /* * REFCOUNTED HANDLES * @@ -131,7 +131,7 @@ * */ #define HNDTYPE_REFCOUNTED (5) -#endif // FEATURE_COMINTEROP +#endif // FEATURE_COMINTEROP || FEATURE_REDHAWK /* @@ -149,7 +149,7 @@ * * */ -#define HNDTYPE_DEPENDENT (6) +#define HNDTYPE_DEPENDENT (6) /* * PINNED HANDLES for asynchronous operation @@ -439,7 +439,9 @@ inline void DestroyDependentHandle(OBJECTHANDLE handle) #ifndef DACCESS_COMPILE OBJECTHANDLE CreateVariableHandle(HHANDLETABLE hTable, OBJECTREF object, UINT type); +UINT GetVariableHandleType(OBJECTHANDLE handle); void UpdateVariableHandleType(OBJECTHANDLE handle, UINT type); +UINT CompareExchangeVariableHandleType(OBJECTHANDLE handle, UINT oldType, UINT newType); inline void DestroyVariableHandle(OBJECTHANDLE handle) { diff --git a/src/coreclr/src/gc/sample/GCSample.cpp b/src/coreclr/src/gc/sample/GCSample.cpp index 7c47fec..071a87f 100644 --- a/src/coreclr/src/gc/sample/GCSample.cpp +++ b/src/coreclr/src/gc/sample/GCSample.cpp @@ -145,7 +145,7 @@ int main(int argc, char* argv[]) // // Initialize current thread // - ThreadStore::AttachCurrentThread(false); + ThreadStore::AttachCurrentThread(); // // Create a Methodtable with GCDesc diff --git a/src/coreclr/src/gc/sample/GCSample.vcxproj b/src/coreclr/src/gc/sample/GCSample.vcxproj index 235d75d..a0a79c5 100644 --- a/src/coreclr/src/gc/sample/GCSample.vcxproj +++ b/src/coreclr/src/gc/sample/GCSample.vcxproj @@ -83,6 +83,7 @@ + @@ -93,7 +94,7 @@ - + Create Create diff --git a/src/coreclr/src/gc/sample/GCSample.vcxproj.filters b/src/coreclr/src/gc/sample/GCSample.vcxproj.filters index 07c46a7..1e9facd 100644 --- a/src/coreclr/src/gc/sample/GCSample.vcxproj.filters +++ b/src/coreclr/src/gc/sample/GCSample.vcxproj.filters @@ -23,9 +23,6 @@ - - Source Files - Source Files @@ -50,14 +47,20 @@ Source Files - - Source Files - Source Files Source Files + + Source Files + + + Source Files + + + Source Files + \ No newline at end of file diff --git a/src/coreclr/src/gc/sample/gcenv.cpp b/src/coreclr/src/gc/sample/gcenv.cpp new file mode 100644 index 0000000..45af9bc --- /dev/null +++ b/src/coreclr/src/gc/sample/gcenv.cpp @@ -0,0 +1,155 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +#include "common.h" + +#include "windows.h" + +#include "gcenv.h" +#include "gc.h" + +EEConfig * g_pConfig; + +#ifdef _MSC_VER +__declspec(thread) +#else +__thread +#endif +Thread * pCurrentThread; + +Thread * GetThread() +{ + return pCurrentThread; +} + +Thread * g_pThreadList = NULL; + +Thread * ThreadStore::GetThreadList(Thread * pThread) +{ + if (pThread == NULL) + return g_pThreadList; + + return pThread->m_pNext; +} + +void ThreadStore::AttachCurrentThread() +{ + // TODO: Locks + + Thread * pThread = new Thread(); + pThread->GetAllocContext()->init(); + pCurrentThread = pThread; + + pThread->m_pNext = g_pThreadList; + g_pThreadList = pThread; +} + +void GCToEEInterface::SuspendEE(GCToEEInterface::SUSPEND_REASON reason) +{ + GCHeap::GetGCHeap()->SetGCInProgress(TRUE); + + // TODO: Implement +} + +void GCToEEInterface::RestartEE(bool bFinishedGC) +{ + // TODO: Implement + + GCHeap::GetGCHeap()->SetGCInProgress(FALSE); +} + +void GCToEEInterface::ScanStackRoots(Thread * pThread, promote_func* fn, ScanContext* sc) +{ + // TODO: Implement - Scan stack roots on given thread +} + +void GCToEEInterface::ScanStaticGCRefsOpportunistically(promote_func* fn, ScanContext* sc) +{ +} + +void GCToEEInterface::GcStartWork(int condemned, int max_gen) +{ +} + +void GCToEEInterface::AfterGcScanRoots(int condemned, int max_gen, ScanContext* sc) +{ +} + +void GCToEEInterface::GcBeforeBGCSweepWork() +{ +} + +void GCToEEInterface::GcDone(int condemned) +{ +} + +bool GCToEEInterface::RefCountedHandleCallbacks(Object * pObject) +{ + return false; +} + +bool GCToEEInterface::IsPreemptiveGCDisabled(Thread * pThread) +{ + return !!pThread->PreemptiveGCDisabled(); +} + +void GCToEEInterface::EnablePreemptiveGC(Thread * pThread) +{ + return pThread->EnablePreemptiveGC(); +} + +void GCToEEInterface::DisablePreemptiveGC(Thread * pThread) +{ + pThread->DisablePreemptiveGC(); +} + +void GCToEEInterface::SetGCSpecial(Thread * pThread) +{ + pThread->SetGCSpecial(true); +} + +alloc_context * GCToEEInterface::GetAllocContext(Thread * pThread) +{ + return pThread->GetAllocContext(); +} + +bool GCToEEInterface::CatchAtSafePoint(Thread * pThread) +{ + return pThread->CatchAtSafePoint(); +} + +// does not acquire thread store lock +void GCToEEInterface::AttachCurrentThread() +{ + ThreadStore::AttachCurrentThread(); +} + +Thread * GCToEEInterface::GetThreadList(Thread * pThread) +{ + return ThreadStore::GetThreadList(pThread); +} + +void FinalizerThread::EnableFinalization() +{ + // Signal to finalizer thread that there are objects to finalize + // TODO: Implement for finalization +} + +bool FinalizerThread::HaveExtraWorkForFinalizer() +{ + return false; +} + +bool PalStartBackgroundGCThread(BackgroundCallback callback, void* pCallbackContext) +{ + // TODO: Implement for background GC + return false; +} + +bool IsGCSpecialThread() +{ + // TODO: Implement for background GC + return false; +} diff --git a/src/coreclr/src/gc/sample/gcenv.h b/src/coreclr/src/gc/sample/gcenv.h new file mode 100644 index 0000000..327aa36 --- /dev/null +++ b/src/coreclr/src/gc/sample/gcenv.h @@ -0,0 +1,128 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +#include "gcenv.base.h" +#include "gcenv.object.h" +#include "gcenv.sync.h" + +// +// Thread +// + +struct alloc_context; + +class Thread +{ + uint32_t m_fPreemptiveGCDisabled; + uintptr_t m_alloc_context[16]; // Reserve enough space to fix allocation context + + friend class ThreadStore; + Thread * m_pNext; + +public: + Thread() + { + } + + bool PreemptiveGCDisabled() + { + return !!m_fPreemptiveGCDisabled; + } + + void EnablePreemptiveGC() + { + m_fPreemptiveGCDisabled = false; + } + + void DisablePreemptiveGC() + { + m_fPreemptiveGCDisabled = true; + } + + alloc_context* GetAllocContext() + { + return (alloc_context *)&m_alloc_context; + } + + void SetGCSpecial(bool fGCSpecial) + { + } + + bool CatchAtSafePoint() + { + // This is only called by the GC on a background GC worker thread that's explicitly interested in letting + // a foreground GC proceed at that point. So it's always safe to return true. + return true; + } +}; + +Thread * GetThread(); + +class ThreadStore +{ +public: + static Thread * GetThreadList(Thread * pThread); + + static void AttachCurrentThread(); +}; + +// ----------------------------------------------------------------------------------------------------------- +// Config file enumulation +// + +class EEConfig +{ +public: + enum HeapVerifyFlags { + HEAPVERIFY_NONE = 0, + HEAPVERIFY_GC = 1, // Verify the heap at beginning and end of GC + HEAPVERIFY_BARRIERCHECK = 2, // Verify the brick table + HEAPVERIFY_SYNCBLK = 4, // Verify sync block scanning + + // the following options can be used to mitigate some of the overhead introduced + // by heap verification. some options might cause heap verifiction to be less + // effective depending on the scenario. + + HEAPVERIFY_NO_RANGE_CHECKS = 0x10, // Excludes checking if an OBJECTREF is within the bounds of the managed heap + HEAPVERIFY_NO_MEM_FILL = 0x20, // Excludes filling unused segment portions with fill pattern + HEAPVERIFY_POST_GC_ONLY = 0x40, // Performs heap verification post-GCs only (instead of before and after each GC) + HEAPVERIFY_DEEP_ON_COMPACT = 0x80 // Performs deep object verfication only on compacting GCs. + }; + + enum GCStressFlags { + GCSTRESS_NONE = 0, + GCSTRESS_ALLOC = 1, // GC on all allocs and 'easy' places + GCSTRESS_TRANSITION = 2, // GC on transitions to preemtive GC + GCSTRESS_INSTR_JIT = 4, // GC on every allowable JITed instr + GCSTRESS_INSTR_NGEN = 8, // GC on every allowable NGEN instr + GCSTRESS_UNIQUE = 16, // GC only on a unique stack trace + }; + + int GetHeapVerifyLevel() { return 0; } + bool IsHeapVerifyEnabled() { return GetHeapVerifyLevel() != 0; } + + GCStressFlags GetGCStressLevel() const { return GCSTRESS_NONE; } + bool IsGCStressMix() const { return false; } + + int GetGCtraceStart() const { return 0; } + int GetGCtraceEnd() const { return 0; }//1000000000; } + int GetGCtraceFac() const { return 0; } + int GetGCprnLvl() const { return 0; } + bool IsGCBreakOnOOMEnabled() const { return false; } + int GetGCgen0size() const { return 0; } + int GetSegmentSize() const { return 0; } + int GetGCconcurrent() const { return 1; } + int GetGCLatencyMode() const { return 1; } + int GetGCForceCompact() const { return 0; } + int GetGCRetainVM() const { return 0; } + int GetGCTrimCommit() const { return 0; } + int GetGCLOHCompactionMode() const { return 0; } + + bool GetGCAllowVeryLargeObjects() const { return false; } + + bool GetGCConservative() const { return true; } +}; + +extern EEConfig * g_pConfig; diff --git a/src/coreclr/src/vm/gcenv.cpp b/src/coreclr/src/vm/gcenv.cpp index 963ca3a..7ed4328 100644 --- a/src/coreclr/src/vm/gcenv.cpp +++ b/src/coreclr/src/vm/gcenv.cpp @@ -21,6 +21,7 @@ #ifdef FEATURE_COMINTEROP #include "runtimecallablewrapper.h" #include "rcwwalker.h" +#include "comcallablewrapper.h" #endif // FEATURE_COMINTEROP void GCToEEInterface::SuspendEE(SUSPEND_REASON reason) @@ -611,6 +612,26 @@ void GCToEEInterface::GcDone(int condemned) #endif // FEATURE_COMINTEROP } +bool GCToEEInterface::RefCountedHandleCallbacks(Object * pObject) +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + +#ifdef FEATURE_COMINTEROP + //@todo optimize the access to the ref-count + ComCallWrapper* pWrap = ComCallWrapper::GetWrapperForObject((OBJECTREF)pObject); + _ASSERTE(pWrap != NULL); + + return !!pWrap->IsWrapperActive(); +#else + return false; +#endif +} + void GCToEEInterface::GcBeforeBGCSweepWork() { CONTRACTL @@ -649,3 +670,27 @@ void GCToEEInterface::SyncBlockCachePromotionsGranted(int max_gen) SyncBlockCache::GetSyncBlockCache()->GCDone(FALSE, max_gen); } + +void GCToEEInterface::SetGCSpecial(Thread * pThread) +{ + WRAPPER_NO_CONTRACT; + pThread->SetGCSpecial(true); +} + +alloc_context * GCToEEInterface::GetAllocContext(Thread * pThread) +{ + WRAPPER_NO_CONTRACT; + return pThread->GetAllocContext(); +} + +bool GCToEEInterface::CatchAtSafePoint(Thread * pThread) +{ + WRAPPER_NO_CONTRACT; + return !!pThread->CatchAtSafePoint(); +} + +Thread * GCToEEInterface::GetThreadList(Thread * pThread) +{ + WRAPPER_NO_CONTRACT; + return ThreadStore::GetThreadList(pThread); +} diff --git a/src/coreclr/src/vm/gcenv.h b/src/coreclr/src/vm/gcenv.h index fc5ca6d..5816d02 100644 --- a/src/coreclr/src/vm/gcenv.h +++ b/src/coreclr/src/vm/gcenv.h @@ -99,10 +99,38 @@ public: // post-gc callback. static void GcDone(int condemned); + // Promote refcounted handle callback + static bool RefCountedHandleCallbacks(Object * pObject); + // Sync block cache management static void SyncBlockCacheWeakPtrScan(HANDLESCANPROC scanProc, LPARAM lp1, LPARAM lp2); static void SyncBlockCacheDemote(int max_gen); static void SyncBlockCachePromotionsGranted(int max_gen); + + // Thread functions + static bool IsPreemptiveGCDisabled(Thread * pThread) + { + WRAPPER_NO_CONTRACT; + return !!pThread->PreemptiveGCDisabled(); + } + + static void EnablePreemptiveGC(Thread * pThread) + { + WRAPPER_NO_CONTRACT; + pThread->EnablePreemptiveGC(); + } + + static void DisablePreemptiveGC(Thread * pThread) + { + WRAPPER_NO_CONTRACT; + pThread->DisablePreemptiveGC(); + } + + static void SetGCSpecial(Thread * pThread); + static alloc_context * GetAllocContext(Thread * pThread); + static bool CatchAtSafePoint(Thread * pThread); + + static Thread * GetThreadList(Thread * pThread); }; #endif // GCENV_H_ \ No newline at end of file diff --git a/src/coreclr/src/vm/jitinterface.cpp b/src/coreclr/src/vm/jitinterface.cpp index ba0c8ba..ba6aebb 100644 --- a/src/coreclr/src/vm/jitinterface.cpp +++ b/src/coreclr/src/vm/jitinterface.cpp @@ -6269,7 +6269,7 @@ CorInfoHelpFunc CEEInfo::getNewHelperStatic(MethodTable * pMT) _ASSERTE(helper == CORINFO_HELP_NEWFAST); } else - if (GCHeap::IsLargeObject(pMT) || + if ((pMT->GetBaseSize() >= LARGE_OBJECT_SIZE) || pMT->HasFinalizer()) { // Use slow helper -- 2.7.4