8000 [main] Source code updates from dotnet/runtime (#616) · dotnet/dotnet@37d3428 · GitHub
[go: up one dir, main page]

Skip to content

Commit 37d3428

Browse files
[main] Source code updates from dotnet/runtime (#616)
Co-authored-by: dotnet-maestro[bot] <dotnet-maestro[bot]@users.noreply.github.com>
1 parent e7f150b commit 37d3428

File tree

180 files changed

+3919
-3544
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

180 files changed

+3919
-3544
lines changed

prereqs/git-info/runtime.props

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<Project>
33
<PropertyGroup>
4-
<GitCommitHash>1307a67de8039d70a9e3d6e74d6651afbd8a0278</GitCommitHash>
5-
<OfficialBuildId>20250515.21</OfficialBuildId>
4+
<GitCommitHash>29638e8e84335bc877f064766be3f1b3038da311</GitCommitHash>
5+
<OfficialBuildId>20250518.1</OfficialBuildId>
66
<OutputPackageVersion>10.0.0-preview.5.25262.10</OutputPackageVersion>
77
</PropertyGroup>
88
</Project>

src/runtime/NuGet.config

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
<add key="dotnet-libraries-transport" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-libraries-transport/nuget/v3/index.json" />
2020
<add key="dotnet10" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet10/nuget/v3/index.json" />
2121
<add key="dotnet10-transport" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet10-transport/nuget/v3/index.json" />
22+
<!-- Need for prototype Roslyn compiler for runtime-async -->
23+
<add key="general-testing" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/general-testing/nuget/v3/index.json" />
2224
</packageSources>
2325
<auditSources>
2426
<clear />
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
# GC write barriers
2+
3+
The GC write barrier function (JIT_WriteBarrier) is generally the hottest function in CoreCLR and is written in assembly. The full pseudo code for the function is as follows:
4+
5+
6+
````
7+
JIT_WriteBarrier(Object **dst, Object *ref)
8+
Set *dst = ref
9+
10+
// Shadow Heap update
11+
ifdef WRITE_BARRIER_CHECK: // Only set in DEBUG mode
12+
if g_GCShadow != 0:
13+
long *shadow_dst = g_GCShadow + (dst - g_lowest_address)
14+
// Check shadow heap location is within shadow heap
15+
if shadow_dst < g_GCShadowEnd:
16+
*shadow_dst = ref
17+
atomic: wait for stores to complete
18+
if *dst != ref:
19+
*shadow_dst = INVALIDGCVALUE
20+
21+
// Update the write watch table, if it's in use
22+
ifdef FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP:
23+
if g_sw_ww_table != 0:
24+
char *ww_table_dst = g_sw_ww_table + (dst>>11)
25+
if *ww_table_dst != 0:
26+
*ww_table_dst = 0xff
27+
28+
// Return if the reference is not in ephemeral generations
29+
if ref < g_ephemeral_low || ref >= g_ephemeral_high:
30+
return
31+
32+
// Region Checks
33+
if g_region_to_generation_table != 0:
34+
35+
// Calculate region generations
36+
char reg_loc_dst = *((dst >> g_region_shr) + g_region_to_generation_table)
37+
char reg_loc_ref = *((ref >> g_region_shr) + g_region_to_generation_table)
38+
39+
// Return if the region we're storing into is Gen 0
40+
if reg_loc_dst == 0:
41+
return
42+
43+
// Return if the new reference is not from old to young
44+
if reg_loc_ref >= reg_loc_dst:
45+
return
46+
47+
// Bitwise write barriers only
48+
if g_region_use_bitwise_write_barrier:
49+
50+
char *card_table_dst = (dst >> 11) + g_card_table
51+
char dst_bit = 1 << (dst >> 8 && 7)
52+
53+
// Check if we need to update the card table
54+
if *card_table_dst & dst_bit == 0:
55+
return
56+
57+
// Atomically update the card table
58+
lock: *card_table_dst |= dst_bit
59+
60+
goto CardBundle
61+
62+
// Check if we need to update the card table
63+
char *card_table_dst = (dst >> 11) + g_card_table
64+
if *card_table_dst == 0xff:
65+
return
66+
67+
// Update the card table
68+
*card_table_dst = 0xff
69+
70+
CardBundle:
71+
72+
// Mark the card bundle table as dirty
73+
Ifdef FEATURE_MANUALLY_MANAGED_CARD_BUNDLES:
74+
char card_bundle_dst = (dst >> 21) + g_card_bundle_table
75+
if *card_bundle_dst != 0xff:
76+
*card_bundle_dst = 0xff
77+
78+
````
79+
80+
The Checked Write Barrier has additional checks:
81+
82+
````
83+
JIT_CheckedWriteBarrier(Object **dst, Object *ref)
84+
85+
// Return if the destination is not on the heap
86+
if ref < g_lowest_address || ref >= g_highest_address:
87+
return
88+
89+
return JIT_WriteBarrier(dst, ref)
90+
````
91+
92+
## WriteBarrierManager
93+
94+
On AMD64 and Arm64, there several different implementations of the write barrier function. Each version is a subset of the `JIT_WriteBarrier` above, assuming different state, meaning most `if` checks can be skipped. The actual write barrier that is called is a copy of one of these implementations.
95+
96+
The WriteBarrierManager keeps track of which implementation is currently being used. As internal state changes, the WriteBarrierManager updates the copy to the correct implementation. In practice, most of the internal state is fixed on startup, with only changes to/from use of write watch barriers changing during runtime.
97+
98+
`WRITE_BARRIER_CHECK` is only set in `DEBUG` mode. On Arm64 `WRITE_BARRIER_CHECK` checks exist at the top of each version of the function when `DEBUG` mode is enabled. On `Amd64` these checks do not exist. Instead, a special `JIT_WriteBarrier_Debug` version of the function exists, which contains most of the functionality of `JIT_WriteBarrier` pseudo code and is used exclusively when `DEBUG` mode is enabled.
99+
100+
On Arm64, `g_region_use_bitwise_write_barrier` is only set if LSE atomics are present on the hardware, as only LSE provides a single instruction to atomically update a byte via a bitwise OR.
101+

src/runtime/eng/testing/tests.browser.targets

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,10 @@
1313

1414
<!--
1515
- For regular library tests, it will use the symbols file from the runtime pack.
16-
- for AOT library tests, we use WasmNativeStrip=false, so we already have symbols
16+
- for AOT library tests, we avoid WasmNativeDebugSymbols so that we don't run OOM on helix during wasm-opt
1717
-->
18-
<WasmNativeStrip Condition="'$(WasmNativeStrip)' == '' and '$(RunAOTCompilation)' == 'true'">false</WasmNativeStrip>
18+
<WasmNativeStrip Condition="'$(ContinuousIntegrationBuild)' == 'true' and '$(RunAOTCompilation)' == 'true'">true</WasmNativeStrip>
19+
<WasmNativeDebugSymbols Condition="'$(ContinuousIntegrationBuild)' == 'true' and '$(RunAOTCompilation)' == 'true'">false</WasmNativeDebugSymbols>
1920
<WasmEmitSymbolMap Condition="'$(WasmEmitSymbolMap)' == ''">true</WasmEmitSymbolMap>
2021

2122
<_WasmMainJSFileName Condition="'$(WasmMainJSPath)' != ''">$([System.IO.Path]::GetFileName('$(WasmMainJSPath)'))</_WasmMainJSFileName>

src/runtime/eng/testing/tests.wasm.targets

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@
133133
<_WasmPropertyNames Include="WasmDedup" />
134134
<_WasmPropertyNames Include="WasmLinkIcalls" />
135135
<_WasmPropertyNames Include="WasmNativeStrip" />
136+
<_WasmPropertyNames Include="WasmNativeDebugSymbols" />
136137
<_WasmPropertyNames Include="_WasmDevel" />
137138
<_WasmPropertyNames Include="_WasmStrictVersionMatch" />
138139
<_WasmPropertyNames Include="WasmEmitSymbolMap" />

src/runtime/src/coreclr/System.Private.CoreLib/src/System/Runtime/ExceptionServices/AsmOffsets.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,9 @@ class AsmOffsets
6868
public const int OFFSETOF__StackFrameIterator__m_isRuntimeWrappedExceptions = 0x132;
6969
#elif TARGET_X86
7070
public const int OFFSETOF__REGDISPLAY__m_pCurrentContext = 0x4;
71-
public const int SIZEOF__StackFrameIterator = 0x3cc;
72-
public const int OFFSETOF__StackFrameIterator__m_isRuntimeWrappedExceptions = 0x3ba;
73-
public const int OFFSETOF__StackFrameIterator__m_AdjustedControlPC = 0x3c8;
71+
public const int SIZEOF__StackFrameIterator = 0x3d4;
72+
public const int OFFSETOF__StackFrameIterator__m_isRuntimeWrappedExceptions = 0x3c2;
73+
public const int OFFSETOF__StackFrameIterator__m_AdjustedControlPC = 0x3d0;
7474
#else // TARGET_64BIT
7575
public const int OFFSETOF__REGDISPLAY__m_pCurrentContext = 0x4;
7676
public const int SIZEOF__StackFrameIterator = 0xcc;
@@ -134,9 +134,9 @@ class AsmOffsets
134134
public const int OFFSETOF__StackFrameIterator__m_isRuntimeWrappedExceptions = 0x12a;
135135
#elif TARGET_X86
136136
public const int OFFSETOF__REGDISPLAY__m_pCurrentContext = 0x4;
137-
public const int SIZEOF__StackFrameIterator = 0x3c4;
138-
public const int OFFSETOF__StackFrameIterator__m_isRuntimeWrappedExceptions = 0x3b2;
139-
public const int OFFSETOF__StackFrameIterator__m_AdjustedControlPC = 0x3c0;
137+
public const int SIZEOF__StackFrameIterator = 0x3cc;
138+
public const int OFFSETOF__StackFrameIterator__m_isRuntimeWrappedExceptions = 0x3ba;
139+
public const int OFFSETOF__StackFrameIterator__m_AdjustedControlPC = 0x3c8;
140140
#else // TARGET_64BIT
141141
public const int OFFSETOF__REGDISPLAY__m_pCurrentContext = 0x4;
142142
public const int SIZEOF__StackFrameIterator = 0xc4;

src/runtime/src/coreclr/clrdefinitions.cmake

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -218,10 +218,6 @@ if (FEATURE_STUBPRECODE_DYNAMIC_HELPERS)
218218
add_definitions(-DFEATURE_STUBPRECODE_DYNAMIC_HELPERS)
219219
endif()
220220

221-
if (CLR_CMAKE_TARGET_APPLE)
222-
add_definitions(-DFEATURE_MAP_THUNKS_FROM_IMAGE)
223-
endif()
224-
225221
# Use this function to enable building with a specific target OS and architecture set of defines
226222
# This is known to work for the set of defines used by the JIT and gcinfo, it is not likely correct for
227223
# other components of the runtime

src/runtime/src/coreclr/debug/daccess/enummem.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -591,8 +591,6 @@ HRESULT ClrDataAccess::DumpManagedExcepObject(CLRDataEnumMemoryFlags flags, OBJE
591591
// Pulls in data to translate from token to MethodDesc
592592
FindLoadedMethodRefOrDef(pMD->GetMethodTable()->GetModule(), pMD->GetMemberDef());
593593

594-
// Pulls in sequence points.
595-
DebugInfoManager::EnumMemoryRegionsForMethodDebugInfo(flags, pMD);
596594
PCODE addr = pMD->GetNativeCode();
597595
if (addr != (PCODE)NULL)
598596
{
@@ -970,9 +968,6 @@ HRESULT ClrDataAccess::EnumMemWalkStackHelper(CLRDataEnumMemoryFlags flags,
970968
// back to source lines for functions on stacks is very useful and we don't
971969
// want to allow the function to fail for all targets.
972970

973-
// Pulls in sequence points and local variable info
974-
DebugInfoManager::EnumMemoryRegionsForMethodDebugInfo(flags, pMethodDesc);
975-
976971
#if defined(FEATURE_EH_FUNCLETS) && defined(USE_GC_INFO_DECODER)
977972

978973
if (addr != (PCODE)NULL)

src/runtime/src/coreclr/gcdump/i386/gcdumpx86.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,17 @@ size_t GCDump::DumpInfoHdr (PTR_CBYTE gcInfoBlock,
114114
header->revPInvokeOffset = count;
115115
}
116116

117+
if (header->noGCRegionCnt == HAS_NOGCREGIONS)
118+
{
119+
hasArgTabOffset = TRUE;
120+
table += decodeUnsigned(table, &count);
121+
header->noGCRegionCnt = count;
122+
}
123+
else if (header->noGCRegionCnt > 0)
124+
{
125+
hasArgTabOffset = TRUE;
126+
}
127+
117128
//
118129
// First print out all the basic information
119130
//
@@ - 10000 156,6 +167,8 @@ size_t GCDump::DumpInfoHdr (PTR_CBYTE gcInfoBlock,
156167
gcPrintf(" Sync region = [%u,%u] ([0x%x,0x%x])\n",
157168
header->syncStartOffset, header->syncEndOffset,
158169
header->syncStartOffset, header->syncEndOffset);
170+
if (header->noGCRegionCnt > 0)
171+
gcPrintf(" no GC region count = %2u \n", header->noGCRegionCnt);
159172

160173
if (header->epilogCount > 1 || (header->epilogCount != 0 &&
161174
header->epilogAtEnd == 0))
@@ -232,6 +245,23 @@ size_t GCDump::DumpGCTable(PTR_CBYTE table,
232245
if (header.ebxSaved) calleeSavedRegs++;
233246
}
234247

248+
/* Dump the no GC region table */
249+
250+
if (header.noGCRegionCnt > 0)
251+
{
252+
count = header.noGCRegionCnt;
253+
while (count-- > 0)
254+
{
255+
unsigned regionOffset;
256+
unsigned regionSize;
257+
258+
table += decodeUnsigned(table, &regionOffset);
259+
table += decodeUnsigned(table, &regionSize);
260+
261+
gcPrintf("[%04X-%04X) no GC region\n", regionOffset, regionOffset + regionSize);
262+
}
263+
}
264+
235265
/* Dump the untracked frame variable table */
236266

237267
count = header.untrackedCnt;
@@ -995,6 +1025,12 @@ void GCDump::DumpPtrsInFrame(PTR_CBYTE gcInfoBlock,
9951025
header.revPInvokeOffset = offset;
9961026
_ASSERTE(offset != INVALID_REV_PINVOKE_OFFSET);
9971027
}
1028+
if (header.noGCRegionCnt == HAS_NOGCREGIONS)
1029+
{
1030+
unsigned count;
1031+
table += decodeUnsigned(table, &count);
1032+
header.noGCRegionCnt = count;
1033+
}
9981034

9991035
prologSize = header.prologSize;
10001036
epilogSize = header.epilogSize;

src/runtime/src/coreclr/inc/executableallocator.h

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -182,9 +182,6 @@ class ExecutableAllocator
182182
// Return true if double mapping is enabled.
183183
static bool IsDoubleMappingEnabled();
184184

185-
// Release memory allocated via DoubleMapping for either templates or normal double mapped data
186-
void ReleaseWorker(void* pRX, bool releaseTemplate);
187-
188185
// Initialize the allocator instance
189186
bool Initialize();
190187

@@ -265,18 +262,6 @@ class ExecutableAllocator
265262

266263
// Unmap the RW mapping at the specified address
267264
void UnmapRW(void* pRW);
268-
269-
// Allocate thunks from a template. pTemplate is the return value from CreateTemplate
270-
void* AllocateThunksFromTemplate(void *pTemplate, size_t templateSize);
271-
272-
// Free a set of thunks allocated from templates. pThunks must have been returned from AllocateThunksFromTemplate
273-
void FreeThunksFromTemplate(void *pThunks, size_t templateSize);
274-
275-
// Create a template
276-
// If templateInImage is not null, it will attempt to use it as the template, otherwise it will create an temporary in memory file to serve as the template
277-
// Some OS/Architectures may/may not be able to work with this, so this api is permitted to return NULL, and callers should have an alternate approach using
278-
// the codePageGenerator directly.
279-
void* CreateTemplate(void* templateInImage, size_t templateSize, void (*codePageGenerator)(uint8_t* pageBase, uint8_t* pageBaseRX, size_t size));
280265
};
281266

282267
#define ExecutableWriterHolder ExecutableWriterHolderNoLog

src/runtime/src/coreclr/inc/gc_unwind_x86.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,8 @@ struct hdrInfo
367367
unsigned int syncEpilogStart; // The start of the epilog. Synchronized methods are guaranteed to have no more than one epilog.
368368
unsigned int revPInvokeOffset; // INVALID_REV_PINVOKE_OFFSET if there is no Reverse PInvoke frame
369369

370+
unsigned int noGCRegionCnt;
371+
370372
enum { NOT_IN_PROLOG = -1, NOT_IN_EPILOG = -1 };
371373

372374
int prologOffs; // NOT_IN_PROLOG if not in prolog
@@ -403,4 +405,8 @@ size_t DecodeGCHdrInfo(GCInfoToken gcInfoToken,
403405
unsigned curOffset,
404406
hdrInfo * infoPtr);
405407

408+
bool IsInNoGCRegion(hdrInfo * infoPtr,
409+
PTR_CBYTE table,
410+
unsigned curOffset);
411+
406412
#endif // _UNWIND_X86_H

src/runtime/src/coreclr/inc/gcdecoder.cpp

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -205,9 +205,22 @@ PTR_CBYTE FASTCALL decodeHeader(PTR_CBYTE table, UINT32 version, InfoHdr* header
205205
nextByte = *table++;
206206
encoding = nextByte & ADJ_ENCODING_MAX;
207207
// encoding here always corresponds to codes in InfoHdrAdjust2 set
208-
209-
_ASSERTE(encoding < SET_RET_KIND_MAX);
210-
header->returnKind = (ReturnKind)encoding;
208+
if (encoding <= SET_RET_KIND_MAX)
209+
{
210+
header->returnKind = (ReturnKind)encoding;
211+
}
212+
else if (encoding < FFFF_NOGCREGION_CNT)
213+
{
214+
header->noGCRegionCnt = encoding - SET_NOGCREGIONS_CNT;
215+
}
216+
else if (encoding == FFFF_NOGCREGION_CNT)
217+
{
218+
header->noGCRegionCnt = HAS_NOGCREGIONS;
219+
}
220+
else
221+
{
222+
_ASSERTE(!"Unexpected encoding");
223+
}
211224
break;
212225
}
213226
}
@@ -470,7 +483,8 @@ bool InfoHdrSmall::isHeaderMatch(const InfoHdr& target) const
470483
target.varPtrTableSize != HAS_VARPTR &&
471484
target.gsCookieOffset != HAS_GS_COOKIE_OFFSET &&
472485
target.syncStartOffset != HAS_SYNC_OFFSET &&
473-
target.revPInvokeOffset != HAS_REV_PINVOKE_FRAME_OFFSET);
486+
target.revPInvokeOffset != HAS_REV_PINVOKE_FRAME_OFFSET &&
487+
target.noGCRegionCnt != HAS_NOGCREGIONS);
474488
#endif
475489

476490
// compare two InfoHdr's up to but not including the untrackCnt field
@@ -495,7 +509,10 @@ bool InfoHdrSmall::isHeaderMatch(const InfoHdr& target) const
495509
if (target.syncStartOffset != INVALID_SYNC_OFFSET)
496510
return false;
497511

498-
if (target.revPInvokeOffset!= INVALID_REV_PINVOKE_OFFSET)
512+
if (target.revPInvokeOffset != INVALID_REV_PINVOKE_OFFSET)
513+
return false;
514+
515+
if (target.noGCRegionCnt > 0)
499516
return false;
500517

501518
return true;

0 commit comments

Comments
 (0)
0