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,