diff --git a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj index 38fe476f4ab8f6..7cd940f242fc8b 100644 --- a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj +++ b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj @@ -224,7 +224,6 @@ - diff --git a/src/coreclr/System.Private.CoreLib/src/System/Buffer.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Buffer.CoreCLR.cs index 69c7ee7b4abb91..7f31868f6a0c8a 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Buffer.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Buffer.CoreCLR.cs @@ -9,12 +9,6 @@ namespace System { public partial class Buffer { - [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "Buffer_Clear")] - private static unsafe partial void ZeroMemoryInternal(void* b, nuint byteLength); - - [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "Buffer_MemMove")] - private static unsafe partial void MemmoveInternal(byte* dest, byte* src, nuint len); - [MethodImpl(MethodImplOptions.InternalCall)] private static extern void BulkMoveWithWriteBarrierInternal(ref byte destination, ref byte source, nuint byteCount); diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Intrinsics/X86/X86Base.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Intrinsics/X86/X86Base.CoreCLR.cs deleted file mode 100644 index b5e011d8d4081c..00000000000000 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Intrinsics/X86/X86Base.CoreCLR.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace System.Runtime.Intrinsics.X86 -{ - public abstract partial class X86Base - { - [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "X86BaseCpuId")] - private static unsafe partial void __cpuidex(int* cpuInfo, int functionId, int subFunctionId); - } -} diff --git a/src/coreclr/System.Private.CoreLib/src/System/Threading/Interlocked.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Threading/Interlocked.CoreCLR.cs index 9de5703e81f136..5fb05077081bbb 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Threading/Interlocked.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Threading/Interlocked.CoreCLR.cs @@ -248,13 +248,5 @@ private static long ExchangeAdd(ref long location1, long value) public static long Read(ref readonly long location) => CompareExchange(ref Unsafe.AsRef(in location), 0, 0); #endregion - - #region MemoryBarrierProcessWide - [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "Interlocked_MemoryBarrierProcessWide")] - private static partial void _MemoryBarrierProcessWide(); - - /// Provides a process-wide memory barrier that ensures that reads and writes from any CPU cannot move across the barrier. - public static void MemoryBarrierProcessWide() => _MemoryBarrierProcessWide(); - #endregion } } diff --git a/src/coreclr/nativeaot/Runtime/CMakeLists.txt b/src/coreclr/nativeaot/Runtime/CMakeLists.txt index a700315c6d7ab6..8605d11706117c 100644 --- a/src/coreclr/nativeaot/Runtime/CMakeLists.txt +++ b/src/coreclr/nativeaot/Runtime/CMakeLists.txt @@ -5,6 +5,7 @@ set(COMMON_RUNTIME_SOURCES rhassert.cpp ${RUNTIME_DIR}/CachedInterfaceDispatch.cpp CachedInterfaceDispatch_Aot.cpp + ${RUNTIME_DIR}/MiscNativeHelpers.cpp Crst.cpp DebugHeader.cpp MethodTable.cpp diff --git a/src/coreclr/nativeaot/Runtime/CachedInterfaceDispatchPal.h b/src/coreclr/nativeaot/Runtime/CachedInterfaceDispatchPal.h index 08665bca02f763..b54db68504d273 100644 --- a/src/coreclr/nativeaot/Runtime/CachedInterfaceDispatchPal.h +++ b/src/coreclr/nativeaot/Runtime/CachedInterfaceDispatchPal.h @@ -16,7 +16,7 @@ #include "Crst.h" #include "TargetPtrs.h" #include "MethodTable.h" -#include "Range.h" + #include "allocheap.h" #include "rhbinder.h" #include "ObjectLayout.h" diff --git a/src/coreclr/nativeaot/Runtime/CommonMacros.h b/src/coreclr/nativeaot/Runtime/CommonMacros.h index e2bea3c2af5fcf..be9b2fa167ce4b 100644 --- a/src/coreclr/nativeaot/Runtime/CommonMacros.h +++ b/src/coreclr/nativeaot/Runtime/CommonMacros.h @@ -63,7 +63,7 @@ inline bool IS_ALIGNED(T* val, uintptr_t alignment); #ifndef DACCESS_COMPILE #ifndef ZeroMemory -#define ZeroMemory(_dst, _size) memset((_dst), 0, (_size)) +#define ZeroMemory(Destination,Length) memset((Destination),0,(Length)) #endif #endif // !DACCESS_COMPILE @@ -83,12 +83,6 @@ inline bool IS_ALIGNED(T* val, uintptr_t alignment); #endif // HOST_64BIT -#ifndef __GCENV_BASE_INCLUDED__ - -#define OS_PAGE_SIZE PalOsPageSize() - -#endif // __GCENV_BASE_INCLUDED__ - #if defined(TARGET_ARM) #define THUMB_CODE 1 #endif @@ -264,8 +258,6 @@ typedef int32_t FC_BOOL_ARG; #define NOT_IN_DAC(x) #endif -#define INLINE inline - enum STARTUP_TIMELINE_EVENT_ID { PROCESS_ATTACH_BEGIN = 0, diff --git a/src/coreclr/nativeaot/Runtime/MiscHelpers.cpp b/src/coreclr/nativeaot/Runtime/MiscHelpers.cpp index b8d3b4f797839d..2050eb1216d9c2 100644 --- a/src/coreclr/nativeaot/Runtime/MiscHelpers.cpp +++ b/src/coreclr/nativeaot/Runtime/MiscHelpers.cpp @@ -67,15 +67,6 @@ EXTERN_C UInt32_BOOL QCALLTYPE RhYield() return PalSwitchToThread(); } -EXTERN_C void QCALLTYPE RhFlushProcessWriteBuffers() -{ - // This must be called via p/invoke -- it's a wait operation and we don't want to block thread suspension on this. - ASSERT_MSG(!ThreadStore::GetCurrentThread()->IsCurrentThreadInCooperativeMode(), - "You must p/invoke to RhFlushProcessWriteBuffers"); - - minipal_memory_barrier_process_wide(); -} - // Get the list of currently loaded NativeAOT modules (as OS HMODULE handles). The caller provides a reference // to an array of pointer-sized elements and we return the total number of modules currently loaded (whether // that is less than, equal to or greater than the number of elements in the array). If there are more modules @@ -486,13 +477,6 @@ FCIMPL2(uint32_t, RhGetKnobValues, char *** pResultKeys, char *** pResultValues) } FCIMPLEND -#if defined(TARGET_X86) || defined(TARGET_AMD64) -EXTERN_C void QCALLTYPE RhCpuIdEx(int* cpuInfo, int functionId, int subFunctionId) -{ - __cpuidex(cpuInfo, functionId, subFunctionId); -} -#endif - FCIMPL3(int32_t, RhpLockCmpXchg32, int32_t * location, int32_t value, int32_t comparand) { return PalInterlockedCompareExchange(location, value, comparand); diff --git a/src/coreclr/nativeaot/Runtime/Pal.h b/src/coreclr/nativeaot/Runtime/Pal.h index b33da9157650d6..74976bce4c9915 100644 --- a/src/coreclr/nativeaot/Runtime/Pal.h +++ b/src/coreclr/nativeaot/Runtime/Pal.h @@ -238,7 +238,6 @@ HANDLE PalCreateEventW(_In_opt_ LPSECURITY_ATTRIBUTES pEventAttributes, UInt32_B HANDLE PalGetModuleHandleFromPointer(_In_ void* pointer); #ifdef TARGET_UNIX -uint32_t PalGetOsPageSize(); typedef int32_t (*PHARDWARE_EXCEPTION_HANDLER)(uintptr_t faultCode, uintptr_t faultAddress, PAL_LIMITED_CONTEXT* palContext, uintptr_t* arg0Reg, uintptr_t* arg1Reg); void PalSetHardwareExceptionHandler(PHARDWARE_EXCEPTION_HANDLER handler); #endif diff --git a/src/coreclr/nativeaot/Runtime/Range.h b/src/coreclr/nativeaot/Runtime/Range.h deleted file mode 100644 index 0ced61e9e190ab..00000000000000 --- a/src/coreclr/nativeaot/Runtime/Range.h +++ /dev/null @@ -1,137 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -#pragma once - -namespace rh { namespace util -{ - //--------------------------------------------------------------------------------------------- - // Represents value range [a,b), and provides various convenience methods. - - template - class Range - { - typedef Range THIS_T; - - public: - //----------------------------------------------------------------------------------------- - // Construction - - Range() - : m_start(0), - m_end(0) - {} - - Range(Range const & range) - : m_start(range.m_start), - m_end(range.m_end) - {} - - static Range CreateWithEndpoint(VALUE_TYPE start, - VALUE_TYPE end) - { return Range(start, end); } - - static Range CreateWithLength(VALUE_TYPE start, LENGTH_TYPE len) - { return Range(start, start + len); } - - //----------------------------------------------------------------------------------------- - // Operations - - THIS_T& operator=(THIS_T const & range) - { m_start = range.m_start; m_end = range.m_end; return *this; } - - bool Equals(THIS_T const & range) const - { return GetStart() == range.GetStart() && GetEnd() == range.GetEnd(); } - - bool operator==(THIS_T const & range) const - { return Equals(range); } - - bool operator!=(THIS_T const & range) const - { return !Equals(range); } - - VALUE_TYPE GetStart() const - { return m_start; } - - VALUE_TYPE GetEnd() const - { return m_end; } - - LENGTH_TYPE GetLength() const - { return m_end - m_start; } - - bool IntersectsWith(THIS_T const &range) const - { return range.GetStart() < GetEnd() && range.GetEnd() > GetStart(); } - - bool IntersectsWith(VALUE_TYPE start, - VALUE_TYPE end) const - { return IntersectsWith(THIS_T(start, end)); } - - bool Contains(THIS_T const &range) const - { return GetStart() <= range.GetStart() && range.GetEnd() <= GetEnd(); } - - bool IsAdjacentTo(THIS_T const &range) const - { return GetEnd() == range.GetStart() || range.GetEnd() == GetStart(); } - - protected: - Range(VALUE_TYPE start, VALUE_TYPE end) - : m_start(start), - m_end(end) - { ASSERT(start <= end); } - - VALUE_TYPE m_start; - VALUE_TYPE m_end; - }; - - //--------------------------------------------------------------------------------------------- - // Represents address range [a,b), and provides various convenience methods. - - class MemRange : public Range - { - typedef Range BASE_T; - - public: - //----------------------------------------------------------------------------------------- - // Construction - - MemRange() - : BASE_T() - {} - - MemRange(void* pvMemStart, - uintptr_t cbMemLen) - : BASE_T(reinterpret_cast(pvMemStart), reinterpret_cast(pvMemStart) + cbMemLen) - {} - - MemRange(void* pvMemStart, - void* pvMemEnd) - : BASE_T(reinterpret_cast(pvMemStart), reinterpret_cast(pvMemEnd)) - {} - - MemRange(MemRange const & range) - : BASE_T(range) - { } - - //----------------------------------------------------------------------------------------- - // Operations - - MemRange& operator=(MemRange const & range) - { BASE_T::operator=(range); return *this; } - - uintptr_t GetPageCount() const - { - uint8_t *pCurPage = ALIGN_DOWN(GetStart(), OS_PAGE_SIZE); - uint8_t *pEndPage = ALIGN_UP(GetEnd(), OS_PAGE_SIZE); - return (pEndPage - pCurPage) / OS_PAGE_SIZE; - } - - uint8_t* GetStartPage() const - { return ALIGN_DOWN(GetStart(), OS_PAGE_SIZE); } - - // The page immediately following the last page contained by this range. - uint8_t* GetEndPage() const - { return ALIGN_UP(GetEnd(), OS_PAGE_SIZE); } - - MemRange GetPageRange() const - { return MemRange(GetStartPage(), GetEndPage()); } - }; -}// namespace util -}// namespace rh - diff --git a/src/coreclr/nativeaot/Runtime/ThunksMapping.cpp b/src/coreclr/nativeaot/Runtime/ThunksMapping.cpp index 9e087f6e9c1879..f29c73333e1184 100644 --- a/src/coreclr/nativeaot/Runtime/ThunksMapping.cpp +++ b/src/coreclr/nativeaot/Runtime/ThunksMapping.cpp @@ -33,7 +33,7 @@ static_assert((THUNK_SIZE % 4) == 0, "Thunk stubs size not aligned correctly. This will cause runtime failures."); // 32 K or OS page -#define THUNKS_MAP_SIZE (max(0x8000, OS_PAGE_SIZE)) +#define THUNKS_MAP_SIZE (max((size_t)0x8000, OS_PAGE_SIZE)) #ifdef TARGET_ARM //***************************************************************************** @@ -63,13 +63,13 @@ FCIMPL0(int, RhpGetNumThunkBlocksPerMapping) { ASSERT_MSG((THUNKS_MAP_SIZE % OS_PAGE_SIZE) == 0, "Thunks map size should be in multiples of pages"); - return THUNKS_MAP_SIZE / OS_PAGE_SIZE; + return (int)(THUNKS_MAP_SIZE / OS_PAGE_SIZE); } FCIMPLEND FCIMPL0(int, RhpGetNumThunksPerBlock) { - return min( + return (int)min( OS_PAGE_SIZE / THUNK_SIZE, // Number of thunks that can fit in a page (OS_PAGE_SIZE - POINTER_SIZE) / (POINTER_SIZE * 2) // Number of pointer pairs, minus the jump stub cell, that can fit in a page ); @@ -96,22 +96,24 @@ FCIMPLEND FCIMPL0(int, RhpGetThunkBlockSize) { - return OS_PAGE_SIZE; + return (int)OS_PAGE_SIZE; } FCIMPLEND EXTERN_C HRESULT QCALLTYPE RhAllocateThunksMapping(void** ppThunksSection) { + size_t thunksMapSize = THUNKS_MAP_SIZE; + #ifdef WIN32 - void * pNewMapping = PalVirtualAlloc(THUNKS_MAP_SIZE * 2, PAGE_READWRITE); + void * pNewMapping = PalVirtualAlloc(thunksMapSize * 2, PAGE_READWRITE); if (pNewMapping == NULL) { return E_OUTOFMEMORY; } void * pThunksSection = pNewMapping; - void * pDataSection = (uint8_t*)pNewMapping + THUNKS_MAP_SIZE; + void * pDataSection = (uint8_t*)pNewMapping + thunksMapSize; #else @@ -120,17 +122,17 @@ EXTERN_C HRESULT QCALLTYPE RhAllocateThunksMapping(void** ppThunksSection) // reduce it to RW for the data section. For the stubs section we need to increase to RWX to generate the stubs // instructions. After this we go back to RX for the stubs section before the stubs are used and should not be // changed anymore. - void * pNewMapping = PalVirtualAlloc(THUNKS_MAP_SIZE * 2, PAGE_EXECUTE_READ); + void * pNewMapping = PalVirtualAlloc(thunksMapSize * 2, PAGE_EXECUTE_READ); if (pNewMapping == NULL) { return E_OUTOFMEMORY; } void * pThunksSection = pNewMapping; - void * pDataSection = (uint8_t*)pNewMapping + THUNKS_MAP_SIZE; + void * pDataSection = (uint8_t*)pNewMapping + thunksMapSize; - if (!PalVirtualProtect(pDataSection, THUNKS_MAP_SIZE, PAGE_READWRITE) || - !PalVirtualProtect(pThunksSection, THUNKS_MAP_SIZE, PAGE_EXECUTE_READWRITE)) + if (!PalVirtualProtect(pDataSection, thunksMapSize, PAGE_READWRITE) || + !PalVirtualProtect(pThunksSection, thunksMapSize, PAGE_EXECUTE_READWRITE)) { PalVirtualFree(pNewMapping, THUNKS_MAP_SIZE * 2); return E_FAIL; @@ -172,7 +174,7 @@ EXTERN_C HRESULT QCALLTYPE RhAllocateThunksMapping(void** ppThunksSection) *((uint32_t*)pCurrentThunkAddress) = 0x00a2ff41; pCurrentThunkAddress += 3; - *((uint32_t*)pCurrentThunkAddress) = OS_PAGE_SIZE - POINTER_SIZE - (i * POINTER_SIZE * 2); + *((uint32_t*)pCurrentThunkAddress) = (uint32_t)(OS_PAGE_SIZE - POINTER_SIZE - (i * POINTER_SIZE * 2)); pCurrentThunkAddress += 4; // nops for alignment @@ -231,7 +233,7 @@ EXTERN_C HRESULT QCALLTYPE RhAllocateThunksMapping(void** ppThunksSection) *((uint32_t*)pCurrentThunkAddress) = 0x10000010 | (((delta & 0x03) << 29) | (((delta & 0x1FFFFC) >> 2) << 5)); pCurrentThunkAddress += 4; - *((uint32_t*)pCurrentThunkAddress) = 0xF9400211 | (((OS_PAGE_SIZE - POINTER_SIZE - (i * POINTER_SIZE * 2)) / 8) << 10); + *((uint32_t*)pCurrentThunkAddress) = 0xF9400211 | (((uint32_t)((OS_PAGE_SIZE - POINTER_SIZE - (i * POINTER_SIZE * 2)) / 8) << 10)); pCurrentThunkAddress += 4; *((uint32_t*)pCurrentThunkAddress) = 0xD61F0220; @@ -307,14 +309,14 @@ EXTERN_C HRESULT QCALLTYPE RhAllocateThunksMapping(void** ppThunksSection) #error "Unknown OS" #endif #else - if (!PalVirtualProtect(pThunksSection, THUNKS_MAP_SIZE, PAGE_EXECUTE_READ)) + if (!PalVirtualProtect(pThunksSection, thunksMapSize, PAGE_EXECUTE_READ)) { - PalVirtualFree(pNewMapping, THUNKS_MAP_SIZE * 2); + PalVirtualFree(pNewMapping, thunksMapSize * 2); return E_FAIL; } #endif - PalFlushInstructionCache(pThunksSection, THUNKS_MAP_SIZE); + PalFlushInstructionCache(pThunksSection, thunksMapSize); *ppThunksSection = pThunksSection; return S_OK; diff --git a/src/coreclr/nativeaot/Runtime/allocheap.cpp b/src/coreclr/nativeaot/Runtime/allocheap.cpp index dd8425cc0ef519..f03a34c946189f 100644 --- a/src/coreclr/nativeaot/Runtime/allocheap.cpp +++ b/src/coreclr/nativeaot/Runtime/allocheap.cpp @@ -11,14 +11,11 @@ #include "slist.h" #include "holder.h" #include "Crst.h" -#include "Range.h" #include "allocheap.h" #include "CommonMacros.inl" #include "slist.inl" -using namespace rh::util; - //------------------------------------------------------------------------------------------------- AllocHeap::AllocHeap() : m_blockList(), @@ -91,7 +88,7 @@ uint8_t * AllocHeap::_Alloc( ) { ASSERT((alignment & (alignment - 1)) == 0); // Power of 2 only. - ASSERT((int32_t)alignment <= OS_PAGE_SIZE); // Can't handle this right now. + ASSERT(alignment <= OS_PAGE_SIZE); // Can't handle this right now. CrstHolder lock(&m_lock); @@ -124,24 +121,9 @@ uint8_t * AllocHeap::AllocAligned( return _Alloc(cbMem, alignment); } -//------------------------------------------------------------------------------------------------- -bool AllocHeap::Contains(void* pvMem, uintptr_t cbMem) -{ - MemRange range(pvMem, cbMem); - for (BlockList::Iterator it = m_blockList.Begin(); it != m_blockList.End(); ++it) - { - if (it->Contains(range)) - { - return true; - } - } - return false; -} - //------------------------------------------------------------------------------------------------- bool AllocHeap::_UpdateMemPtrs(uint8_t* pNextFree, uint8_t* pFreeCommitEnd, uint8_t* pFreeReserveEnd) { - ASSERT(MemRange(pNextFree, pFreeReserveEnd).Contains(MemRange(pNextFree, pFreeCommitEnd))); ASSERT(ALIGN_DOWN(pFreeCommitEnd, OS_PAGE_SIZE) == pFreeCommitEnd); ASSERT(ALIGN_DOWN(pFreeReserveEnd, OS_PAGE_SIZE) == pFreeReserveEnd); diff --git a/src/coreclr/nativeaot/Runtime/allocheap.h b/src/coreclr/nativeaot/Runtime/allocheap.h index 6bb8c9cfe699aa..7da47eda6e4130 100644 --- a/src/coreclr/nativeaot/Runtime/allocheap.h +++ b/src/coreclr/nativeaot/Runtime/allocheap.h @@ -27,10 +27,6 @@ class AllocHeap uint8_t * AllocAligned(uintptr_t cbMem, uintptr_t alignment); - // Returns true if this AllocHeap owns the memory range [pvMem, pvMem+cbMem) - bool Contains(void * pvMem, - uintptr_t cbMem); - private: // Allocation Helpers uint8_t* _Alloc(uintptr_t cbMem, uintptr_t alignment); @@ -43,20 +39,18 @@ class AllocHeap bool _UpdateMemPtrs(uint8_t* pNextFree, uint8_t* pFreeCommitEnd); bool _UpdateMemPtrs(uint8_t* pNextFree); - typedef rh::util::MemRange Block; - typedef DPTR(Block) PTR_Block; - struct BlockListElem : public Block + struct BlockListElem { - BlockListElem(Block const & block) - : Block(block) - {} - BlockListElem(uint8_t * pbMem, uintptr_t cbMem) - : Block(pbMem, cbMem) + : m_pbMem(pbMem), m_cbMem(cbMem), m_pNext(NULL) {} - Block m_block; - PTR_Block m_pNext; + uint8_t* GetStart() const { return m_pbMem; } + uintptr_t GetLength() const { return m_cbMem; } + + uint8_t * m_pbMem; + uintptr_t m_cbMem; + BlockListElem* m_pNext; }; typedef SList BlockList; diff --git a/src/coreclr/nativeaot/Runtime/common.h b/src/coreclr/nativeaot/Runtime/common.h new file mode 100644 index 00000000000000..05944fef040d1a --- /dev/null +++ b/src/coreclr/nativeaot/Runtime/common.h @@ -0,0 +1,14 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#ifndef __NATIVEAOT_RUNTIME_COMMON_H__ +#define __NATIVEAOT_RUNTIME_COMMON_H__ + +// Include the GC common header +#include "../../gc/env/common.h" +#include +#include "../../gc/gcenv.inl" + +#include "CommonMacros.h" + +#endif // __NATIVEAOT_RUNTIME_COMMON_H__ diff --git a/src/coreclr/nativeaot/Runtime/disabledeventpipeinternal.cpp b/src/coreclr/nativeaot/Runtime/disabledeventpipeinternal.cpp index ecd0227c57e785..4000f50db26fa0 100644 --- a/src/coreclr/nativeaot/Runtime/disabledeventpipeinternal.cpp +++ b/src/coreclr/nativeaot/Runtime/disabledeventpipeinternal.cpp @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#include "common.h" #include "CommonTypes.h" #include "CommonMacros.h" #include "Pal.h" diff --git a/src/coreclr/nativeaot/Runtime/disabledruntimeeventinternal.cpp b/src/coreclr/nativeaot/Runtime/disabledruntimeeventinternal.cpp index 22206116098223..02af69dad5a0f3 100644 --- a/src/coreclr/nativeaot/Runtime/disabledruntimeeventinternal.cpp +++ b/src/coreclr/nativeaot/Runtime/disabledruntimeeventinternal.cpp @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#include "common.h" #include "CommonTypes.h" #include "CommonMacros.h" #include "Pal.h" diff --git a/src/coreclr/nativeaot/Runtime/unix/HardwareExceptions.cpp b/src/coreclr/nativeaot/Runtime/unix/HardwareExceptions.cpp index d62c1fc6414a11..4381073c0ce081 100644 --- a/src/coreclr/nativeaot/Runtime/unix/HardwareExceptions.cpp +++ b/src/coreclr/nativeaot/Runtime/unix/HardwareExceptions.cpp @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#include "common.h" #include "CommonTypes.h" #include "Pal.h" #include "PalLimitedContext.h" diff --git a/src/coreclr/nativeaot/Runtime/unix/PalInline.h b/src/coreclr/nativeaot/Runtime/unix/PalInline.h index 7d64c1e1cd568d..cb64c799cf2979 100644 --- a/src/coreclr/nativeaot/Runtime/unix/PalInline.h +++ b/src/coreclr/nativeaot/Runtime/unix/PalInline.h @@ -167,17 +167,3 @@ FORCEINLINE void PalSetLastError(int32_t error) { errno = error; } - -FORCEINLINE int32_t PalOsPageSize() -{ -#if defined(HOST_AMD64) - // all supported platforms use 4K pages on x64, including emulated environments - return 0x1000; -#elif defined(HOST_APPLE) - // OSX and related OS expose 16-kilobyte pages to the 64-bit userspace - // https://developer.apple.com/library/archive/documentation/Performance/Conceptual/ManagingMemory/Articles/AboutMemory.html - return 0x4000; -#else - return PalGetOsPageSize(); -#endif -} diff --git a/src/coreclr/nativeaot/Runtime/unix/PalUnix.cpp b/src/coreclr/nativeaot/Runtime/unix/PalUnix.cpp index 8cc290225297ab..25ee81b33fb876 100644 --- a/src/coreclr/nativeaot/Runtime/unix/PalUnix.cpp +++ b/src/coreclr/nativeaot/Runtime/unix/PalUnix.cpp @@ -477,24 +477,6 @@ void InitializeCurrentProcessCpuCount() g_RhNumberOfProcessors = count; } -static uint32_t g_RhPageSize; - -void InitializeOsPageSize() -{ - g_RhPageSize = (uint32_t)sysconf(_SC_PAGE_SIZE); - -#if defined(HOST_AMD64) - ASSERT(g_RhPageSize == 0x1000); -#elif defined(HOST_APPLE) - ASSERT(g_RhPageSize == 0x4000); -#endif -} - -uint32_t PalGetOsPageSize() -{ - return g_RhPageSize; -} - #if defined(TARGET_LINUX) || defined(TARGET_ANDROID) static pthread_key_t key; #endif @@ -532,8 +514,6 @@ bool PalInit() InitializeCurrentProcessCpuCount(); - InitializeOsPageSize(); - #ifdef FEATURE_HIJACK if (!InitializeSignalHandling()) { diff --git a/src/coreclr/nativeaot/Runtime/unix/UnixSignals.cpp b/src/coreclr/nativeaot/Runtime/unix/UnixSignals.cpp index 518b4bbf82f36a..1bede45c0873b4 100644 --- a/src/coreclr/nativeaot/Runtime/unix/UnixSignals.cpp +++ b/src/coreclr/nativeaot/Runtime/unix/UnixSignals.cpp @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#include "common.h" #include "CommonTypes.h" #include "PalLimitedContext.h" #include "CommonMacros.h" diff --git a/src/coreclr/nativeaot/Runtime/windows/PalInline.h b/src/coreclr/nativeaot/Runtime/windows/PalInline.h index d03d9399d01573..7bbc969b72c921 100644 --- a/src/coreclr/nativeaot/Runtime/windows/PalInline.h +++ b/src/coreclr/nativeaot/Runtime/windows/PalInline.h @@ -182,8 +182,3 @@ FORCEINLINE void PalYieldProcessor() #endif #define PalDebugBreak() __debugbreak() - -FORCEINLINE int32_t PalOsPageSize() -{ - return 0x1000; -} diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj b/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj index d7920c7be7249c..5d0e58fcb340a1 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj @@ -211,7 +211,6 @@ - diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Buffer.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Buffer.NativeAot.cs index 4ceecdf70f664b..893002b83229e3 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Buffer.NativeAot.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Buffer.NativeAot.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Diagnostics; using System.Runtime; using System.Runtime.CompilerServices; @@ -11,14 +10,6 @@ namespace System { public static partial class Buffer { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static unsafe void ZeroMemoryInternal(void* b, nuint byteLength) => - RuntimeImports.memset((byte*)b, 0, byteLength); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static unsafe void MemmoveInternal(byte* dest, byte* src, nuint len) => - RuntimeImports.memmove(dest, src, len); - [MethodImpl(MethodImplOptions.AggressiveInlining)] private static void BulkMoveWithWriteBarrierInternal(ref byte destination, ref byte source, nuint byteCount) => RuntimeImports.RhBulkMoveWithWriteBarrier(ref destination, ref source, byteCount); diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/Intrinsics/X86/X86Base.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/Intrinsics/X86/X86Base.NativeAot.cs deleted file mode 100644 index 247b02e0c0feb5..00000000000000 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/Intrinsics/X86/X86Base.NativeAot.cs +++ /dev/null @@ -1,10 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -namespace System.Runtime.Intrinsics.X86 -{ - public abstract partial class X86Base - { - private static unsafe void __cpuidex(int* cpuInfo, int functionId, int subFunctionId) => RuntimeImports.RhCpuIdEx(cpuInfo, functionId, subFunctionId); - } -} diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs index 4132a9abfde1ba..fdcec68e625633 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs @@ -426,9 +426,6 @@ internal static IntPtr RhHandleAllocCrossReference(object value, IntPtr context) private static partial int _RhYield(); internal static bool RhYield() => _RhYield() != 0; - [LibraryImport(RuntimeLibrary, EntryPoint = "RhFlushProcessWriteBuffers")] - internal static partial void RhFlushProcessWriteBuffers(); - #if !TARGET_UNIX // Wait for any object to be signalled, in a way that's compatible with the CLR's behavior in an STA. [LibraryImport(RuntimeLibrary)] @@ -879,19 +876,6 @@ internal static IntPtr RhGetModuleSection(TypeManagerHandle module, ReadyToRunSe [RuntimeImport(RuntimeLibrary, "modff")] internal static extern unsafe float modff(float x, float* intptr); - [LibraryImport(RuntimeImports.RuntimeLibrary)] - [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] - internal static unsafe partial void* memmove(byte* dmem, byte* smem, nuint size); - - [LibraryImport(RuntimeImports.RuntimeLibrary)] - [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] - internal static unsafe partial void* memset(byte* mem, int value, nuint size); - -#if TARGET_X86 || TARGET_AMD64 - [LibraryImport(RuntimeLibrary)] - internal static unsafe partial void RhCpuIdEx(int* cpuInfo, int functionId, int subFunctionId); -#endif - #if TARGET_UNIX [LibraryImport(RuntimeLibrary, StringMarshalling = StringMarshalling.Utf8)] internal static partial void RhSetCurrentThreadName(string name); diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Interlocked.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Interlocked.cs index 5ee8576357a1aa..c8a9c739831fcc 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Interlocked.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Interlocked.cs @@ -196,10 +196,5 @@ public static long Read(ref long location) return CompareExchange(ref location, 0, 0); } #endregion - - public static void MemoryBarrierProcessWide() - { - RuntimeImports.RhFlushProcessWriteBuffers(); - } } } diff --git a/src/coreclr/runtime/MiscNativeHelpers.cpp b/src/coreclr/runtime/MiscNativeHelpers.cpp new file mode 100644 index 00000000000000..df438c42127ac7 --- /dev/null +++ b/src/coreclr/runtime/MiscNativeHelpers.cpp @@ -0,0 +1,19 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include "common.h" +#include "MiscNativeHelpers.h" +#include +#include + +#if defined(TARGET_X86) || defined(TARGET_AMD64) +extern "C" void QCALLTYPE X86Base_CpuId(int cpuInfo[4], int functionId, int subFunctionId) +{ + __cpuidex(cpuInfo, functionId, subFunctionId); +} +#endif // defined(TARGET_X86) || defined(TARGET_AMD64) + +extern "C" void QCALLTYPE Interlocked_MemoryBarrierProcessWide() +{ + minipal_memory_barrier_process_wide(); +} diff --git a/src/coreclr/runtime/MiscNativeHelpers.h b/src/coreclr/runtime/MiscNativeHelpers.h new file mode 100644 index 00000000000000..bf18195492a26f --- /dev/null +++ b/src/coreclr/runtime/MiscNativeHelpers.h @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#ifndef __MISCNATIVEHELPERS_H__ +#define __MISCNATIVEHELPERS_H__ + +#if defined(TARGET_X86) || defined(TARGET_AMD64) +extern "C" void QCALLTYPE X86Base_CpuId(int cpuInfo[4], int functionId, int subFunctionId); +#endif // defined(TARGET_X86) || defined(TARGET_AMD64) + +extern "C" void QCALLTYPE Interlocked_MemoryBarrierProcessWide(); + +#endif // __MISCNATIVEHELPERS_H__ diff --git a/src/coreclr/vm/CMakeLists.txt b/src/coreclr/vm/CMakeLists.txt index bfb16752ffb08e..0e2d8959dd76c0 100644 --- a/src/coreclr/vm/CMakeLists.txt +++ b/src/coreclr/vm/CMakeLists.txt @@ -293,6 +293,7 @@ set(VM_SOURCES_WKS bundle.cpp ${RUNTIME_DIR}/CachedInterfaceDispatch.cpp CachedInterfaceDispatch_Coreclr.cpp + ${RUNTIME_DIR}/MiscNativeHelpers.cpp cachelinealloc.cpp callconvbuilder.cpp callhelpers.cpp diff --git a/src/coreclr/vm/comutilnative.cpp b/src/coreclr/vm/comutilnative.cpp index 9ee90557175863..27ea6fa75b4b6e 100644 --- a/src/coreclr/vm/comutilnative.cpp +++ b/src/coreclr/vm/comutilnative.cpp @@ -524,42 +524,6 @@ extern "C" void QCALLTYPE ExceptionNative_ThrowClassAccessException(MethodDesc* END_QCALL; } -extern "C" void QCALLTYPE Buffer_Clear(void *dst, size_t length) -{ - QCALL_CONTRACT; - -#if defined(HOST_X86) || defined(HOST_AMD64) - if (length > 0x100) - { - // memset ends up calling rep stosb if the hardware claims to support it efficiently. rep stosb is up to 2x slower - // on misaligned blocks. Workaround this issue by aligning the blocks passed to memset upfront. - - *(uint64_t*)dst = 0; - *((uint64_t*)dst + 1) = 0; - *((uint64_t*)dst + 2) = 0; - *((uint64_t*)dst + 3) = 0; - - void* end = (uint8_t*)dst + length; - *((uint64_t*)end - 1) = 0; - *((uint64_t*)end - 2) = 0; - *((uint64_t*)end - 3) = 0; - *((uint64_t*)end - 4) = 0; - - dst = ALIGN_UP((uint8_t*)dst + 1, 32); - length = ALIGN_DOWN((uint8_t*)end - 1, 32) - (uint8_t*)dst; - } -#endif - - memset(dst, 0, length); -} - -extern "C" void QCALLTYPE Buffer_MemMove(void *dst, void *src, size_t length) -{ - QCALL_CONTRACT; - - memmove(dst, src, length); -} - FCIMPL3(VOID, Buffer::BulkMoveWithWriteBarrier, void *dst, void *src, size_t byteCount) { FCALL_CONTRACT; @@ -1654,21 +1618,6 @@ extern "C" void QCALLTYPE Environment_FailFast(QCall::StackCrawlMarkHandle mark, END_QCALL; } -#if defined(TARGET_X86) || defined(TARGET_AMD64) - -extern "C" void QCALLTYPE X86BaseCpuId(int cpuInfo[4], int functionId, int subFunctionId) -{ - QCALL_CONTRACT; - - BEGIN_QCALL; - - __cpuidex(cpuInfo, functionId, subFunctionId); - - END_QCALL; -} - -#endif // defined(TARGET_X86) || defined(TARGET_AMD64) - // // ObjectNative // @@ -1838,13 +1787,6 @@ FCIMPLEND #include -extern "C" void QCALLTYPE Interlocked_MemoryBarrierProcessWide() -{ - QCALL_CONTRACT; - - minipal_memory_barrier_process_wide(); -} - static BOOL HasOverriddenMethod(MethodTable* mt, MethodTable* classMT, WORD methodSlot) { CONTRACTL{ diff --git a/src/coreclr/vm/comutilnative.h b/src/coreclr/vm/comutilnative.h index a7c520a3931c87..2d362b0fa0cc0c 100644 --- a/src/coreclr/vm/comutilnative.h +++ b/src/coreclr/vm/comutilnative.h @@ -82,9 +82,6 @@ class Buffer static FCDECL3(VOID, BulkMoveWithWriteBarrier, void *dst, void *src, size_t byteCount); }; -extern "C" void QCALLTYPE Buffer_Clear(void *dst, size_t length); -extern "C" void QCALLTYPE Buffer_MemMove(void *dst, void *src, size_t length); - const UINT MEM_PRESSURE_COUNT = 4; struct GCGenerationInfo @@ -256,10 +253,6 @@ extern "C" void QCALLTYPE Environment_FailFast(QCall::StackCrawlMarkHandle mark, // Returns the number of logical processors that can be used by managed code extern "C" INT32 QCALLTYPE Environment_GetProcessorCount(); -#if defined(TARGET_X86) || defined(TARGET_AMD64) -extern "C" void QCALLTYPE X86BaseCpuId(int cpuInfo[4], int functionId, int subFunctionId); -#endif // defined(TARGET_X86) || defined(TARGET_AMD64) - extern "C" void QCALLTYPE GetTypeLoadExceptionMessage(UINT32 resId, QCall::StringHandleOnStack retString); extern "C" void QCALLTYPE GetFileLoadExceptionMessage(UINT32 hr, QCall::StringHandleOnStack retString); @@ -289,8 +282,6 @@ class COMInterlocked static FCDECL2_IV(INT64, ExchangeAdd64, INT64 *location, INT64 value); }; -extern "C" void QCALLTYPE Interlocked_MemoryBarrierProcessWide(); - class MethodTableNative { public: static FCDECL1(UINT32, GetNumInstanceFieldBytes, MethodTable* mt); diff --git a/src/coreclr/vm/qcallentrypoints.cpp b/src/coreclr/vm/qcallentrypoints.cpp index e5e55314a6110d..2ffe42d10a1261 100644 --- a/src/coreclr/vm/qcallentrypoints.cpp +++ b/src/coreclr/vm/qcallentrypoints.cpp @@ -80,6 +80,8 @@ #include "interpexec.h" #endif // FEATURE_INTERPRETER +#include "MiscNativeHelpers.h" + static const Entry s_QCall[] = { DllImportEntry(ArgIterator_Init) @@ -313,8 +315,8 @@ static const Entry s_QCall[] = #endif // FEATURE_COMINTEROP DllImportEntry(Monitor_GetOrCreateLockObject) DllImportEntry(ClrConfig_GetConfigBoolValue) - DllImportEntry(Buffer_Clear) - DllImportEntry(Buffer_MemMove) + DllImportEntry(memset) + DllImportEntry(memmove) DllImportEntry(DependentHandle_InternalAllocWithGCTransition) DllImportEntry(DependentHandle_InternalFreeWithGCTransition) DllImportEntry(GCInterface_GetTotalAllocatedBytesPrecise) @@ -485,7 +487,7 @@ static const Entry s_QCall[] = DllImportEntry(SetEnvironmentVariableW) #endif #if defined(TARGET_X86) || defined(TARGET_AMD64) - DllImportEntry(X86BaseCpuId) + DllImportEntry(X86Base_CpuId) #endif DllImportEntry(StubHelpers_CreateCustomMarshaler) DllImportEntry(StubHelpers_ThrowInteropParamException) diff --git a/src/libraries/System.Private.CoreLib/src/System/Buffer.cs b/src/libraries/System.Private.CoreLib/src/System/Buffer.cs index 5b928276df64e5..49a90bce422fbd 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Buffer.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Buffer.cs @@ -124,27 +124,6 @@ public static unsafe void MemoryCopy(void* source, void* destination, ulong dest Memmove(ref *(byte*)destination, ref *(byte*)source, checked((nuint)sourceBytesToCopy)); } - // Non-inlinable wrapper around the QCall that avoids polluting the fast path - // with P/Invoke prolog/epilog. - [MethodImpl(MethodImplOptions.NoInlining)] - internal static unsafe void MemmoveInternal(ref byte dest, ref byte src, nuint len) - { - fixed (byte* pDest = &dest) - fixed (byte* pSrc = &src) - MemmoveInternal(pDest, pSrc, len); - } - - // Non-inlinable wrapper around the QCall that avoids polluting the fast path - // with P/Invoke prolog/epilog. - [MethodImpl(MethodImplOptions.NoInlining)] - internal static unsafe void ZeroMemoryInternal(ref byte b, nuint byteLength) - { - fixed (byte* bytePointer = &b) - { - ZeroMemoryInternal(bytePointer, byteLength); - } - } - #if !MONO // Mono BulkMoveWithWriteBarrier is in terms of elements (not bytes) and takes a type handle. [Intrinsic] diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/X86/X86Base.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/X86/X86Base.cs index 721bef9928ee1a..b73e804f70c36b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/X86/X86Base.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/X86/X86Base.cs @@ -97,10 +97,18 @@ internal X64() { } public static unsafe (int Eax, int Ebx, int Ecx, int Edx) CpuId(int functionId, int subFunctionId) { int* cpuInfo = stackalloc int[4]; - __cpuidex(cpuInfo, functionId, subFunctionId); + CpuId(cpuInfo, functionId, subFunctionId); return (cpuInfo[0], cpuInfo[1], cpuInfo[2], cpuInfo[3]); } +#if MONO + [MethodImplAttribute(MethodImplOptions.InternalCall)] + private static extern unsafe void CpuId(int* cpuInfo, int functionId, int subFunctionId); +#else + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "X86Base_CpuId")] + private static unsafe partial void CpuId(int* cpuInfo, int functionId, int subFunctionId); +#endif + /// /// unsigned _udiv64(unsigned __int64 dividend, unsigned divisor, unsigned* remainder) /// DIV reg/m32 diff --git a/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.ByteMemOps.cs b/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.ByteMemOps.cs index 1f24c8c0924cbe..d54a369eb18c34 100644 --- a/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.ByteMemOps.cs +++ b/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.ByteMemOps.cs @@ -239,9 +239,32 @@ internal static void Memmove(ref byte dest, ref byte src, nuint len) Debug.Assert(len > 0); _ = Unsafe.ReadUnaligned(ref dest); _ = Unsafe.ReadUnaligned(ref src); - Buffer.MemmoveInternal(ref dest, ref src, len); + MemmoveNative(ref dest, ref src, len); } + // Non-inlinable wrapper around the QCall that avoids polluting the fast path + // with P/Invoke prolog/epilog. + [MethodImpl(MethodImplOptions.NoInlining)] + private static unsafe void MemmoveNative(ref byte dest, ref byte src, nuint len) + { + fixed (byte* pDest = &dest) + fixed (byte* pSrc = &src) + { + memmove(pDest, pSrc, len); + } + } + +#if MONO + [MethodImpl(MethodImplOptions.InternalCall)] + private static unsafe extern void memmove(void* dest, void* src, nuint len); +#else +#pragma warning disable CS3016 // Arrays as attribute arguments is not CLS-compliant + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "memmove")] + [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] + private static unsafe partial void* memmove(void* dest, void* src, nuint len); +#pragma warning restore CS3016 +#endif + [Intrinsic] // Unrolled for small sizes public static void ClearWithoutReferences(ref byte dest, nuint len) { @@ -425,9 +448,46 @@ public static void ClearWithoutReferences(ref byte dest, nuint len) PInvoke: // Implicit nullchecks _ = Unsafe.ReadUnaligned(ref dest); - Buffer.ZeroMemoryInternal(ref dest, len); + ZeroMemoryNative(ref dest, len); } + // Non-inlinable wrapper around the QCall that avoids polluting the fast path + // with P/Invoke prolog/epilog. + [MethodImpl(MethodImplOptions.NoInlining)] + private static unsafe void ZeroMemoryNative(ref byte b, nuint byteLength) + { + fixed (byte* ptr = &b) + { + byte* adjustedPtr = ptr; +#if TARGET_X86 || TARGET_AMD64 + if (byteLength > 0x100) + { + // memset ends up calling rep stosb if the hardware claims to support it efficiently. rep stosb is up to 2x slower + // on misaligned blocks. Workaround this issue by aligning the blocks passed to memset upfront. + Unsafe.WriteUnaligned(ptr, default); + Unsafe.WriteUnaligned(ptr + byteLength - 16, default); + + byte* alignedEnd = (byte*)((nuint)(ptr + byteLength - 1) & ~(nuint)(16 - 1)); + + adjustedPtr = (byte*)(((nuint)ptr + 16) & ~(nuint)(16 - 1)); + byteLength = (nuint)(alignedEnd - adjustedPtr); + } +#endif + memset(adjustedPtr, 0, byteLength); + } + } + +#if MONO + [MethodImpl(MethodImplOptions.InternalCall)] + private static unsafe extern void memset(void* dest, int value, nuint len); +#else +#pragma warning disable CS3016 // Arrays as attribute arguments is not CLS-compliant + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "memset")] + [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] + private static unsafe partial void* memset(void* dest, int value, nuint len); +#pragma warning restore CS3016 +#endif + internal static void Fill(ref byte dest, byte value, nuint len) { if (!Vector.IsHardwareAccelerated) diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Interlocked.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Interlocked.cs index cc33770071fe77..dfa92e8b9381e1 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Interlocked.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Interlocked.cs @@ -865,5 +865,15 @@ ref Unsafe.As(ref location1), [Intrinsic] public static void MemoryBarrier() => MemoryBarrier(); #endregion + +#if !MONO + #region MemoryBarrierProcessWide + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "Interlocked_MemoryBarrierProcessWide")] + private static partial void _MemoryBarrierProcessWide(); + + /// Provides a process-wide memory barrier that ensures that reads and writes from any CPU cannot move across the barrier. + public static void MemoryBarrierProcessWide() => _MemoryBarrierProcessWide(); + #endregion +#endif } } diff --git a/src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj b/src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj index e379ab5a819f34..69f06966ce1b4c 100644 --- a/src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj +++ b/src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj @@ -248,7 +248,6 @@ - diff --git a/src/mono/System.Private.CoreLib/src/System/Buffer.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Buffer.Mono.cs index 4139326cc1a370..b93d80de4b5eca 100644 --- a/src/mono/System.Private.CoreLib/src/System/Buffer.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Buffer.Mono.cs @@ -7,12 +7,6 @@ namespace System { public partial class Buffer { - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern unsafe void ZeroMemoryInternal(void* b, nuint byteLength); - - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern unsafe void MemmoveInternal(byte* dest, byte* src, nuint len); - [MethodImpl(MethodImplOptions.InternalCall)] private static extern void BulkMoveWithWriteBarrier(ref byte dmem, ref byte smem, nuint len, IntPtr type_handle); diff --git a/src/mono/System.Private.CoreLib/src/System/Runtime/Intrinsics/X86/X86Base.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Runtime/Intrinsics/X86/X86Base.Mono.cs deleted file mode 100644 index f29203516cc374..00000000000000 --- a/src/mono/System.Private.CoreLib/src/System/Runtime/Intrinsics/X86/X86Base.Mono.cs +++ /dev/null @@ -1,13 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Runtime.CompilerServices; - -namespace System.Runtime.Intrinsics.X86 -{ - public abstract partial class X86Base - { - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private static extern unsafe void __cpuidex(int* cpuInfo, int functionId, int subFunctionId); - } -} diff --git a/src/mono/mono/metadata/icall-decl.h b/src/mono/mono/metadata/icall-decl.h index 387282931aa5a1..475e219bf9bc13 100644 --- a/src/mono/mono/metadata/icall-decl.h +++ b/src/mono/mono/metadata/icall-decl.h @@ -135,9 +135,9 @@ ICALL_EXPORT void ves_icall_System_GC_RemovePressure (guint64); ICALL_EXPORT void ves_icall_System_GC_WaitForPendingFinalizers (void); ICALL_EXPORT void ves_icall_System_GC_GetGCMemoryInfo (gint64*, gint64*, gint64*, gint64*, gint64*, gint64*); -ICALL_EXPORT void ves_icall_System_Runtime_RuntimeImports_Memmove (guint8*, guint8*, size_t); +ICALL_EXPORT void ves_icall_System_SpanHelpers_memmove (void*, void*, size_t); ICALL_EXPORT void ves_icall_System_Buffer_BulkMoveWithWriteBarrier (guint8 *, guint8 *, size_t, MonoType *); -ICALL_EXPORT void ves_icall_System_Runtime_RuntimeImports_ZeroMemory (guint8*, size_t); +ICALL_EXPORT void ves_icall_System_SpanHelpers_memset (void*, gint32, size_t); ICALL_EXPORT void ves_icall_System_Array_InternalCreate (MonoArray *volatile* result, MonoType* type, gint32 rank, gint32* pLengths, gint32* pLowerBounds); ICALL_EXPORT MonoBoolean ves_icall_System_Array_CanChangePrimitive (MonoObjectHandleOnStack ref_src_type_handle, MonoObjectHandleOnStack ref_dst_type_handle, MonoBoolean reliable); @@ -182,7 +182,7 @@ ICALL_EXPORT char* ves_icall_Mono_SafeStringMarshal_StringToUtf8 (MonoString *vo ICALL_EXPORT MonoType* ves_icall_Mono_RuntimeClassHandle_GetTypeFromClass (MonoClass *klass); #ifdef TARGET_AMD64 -ICALL_EXPORT void ves_icall_System_Runtime_Intrinsics_X86_X86Base___cpuidex (int abcd[4], int function_id, int subfunction_id); +ICALL_EXPORT void ves_icall_System_Runtime_Intrinsics_X86_X86Base_CpuId (int abcd[4], int function_id, int subfunction_id); #endif ICALL_EXPORT void ves_icall_AssemblyExtensions_ApplyUpdate (MonoAssembly *assm, gconstpointer dmeta_bytes, int32_t dmeta_len, gconstpointer dil_bytes, int32_t dil_len, gconstpointer dpdb_bytes, int32_t dpdb_len); diff --git a/src/mono/mono/metadata/icall-def.h b/src/mono/mono/metadata/icall-def.h index fd135f5046fcf6..0158888234e080 100644 --- a/src/mono/mono/metadata/icall-def.h +++ b/src/mono/mono/metadata/icall-def.h @@ -140,8 +140,6 @@ HANDLES(ARRAY_14, "SetValueRelaxedImpl", ves_icall_System_Array_SetValueRelaxed ICALL_TYPE(BUFFER, "System.Buffer", BUFFER_0) NOHANDLES(ICALL(BUFFER_0, "BulkMoveWithWriteBarrier", ves_icall_System_Buffer_BulkMoveWithWriteBarrier)) -NOHANDLES(ICALL(BUFFER_2, "MemmoveInternal", ves_icall_System_Runtime_RuntimeImports_Memmove)) -NOHANDLES(ICALL(BUFFER_3, "ZeroMemoryInternal", ves_icall_System_Runtime_RuntimeImports_ZeroMemory)) ICALL_TYPE(DELEGATE, "System.Delegate", DELEGATE_1) HANDLES(DELEGATE_1, "AllocDelegateLike_internal", ves_icall_System_Delegate_AllocDelegateLike_internal, MonoMulticastDelegate, 1, (MonoDelegate)) @@ -467,7 +465,7 @@ HANDLES(NATIVEL_4, "LoadFromPath", ves_icall_System_Runtime_InteropServices_Nati #if defined(TARGET_AMD64) ICALL_TYPE(X86BASE, "System.Runtime.Intrinsics.X86.X86Base", X86BASE_1) -NOHANDLES(ICALL(X86BASE_1, "__cpuidex", ves_icall_System_Runtime_Intrinsics_X86_X86Base___cpuidex)) +NOHANDLES(ICALL(X86BASE_1, "CpuId", ves_icall_System_Runtime_Intrinsics_X86_X86Base_CpuId)) #endif ICALL_TYPE(ALC, "System.Runtime.Loader.AssemblyLoadContext", ALC_5) @@ -538,6 +536,10 @@ HANDLES(RTH_17a, "internal_from_name", ves_icall_System_RuntimeTypeHandle_intern HANDLES(RTH_17b, "is_subclass_of", ves_icall_RuntimeTypeHandle_is_subclass_of, MonoBoolean, 2, (MonoQCallTypeHandle, MonoQCallTypeHandle)) HANDLES(RTH_18, "type_is_assignable_from", ves_icall_RuntimeTypeHandle_type_is_assignable_from, MonoBoolean, 2, (MonoQCallTypeHandle, MonoQCallTypeHandle)) +ICALL_TYPE(SPANHELPERS, "System.SpanHelpers", SPANHELPERS_0) +NOHANDLES(ICALL(SPANHELPERS_0, "memmove", ves_icall_System_SpanHelpers_memmove)) +NOHANDLES(ICALL(SPANHELPERS_1, "memset", ves_icall_System_SpanHelpers_memset)) + ICALL_TYPE(STRING, "System.String", STRING_1) NOHANDLES(ICALL(STRING_1, ".ctor(System.ReadOnlySpan`1)", ves_icall_System_String_ctor_RedirectToCreateString)) NOHANDLES(ICALL(STRING_1a, ".ctor(char*)", ves_icall_System_String_ctor_RedirectToCreateString)) diff --git a/src/mono/mono/metadata/icall.c b/src/mono/mono/metadata/icall.c index 182ede96e90dc5..5c8a35a367ca9c 100644 --- a/src/mono/mono/metadata/icall.c +++ b/src/mono/mono/metadata/icall.c @@ -948,7 +948,7 @@ ves_icall_System_Array_SetGenericValue_icall (MonoObjectHandleOnStack *arr_handl } void -ves_icall_System_Runtime_RuntimeImports_Memmove (guint8 *destination, guint8 *source, size_t byte_count) +ves_icall_System_SpanHelpers_memmove (void *destination, void *source, size_t byte_count) { mono_gc_memmove_atomic (destination, source, byte_count); } @@ -966,9 +966,9 @@ ves_icall_System_Buffer_BulkMoveWithWriteBarrier (guint8 *destination, guint8 *s } void -ves_icall_System_Runtime_RuntimeImports_ZeroMemory (guint8 *p, size_t byte_length) +ves_icall_System_SpanHelpers_memset (void *p, gint32 value, size_t byte_length) { - memset (p, 0, byte_length); + memset (p, value, byte_length); } gpointer diff --git a/src/mono/mono/mini/simd-intrinsics.c b/src/mono/mono/mini/simd-intrinsics.c index ebe0637605fe5a..66ba056611ece4 100644 --- a/src/mono/mono/mini/simd-intrinsics.c +++ b/src/mono/mono/mini/simd-intrinsics.c @@ -7135,7 +7135,7 @@ mono_simd_unsupported_aggressive_inline_intrinsic_type (MonoCompile *cfg, MonoMe #if defined(TARGET_AMD64) void -ves_icall_System_Runtime_Intrinsics_X86_X86Base___cpuidex (int abcd[4], int function_id, int subfunction_id) +ves_icall_System_Runtime_Intrinsics_X86_X86Base_CpuId (int abcd[4], int function_id, int subfunction_id) { #ifndef MONO_CROSS_COMPILE mono_hwcap_x86_call_cpuidex (function_id, subfunction_id,