Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
c342e64
Re-enable, with a dmb, and change the stub examination logic to use a…
davidwrighton May 16, 2025
226cc59
Add the new logic for handling the disasm comparison in the DAC to th…
davidwrighton May 17, 2025
5388a3d
Merge branch 'main' of github.com:dotnet/runtime into enable_FEATURE_…
davidwrighton May 19, 2025
36e0ec1
More updates to latest
davidwrighton May 19, 2025
279a458
Add cDAC support
davidwrighton May 20, 2025
eca7820
Merge branch 'main' of github.com:dotnet/runtime into enable_FEATURE_…
davidwrighton May 20, 2025
3233cd5
Adjust to having the stub templates back
davidwrighton May 20, 2025
8557dea
Merge branch 'main' into enable_FEATURE_STUBPRECODE_DYNAMIC_HELPERS_a…
davidwrighton May 21, 2025
6c07b89
Update src/coreclr/vm/precode.h
davidwrighton May 21, 2025
43e29b9
Update docs/design/datacontracts/PrecodeStubs.md
davidwrighton May 21, 2025
721be9e
Apply suggestions from code review
davidwrighton May 21, 2025
fca72ac
Issue issue around code copilot found
davidwrighton May 21, 2025
051e071
Changes to make StubPrecode have the write barrier on the writer side
davidwrighton May 22, 2025
59324fd
Add memory ordering protection for FixupPrecode
davidwrighton May 23, 2025
9f86bc1
Merge branch 'main' of github.com:dotnet/runtime into enable_FEATURE_…
davidwrighton May 23, 2025
870e7cf
Fix build on various platforms, and reduce incorrect assert
davidwrighton May 27, 2025
bc9bb86
Fix assertions
davidwrighton May 27, 2025
07df9b1
Fix build break
davidwrighton May 29, 2025
7421c04
Fix copy/paste thinko
davidwrighton May 29, 2025
f2c941d
Fix WASM build
davidwrighton May 29, 2025
2af00ef
Merge branch 'main' into enable_FEATURE_STUBPRECODE_DYNAMIC_HELPERS_a…
davidwrighton Jun 2, 2025
54b3501
Update src/coreclr/vm/riscv64/thunktemplates.S
davidwrighton Jun 11, 2025
e15440c
fix test run
max-charlamb Jun 27, 2025
fc1b028
add to PlatformManifestFileEntry
max-charlamb Jun 27, 2025
98ef4a3
typo
max-charlamb Jun 27, 2025
a42a414
Merge remote-tracking branch 'origin/main' into cdac-fail-fast
max-charlamb Jun 28, 2025
cd85e3e
fix bug in AMD64Unwinder
max-charlamb Jun 28, 2025
0f7a702
exactly match DAC behavior for initial context flags
max-charlamb Jun 28, 2025
4d59a8e
Merge branch 'main' of https://github.com/dotnet/runtime into enable_…
davidwrighton Jul 1, 2025
563ca30
Merge branch 'main' into enable_FEATURE_STUBPRECODE_DYNAMIC_HELPERS_a…
davidwrighton Jul 1, 2025
3cfe122
Update relative offsets for Loongarch and Riscv
davidwrighton Jul 2, 2025
fda796a
Use alternative barrier approach on Arm64
davidwrighton Jul 2, 2025
306ae1b
Merge branch 'enable_FEATURE_STUBPRECODE_DYNAMIC_HELPERS_again' of ht…
davidwrighton Jul 2, 2025
887c885
Try slight variation
davidwrighton Jul 2, 2025
1a8c6b0
Go back to a simple dmb. Seems to have the same perf as a stlr,ldar p…
davidwrighton Jul 2, 2025
a207c9c
Use FlushInstructionCache to protect stub reads instead of using a ba…
davidwrighton Jul 3, 2025
9c17ab8
Remove hallucinations
davidwrighton Jul 3, 2025
71b3876
Missed removing one dmb
davidwrighton Jul 4, 2025
e96076e
remove from sharedFramework and add to externals
max-charlamb Jul 7, 2025
ddb0094
properly release unused pClrDataAccess on failure
max-charlamb Jul 7, 2025
676321b
Merge branch 'cdac-fail-fast' into enable_FEATURE_STUBPRECODE_DYNAMIC…
max-charlamb Jul 7, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 84 additions & 8 deletions docs/design/datacontracts/PrecodeStubs.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,32 @@ This contract provides support for examining [precode](../coreclr/botr/method-de
TargetPointer GetMethodDescFromStubAddress(TargetCodePointer entryPoint);
```

## Version 1 and 2
## Version 1, 2, and 3

Data descriptors used:
| Data Descriptor Name | Field | Meaning |
| --- | --- | --- |
| PrecodeMachineDescriptor | OffsetOfPrecodeType | See `ReadPrecodeType` |
| PrecodeMachineDescriptor | ShiftOfPrecodeType | See `ReadPrecodeType` |
| PrecodeMachineDescriptor | ReadWidthOfPrecodeType | See `ReadPrecodeType` |
| PrecodeMachineDescriptor | OffsetOfPrecodeType | See `ReadPrecodeType` (Version 1 and 2 only) |
| PrecodeMachineDescriptor | ShiftOfPrecodeType | See `ReadPrecodeType` (Version 1 and 2 only) |
| PrecodeMachineDescriptor | ReadWidthOfPrecodeType | See `ReadPrecodeType` (Version 1 and 2 only) |
| PrecodeMachineDescriptor | StubCodePageSize | Size of a precode code page (in bytes) |
| PrecodeMachineDescriptor | CodePointerToInstrPointerMask | mask to apply to code pointers to get an address (see arm32 note)
| PrecodeMachineDescriptor | StubPrecodeType | precode sort byte for stub precodes |
| PrecodeMachineDescriptor | HasPInvokeImportPrecode | 1 if platform supports PInvoke precode stubs |
| PrecodeMachineDescriptor | PInvokeImportPrecodeType| precode sort byte for PInvoke precode stubs, if supported |
| PrecodeMachineDescriptor | PInvokeImportPrecodeType | precode sort byte for PInvoke precode stubs, if supported |
| PrecodeMachineDescriptor | HasFixupPrecode | 1 if platform supports fixup precode stubs |
| PrecodeMachineDescriptor | FixupPrecodeType| precode sort byte for fixup precode stubs, if supported |
| PrecodeMachineDescriptor | FixupPrecodeType | precode sort byte for fixup precode stubs, if supported |
| PrecodeMachineDescriptor | ThisPointerRetBufPrecodeType | precode sort byte for this pointer ret buf precodes |
| PrecodeMachineDescriptor | FixupStubPrecodeSize | Byte size of `FixupBytes` and `FixupIgnoredBytes` (Version 3 only) |
| PrecodeMachineDescriptor | FixupBytes | Assembly code of a FixupStub (Version 3 only) |
| PrecodeMachineDescriptor | FixupIgnoredBytes | Bytes to ignore of when comparing `FixupBytes` to an actual block of memory in the target process. (Version 3 only) |
| PrecodeMachineDescriptor | StubPrecodeSize | Byte size of `StubBytes` and `StubIgnoredBytes` (Version 3 only) |
| PrecodeMachineDescriptor | StubBytes | Assembly code of a StubPrecode (Version 3 only) |
| PrecodeMachineDescriptor | StubIgnoredBytes | Bytes to ignore of when comparing `StubBytes` to an actual block of memory in the target process. (Version 3 only) |
| PrecodeMachineDescriptor | FixupCodeOffset | Offset of second entrypoint into a `FixupStub` (Present in data for Version 3 and above only.) |
| PrecodeMachineDescriptor | InterpreterPrecodeType | precode sort byte for the entrypoint into the interpreter (Version 3 only) |
| PrecodeMachineDescriptor | UMEntryPrecodeType | precode sort byte for the entrypoint into the UMEntry thunk (Version 3 only) |
| PrecodeMachineDescriptor | DynamicHelperPrecodeType | precode sort byte for the entrypoint into a dynamic helper (Version 3 only) |
| StubPrecodeData | MethodDesc | pointer to the MethodDesc associated with this stub precode (Version 1 only) |
| StubPrecodeData | SecretParam | pointer to the MethodDesc associated with this stub precode or a second stub data pointer for other types (Version 2 only) |
| StubPrecodeData | Type | precise sort of stub precode |
Expand All @@ -44,12 +54,75 @@ Contracts used:
| --- |
| `PlatformMetadata` |

### Determining the precode type
### Determining the precode type (Version 3)
``` csharp
private bool ReadBytesAndCompare(TargetPointer instrAddress, byte[] expectedBytePattern, byte[] bytesToIgnore)
{
byte[] localCopy = new byte[expectedBytePattern.Length];
for (int i = 0; i < expectedBytePattern.Length; i++)
{
if (bytesToIgnore[i] == 0)
{
byte targetBytePattern = _target.Read<byte>(instrAddress + i);
if (expectedBytePattern[i] != targetBytePattern)
{
return false;
}
}
}

return true;
}
private KnownPrecodeType? TryGetKnownPrecodeType(TargetPointer instrAddress)
{
KnownPrecodeType? basicPrecodeType = default;
if (ReadBytesAndCompare(instrAddress, MachineDescriptor.StubBytes, MachineDescriptor.StubIgnoredBytes))
{
// get the actual type from the StubPrecodeData
Data.StubPrecodeData stubPrecodeData = GetStubPrecodeData(instrAddress);
byte exactPrecodeType = stubPrecodeData.Type;
if (exactPrecodeType == 0)
return null;

if (exactPrecodeType == MachineDescriptor.StubPrecodeType)
{
return KnownPrecodeType.Stub;
}
else if (MachineDescriptor.PInvokeImportPrecodeType is byte compareByte1 && compareByte1 == exactPrecodeType)
{
return KnownPrecodeType.PInvokeImport;
}
else if (MachineDescriptor.ThisPointerRetBufPrecodeType is byte compareByte2 && compareByte2 == exactPrecodeType)
{
return KnownPrecodeType.ThisPtrRetBuf;
}
else if (MachineDescriptor.UMEntryPrecodeType is byte compareByte3 && compareByte3 == exactPrecodeType)
{
return KnownPrecodeType.UMEntry;
}
else if (MachineDescriptor.InterpreterPrecodeType is byte compareByte4 && compareByte4 == exactPrecodeType)
{
return KnownPrecodeType.Interpreter;
}
else if (MachineDescriptor.DynamicHelperPrecodeType is byte compareByte5 && compareByte5 == exactPrecodeType)
{
return KnownPrecodeType.DynamicHelper;
}
}
else if (ReadBytesAndCompare(instrAddress, MachineDescriptor.FixupBytes, MachineDescriptor.FixupIgnoredBytes))
{
return KnownPrecodeType.Fixup;
}
return null;
}
```

### Determining the precode type (Version 1 and 2)

An initial approximation of the precode type relies on a particular pattern at a known offset from the precode entrypoint.
The precode type is expected to be encoded as an immediate. On some platforms the value is spread over multiple instruction bytes and may need to be right-shifted.

```
```csharp
private byte ReadPrecodeType(TargetPointer instrPointer)
{
if (MachineDescriptor.ReadWidthOfPrecodeType == 1)
Expand Down Expand Up @@ -124,6 +197,9 @@ After the initial precode type is determined, for stub precodes a refined precod
PInvokeImport, // also known as NDirectImport in the runtime
Fixup,
ThisPtrRetBuf,
UMEntry,
DynamicHelper,
Interpreter
}

internal abstract class ValidPrecode
Expand Down
4 changes: 4 additions & 0 deletions src/coreclr/clrdefinitions.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,10 @@ if (FEATURE_STUBPRECODE_DYNAMIC_HELPERS)
add_definitions(-DFEATURE_STUBPRECODE_DYNAMIC_HELPERS)
endif()

if (FEATURE_CORECLR_FLUSH_INSTRUCTION_CACHE_TO_PROTECT_STUB_READS)
add_definitions(-DFEATURE_CORECLR_FLUSH_INSTRUCTION_CACHE_TO_PROTECT_STUB_READS)
endif()

if (CLR_CMAKE_TARGET_APPLE)
# Re-enable when dbgshim containing https://github.com/dotnet/diagnostics/pull/5487 is generally available
# add_definitions(-DFEATURE_MAP_THUNKS_FROM_IMAGE)
Expand Down
9 changes: 9 additions & 0 deletions src/coreclr/clrfeatures.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ if (CLR_CMAKE_TARGET_WIN32)
set(FEATURE_TYPEEQUIVALENCE 1)
endif(CLR_CMAKE_TARGET_WIN32)

if (CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_ARM64)
set(FEATURE_STUBPRECODE_DYNAMIC_HELPERS 1)
endif()

if (CLR_CMAKE_TARGET_MACCATALYST OR CLR_CMAKE_TARGET_IOS OR CLR_CMAKE_TARGET_TVOS OR CLR_CMAKE_TARGET_ARCH_WASM)
set(FEATURE_CORECLR_CACHED_INTERFACE_DISPATCH 1)
Expand All @@ -81,6 +84,12 @@ else()
set(FEATURE_CORECLR_VIRTUAL_STUB_DISPATCH 1)
endif()

# We use a flush instruction cache to protect reads from the StubPrecodeData/CallCountingStub structures in the stubs.
# This is needed because the StubPrecodeData structure is initialized after the stub code is written, and we need to ensure that
# the reads in the stub happen after the writes to the StubPrecodeData structure. We could do this with a barrier instruction in the stub,
# but that would be more expensive.
set(FEATURE_CORECLR_FLUSH_INSTRUCTION_CACHE_TO_PROTECT_STUB_READS 1)

if (CLR_CMAKE_HOST_UNIX AND CLR_CMAKE_HOST_ARCH_AMD64)
# Allow 16 byte compare-exchange (cmpxchg16b)
add_compile_options($<${FEATURE_CORECLR_CACHED_INTERFACE_DISPATCH}:-mcx16>)
Expand Down
8 changes: 8 additions & 0 deletions src/coreclr/debug/daccess/daccess.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7045,6 +7045,14 @@ CLRDataCreateInstance(REFIID iid,
// Release the AddRef from the QI.
pClrDataAccess->Release();
}

if (cdacInterface == nullptr)
{
// If we requested to use the cDAC, but failed to create the cDAC interface, return failure
// Release the ClrDataAccess instance we created
pClrDataAccess->Release();
return E_FAIL;
}
}
}
#endif
Expand Down
2 changes: 2 additions & 0 deletions src/coreclr/debug/daccess/enummem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
#include <interoplibabi.h>
#endif // FEATURE_COMWRAPPERS

#include "cdacplatformmetadata.hpp"

extern HRESULT GetDacTableAddress(ICorDebugDataTarget* dataTarget, ULONG64 baseAddress, PULONG64 dacTableAddress);

#if defined(DAC_MEASURE_PERF)
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/debug/ee/dactable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "../../vm/common.h"
#include "../../vm/gcenv.h"
#include "../../vm/ecall.h"
#include "../../vm/cdacplatformmetadata.hpp"

#ifdef DEBUGGING_SUPPORTED

Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/debug/runtimeinfo/contracts.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"Loader": 1,
"Object": 1,
"PlatformMetadata": 1,
"PrecodeStubs": 2,
"PrecodeStubs": 3,
"ReJIT": 1,
"RuntimeInfo": 1,
"RuntimeTypeSystem": 1,
Expand Down
25 changes: 20 additions & 5 deletions src/coreclr/debug/runtimeinfo/datadescriptor.h
Original file line number Diff line number Diff line change
Expand Up @@ -523,20 +523,35 @@ CDAC_TYPE_END(MethodDescVersioningState)

CDAC_TYPE_BEGIN(PrecodeMachineDescriptor)
CDAC_TYPE_INDETERMINATE(PrecodeMachineDescriptor)
CDAC_TYPE_FIELD(PrecodeMachineDescriptor, /*uint8*/, ReadWidthOfPrecodeType, offsetof(PrecodeMachineDescriptor, ReadWidthOfPrecodeType))
CDAC_TYPE_FIELD(PrecodeMachineDescriptor, /*uint8*/, ShiftOfPrecodeType, offsetof(PrecodeMachineDescriptor, ShiftOfPrecodeType))
CDAC_TYPE_FIELD(PrecodeMachineDescriptor, /*uint8*/, OffsetOfPrecodeType, offsetof(PrecodeMachineDescriptor, OffsetOfPrecodeType))
CDAC_TYPE_FIELD(PrecodeMachineDescriptor, /*uint8*/, InvalidPrecodeType, offsetof(PrecodeMachineDescriptor, InvalidPrecodeType))
CDAC_TYPE_FIELD(PrecodeMachineDescriptor, /*uint8*/, StubPrecodeType, offsetof(PrecodeMachineDescriptor, StubPrecodeType))
#ifdef HAS_NDIRECT_IMPORT_PRECODE
CDAC_TYPE_FIELD(PrecodeMachineDescriptor, /*uint8*/, PInvokeImportPrecodeType, offsetof(PrecodeMachineDescriptor, PInvokeImportPrecodeType))
#endif

#ifdef HAS_FIXUP_PRECODE
CDAC_TYPE_FIELD(PrecodeMachineDescriptor, /*uint8*/, FixupPrecodeType, offsetof(PrecodeMachineDescriptor, FixupPrecodeType))
#endif
CDAC_TYPE_FIELD(PrecodeMachineDescriptor, /*uint8*/, FixupCodeOffset, offsetof(PrecodeMachineDescriptor, FixupCodeOffset))
CDAC_TYPE_FIELD(PrecodeMachineDescriptor, /*uint8*/, FixupStubPrecodeSize, offsetof(PrecodeMachineDescriptor, FixupStubPrecodeSize))
CDAC_TYPE_FIELD(PrecodeMachineDescriptor, /*byte[]*/, FixupBytes, offsetof(PrecodeMachineDescriptor, FixupBytes))
CDAC_TYPE_FIELD(PrecodeMachineDescriptor, /*byte[]*/, FixupIgnoredBytes, offsetof(PrecodeMachineDescriptor, FixupIgnoredBytes))
#endif // HAS_FIXUP_PRECODE

CDAC_TYPE_FIELD(PrecodeMachineDescriptor, /*uint8*/, StubPrecodeSize, offsetof(PrecodeMachineDescriptor, StubPrecodeSize))
CDAC_TYPE_FIELD(PrecodeMachineDescriptor, /*uint8*/, StubPrecodeType, offsetof(PrecodeMachineDescriptor, StubPrecodeType))

CDAC_TYPE_FIELD(PrecodeMachineDescriptor, /*byte[]*/, StubBytes, offsetof(PrecodeMachineDescriptor, StubBytes))
CDAC_TYPE_FIELD(PrecodeMachineDescriptor, /*byte[]*/, StubIgnoredBytes, offsetof(PrecodeMachineDescriptor, StubIgnoredBytes))

#ifdef HAS_THISPTR_RETBUF_PRECODE
CDAC_TYPE_FIELD(PrecodeMachineDescriptor, /*uint8*/, ThisPointerRetBufPrecodeType, offsetof(PrecodeMachineDescriptor, ThisPointerRetBufPrecodeType))
#endif
#ifdef FEATURE_INTERPRETER
CDAC_TYPE_FIELD(PrecodeMachineDescriptor, /*uint8*/, InterpreterPrecodeType, offsetof(PrecodeMachineDescriptor, InterpreterPrecodeType))
#endif
#ifdef FEATURE_STUBPRECODE_DYNAMIC_HELPERS
CDAC_TYPE_FIELD(PrecodeMachineDescriptor, /*uint8*/, DynamicHelperPrecodeType, offsetof(PrecodeMachineDescriptor, DynamicHelperPrecodeType))
#endif
CDAC_TYPE_FIELD(PrecodeMachineDescriptor, /*uint8*/, UMEntryPrecodeType, offsetof(PrecodeMachineDescriptor, UMEntryPrecodeType))
CDAC_TYPE_FIELD(PrecodeMachineDescriptor, /*uint32*/, StubCodePageSize, offsetof(PrecodeMachineDescriptor, StubCodePageSize))
CDAC_TYPE_END(PrecodeMachineDescriptor)

Expand Down
2 changes: 2 additions & 0 deletions src/coreclr/inc/dacvars.h
Original file line number Diff line number Diff line change
Expand Up @@ -236,5 +236,7 @@ DEFINE_DACVAR(bool, dac__g_metadataUpdatesApplied, ::g_metadataUpdatesApplied)

DEFINE_DACVAR(PTR_WSTR, dac__g_EntryAssemblyPath, ::g_EntryAssemblyPath)

DEFINE_DACVAR(CDacPlatformMetadata, dac__g_cdacPlatformMetadata, ::g_cdacPlatformMetadata)

#undef DEFINE_DACVAR
#undef DEFINE_DACVAR_NO_DUMP
2 changes: 1 addition & 1 deletion src/coreclr/inc/executableallocator.h
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ class ExecutableAllocator
void UnmapRW(void* pRW);

// Allocate thunks from a template. pTemplate is the return value from CreateTemplate
void* AllocateThunksFromTemplate(void *pTemplate, size_t templateSize);
void* AllocateThunksFromTemplate(void *pTemplate, size_t templateSize, void (*dataPageGenerator)(uint8_t* pageBase, size_t size));

// Free a set of thunks allocated from templates. pThunks must have been returned from AllocateThunksFromTemplate
void FreeThunksFromTemplate(void *pThunks, size_t templateSize);
Expand Down
3 changes: 2 additions & 1 deletion src/coreclr/inc/loaderheap.h
Original file line number Diff line number Diff line change
Expand Up @@ -460,9 +460,10 @@ struct InterleavedLoaderHeapConfig
uint32_t StubSize;
void* Template;
void (*CodePageGenerator)(uint8_t* pageBase, uint8_t* pageBaseRX, size_t size);
void (*DataPageGenerator)(uint8_t* pageBase, size_t size);
};

void InitializeLoaderHeapConfig(InterleavedLoaderHeapConfig *pConfig, size_t stubSize, void* templateInImage, void (*codePageGenerator)(uint8_t* pageBase, uint8_t* pageBaseRX, size_t size));
void InitializeLoaderHeapConfig(InterleavedLoaderHeapConfig *pConfig, size_t stubSize, void* templateInImage, void (*codePageGenerator)(uint8_t* pageBase, uint8_t* pageBaseRX, size_t size), void (*dataPageGenerator)(uint8_t* pageBase, size_t size));

//===============================================================================
// This is the base class for InterleavedLoaderHeap It's used as a simple
Expand Down
14 changes: 14 additions & 0 deletions src/coreclr/inc/volatile.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,11 @@
#endif

#if defined(__GNUC__)
#if defined(HOST_X86) || defined(HOST_AMD64)
#define SFENCE_MEMORY_BARRIER() asm volatile ("sfence" : : : "memory")
#else
#define SFENCE_MEMORY_BARRIER()
#endif
#if defined(HOST_ARMV6)
// DMB ISH not valid on ARMv6
#define VOLATILE_MEMORY_BARRIER() asm volatile ("mcr p15, 0, r0, c7, c10, 5" : : : "memory")
Expand All @@ -97,13 +102,22 @@
//
#define VOLATILE_MEMORY_BARRIER() asm volatile ("" : : : "memory")
#endif // HOST_ARM || HOST_ARM64

#elif (defined(HOST_ARM) || defined(HOST_ARM64)) && _ISO_VOLATILE
// ARM & ARM64 have a very weak memory model and very few tools to control that model. We're forced to perform a full
// memory barrier to preserve the volatile semantics. Technically this is only necessary on MP systems but we
// currently don't have a cheap way to determine the number of CPUs from this header file. Revisit this if it
// turns out to be a performance issue for the uni-proc case.

#define VOLATILE_MEMORY_BARRIER() MemoryBarrier()
#define SFENCE_MEMORY_BARRIER()
#else

#if defined(HOST_X86) || defined(HOST_AMD64)
#define SFENCE_MEMORY_BARRIER() _mm_sfence()
#else
#define SFENCE_MEMORY_BARRIER()
#endif
//
// On VC++, reorderings at the compiler and machine level are prevented by the use of the
// "volatile" keyword in VolatileLoad and VolatileStore. This should work on any CPU architecture
Expand Down
14 changes: 13 additions & 1 deletion src/coreclr/minipal/Unix/doublemapping.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,7 @@ void* VMToOSInterface::CreateTemplate(void* pImageTemplate, size_t templateSize,
#endif
}

void* VMToOSInterface::AllocateThunksFromTemplate(void* pTemplate, size_t templateSize, void* pStartSpecification)
void* VMToOSInterface::AllocateThunksFromTemplate(void* pTemplate, size_t templateSize, void* pStartSpecification, void (*dataPageGenerator)(uint8_t* pageBase, size_t size))
{
#ifdef TARGET_APPLE
vm_address_t addr, taddr;
Expand All @@ -501,6 +501,12 @@ void* VMToOSInterface::AllocateThunksFromTemplate(void* pTemplate, size_t templa
return NULL;
}

if (dataPageGenerator)
{
// Generate the data page before we map the code page into memory
dataPageGenerator(((uint8_t*) addr) + templateSize, templateSize);
}

do
{
ret = vm_remap(
Expand Down Expand Up @@ -549,6 +555,12 @@ void* VMToOSInterface::AllocateThunksFromTemplate(void* pTemplate, size_t templa
return NULL;
}

if (dataPageGenerator)
{
// Generate the data page before we map the code page into memory
dataPageGenerator(((uint8_t*) pStart) + templateSize, templateSize);
}

void *pStartCode = mmap(pStart, templateSize, PROT_READ | PROT_EXEC, MAP_PRIVATE | MAP_FIXED, pThunkData->fdImage, fileOffset);
if (pStart != pStartCode)
{
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/minipal/Windows/doublemapping.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ bool VMToOSInterface::AllocateThunksFromTemplateRespectsStartAddress()
return false;
}

void* VMToOSInterface::AllocateThunksFromTemplate(void* pTemplate, size_t templateSize, void* pStart)
void* VMToOSInterface::AllocateThunksFromTemplate(void* pTemplate, size_t templateSize, void* pStart, void (*dataPageGenerator)(uint8_t* pageBase, size_t size))
{
return NULL;
}
Expand Down
3 changes: 2 additions & 1 deletion src/coreclr/minipal/minipal.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,12 @@ class VMToOSInterface
// pTemplate - Value returned from CreateTemplate
// templateSize - Size of the templates block in the image
// pStart - Where to allocate (Specify NULL if no particular address is required). If non-null, this must be an address returned by ReserveDoubleMappedMemory
// dataPageGenerator - If non-null fill the data page of the template using this function. This function is called BEFORE the code page is mapped into memory.
//
// Return:
// NULL if the allocation fails
// Non-NULL, a pointer to the allocated region.
static void* AllocateThunksFromTemplate(void* pTemplate, size_t templateSize, void* pStart);
static void* AllocateThunksFromTemplate(void* pTemplate, size_t templateSize, void* pStart, void (*dataPageGenerator)(uint8_t* pageBase, size_t size));

// Free thunks allocated from template
// Parameters:
Expand Down
6 changes: 3 additions & 3 deletions src/coreclr/utilcode/executableallocator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -978,7 +978,7 @@ void ExecutableAllocator::UnmapRW(void* pRW)
}
}

void* ExecutableAllocator::AllocateThunksFromTemplate(void *pTemplate, size_t templateSize)
void* ExecutableAllocator::AllocateThunksFromTemplate(void *pTemplate, size_t templateSize, void (*dataPageGenerator)(uint8_t* pageBase, size_t size))
{
if (IsDoubleMappingEnabled() && VMToOSInterface::AllocateThunksFromTemplateRespectsStartAddress())
{
Expand All @@ -1003,7 +1003,7 @@ void* ExecutableAllocator::AllocateThunksFromTemplate(void *pTemplate, size_t te
BackoutBlock(block, isFreeBlock);
}

void *pTemplateAddressAllocated = VMToOSInterface::AllocateThunksFromTemplate(pTemplate, templateSize, block->baseRX);
void *pTemplateAddressAllocated = VMToOSInterface::AllocateThunksFromTemplate(pTemplate, templateSize, block->baseRX, dataPageGenerator);

if (pTemplateAddressAllocated == NULL)
{
Expand All @@ -1014,7 +1014,7 @@ void* ExecutableAllocator::AllocateThunksFromTemplate(void *pTemplate, size_t te
}
else
{
return VMToOSInterface::AllocateThunksFromTemplate(pTemplate, templateSize, NULL);
return VMToOSInterface::AllocateThunksFromTemplate(pTemplate, templateSize, NULL, dataPageGenerator);
}
}

Expand Down
Loading
Loading