Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 38ee40a

Browse files
[release/10.0.1xx] Source code updates from dotnet/runtime (#2835)
Co-authored-by: dotnet-maestro[bot] <dotnet-maestro[bot]@users.noreply.github.com>
1 parent 1b09965 commit 38ee40a

File tree

15 files changed

+368
-94
lines changed

15 files changed

+368
-94
lines changed

src/runtime/src/coreclr/jit/lclmorph.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2020,7 +2020,7 @@ class LocalAddressVisitor final : public GenTreeVisitor<LocalAddressVisitor>
20202020
}
20212021

20222022
if ((genTypeSize(indir) == genTypeSize(varDsc)) && (genTypeSize(indir) <= TARGET_POINTER_SIZE) &&
2023-
(varTypeIsFloating(indir) || varTypeIsFloating(varDsc)))
2023+
(varTypeIsFloating(indir) || varTypeIsFloating(varDsc)) && !varDsc->lvPromoted)
20242024
{
20252025
return IndirTransform::BitCast;
20262026
}

src/runtime/src/coreclr/vm/appdomain.cpp

Lines changed: 84 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1871,7 +1871,7 @@ DispIDCache* AppDomain::SetupRefDispIDCache()
18711871

18721872
#endif // FEATURE_COMINTEROP
18731873

1874-
FileLoadLock *FileLoadLock::Create(PEFileListLock *pLock, PEAssembly * pPEAssembly, Assembly *pAssembly)
1874+
FileLoadLock* FileLoadLock::Create(PEFileListLock* pLock, PEAssembly* pPEAssembly)
18751875
{
18761876
CONTRACTL
18771877
{
@@ -1884,7 +1884,7 @@ FileLoadLock *FileLoadLock::Create(PEFileListLock *pLock, PEAssembly * pPEAssemb
18841884
}
18851885
CONTRACTL_END;
18861886

1887-
NewHolder<FileLoadLock> result(new FileLoadLock(pLock, pPEAssembly, pAssembly));
1887+
NewHolder<FileLoadLock> result(new FileLoadLock(pLock, pPEAssembly));
18881888

18891889
pLock->AddElement(result);
18901890
result->AddRef(); // Add one ref on behalf of the ListLock's reference. The corresponding Release() happens in FileLoadLock::CompleteLoadLevel.
@@ -1910,6 +1910,14 @@ Assembly *FileLoadLock::GetAssembly()
19101910
return m_pAssembly;
19111911
}
19121912

1913+
PEAssembly* FileLoadLock::GetPEAssembly()
1914+
{
1915+
LIMITED_METHOD_CONTRACT;
1916+
// Underlying PEAssembly pointer is stored in the constructor in base ListLockEntry::m_data.
1917+
_ASSERTE(m_data != NULL);
1918+
return (PEAssembly*)m_data;
1919+
}
1920+
19131921
FileLoadLevel FileLoadLock::GetLoadLevel()
19141922
{
19151923
LIMITED_METHOD_CONTRACT;
@@ -1958,6 +1966,7 @@ BOOL FileLoadLock::CanAcquire(FileLoadLevel targetLevel)
19581966
static const char *fileLoadLevelName[] =
19591967
{
19601968
"CREATE", // FILE_LOAD_CREATE
1969+
"ALLOCATE", // FILE_LOAD_ALLOCATE
19611970
"BEGIN", // FILE_LOAD_BEGIN
19621971
"BEFORE_TYPE_LOAD", // FILE_LOAD_BEFORE_TYPE_LOAD
19631972
"EAGER_FIXUPS", // FILE_LOAD_EAGER_FIXUPS
@@ -1983,7 +1992,9 @@ BOOL FileLoadLock::CompleteLoadLevel(FileLoadLevel level, BOOL success)
19831992
if (level > m_level)
19841993
{
19851994
// Must complete each level in turn, unless we have an error
1986-
CONSISTENCY_CHECK(m_pAssembly->IsError() || (level == (m_level+1)));
1995+
CONSISTENCY_CHECK((level == (m_level+1)) || (m_pAssembly != nullptr && m_pAssembly->IsError()));
1996+
CONSISTENCY_CHECK(m_pAssembly != nullptr || level < FILE_LOAD_ALLOCATE);
1997+
19871998
// Remove the lock from the list if the load is completed
19881999
if (level >= FILE_ACTIVE)
19892000
{
@@ -2019,7 +2030,7 @@ BOOL FileLoadLock::CompleteLoadLevel(FileLoadLevel level, BOOL success)
20192030
{
20202031
m_level = (FileLoadLevel)level;
20212032

2022-
if (success)
2033+
if (success && level >= FILE_LOAD_ALLOCATE)
20232034
m_pAssembly->SetLoadLevel(level);
20242035
}
20252036

@@ -2042,6 +2053,18 @@ BOOL FileLoadLock::CompleteLoadLevel(FileLoadLevel level, BOOL success)
20422053
return FALSE;
20432054
}
20442055

2056+
void FileLoadLock::SetAssembly(Assembly* pAssembly)
2057+
{
2058+
LIMITED_METHOD_CONTRACT;
2059+
2060+
_ASSERTE(HasLock());
2061+
_ASSERTE(m_level == FILE_LOAD_CREATE); // Only valid to set during CREATE -> ALLOCATE
2062+
_ASSERTE(m_pAssembly == nullptr);
2063+
_ASSERTE(pAssembly != nullptr && pAssembly->GetPEAssembly() == (PEAssembly *)m_data);
2064+
2065+
m_pAssembly = pAssembly;
2066+
}
2067+
20452068
void FileLoadLock::SetError(Exception *ex)
20462069
{
20472070
CONTRACTL
@@ -2088,10 +2111,10 @@ UINT32 FileLoadLock::Release()
20882111
return count;
20892112
}
20902113

2091-
FileLoadLock::FileLoadLock(PEFileListLock *pLock, PEAssembly * pPEAssembly, Assembly *pAssembly)
2114+
FileLoadLock::FileLoadLock(PEFileListLock* pLock, PEAssembly* pPEAssembly)
20922115
: ListLockEntry(pLock, pPEAssembly, "File load lock"),
20932116
m_level((FileLoadLevel) (FILE_LOAD_CREATE)),
2094-
m_pAssembly(pAssembly),
2117+
m_pAssembly(nullptr),
20952118
m_cachedHR(S_OK)
20962119
{
20972120
WRAPPER_NO_CONTRACT;
@@ -2420,23 +2443,6 @@ Assembly *AppDomain::LoadAssemblyInternal(AssemblySpec* pIdentity,
24202443

24212444
if (result == NULL)
24222445
{
2423-
LoaderAllocator *pLoaderAllocator = NULL;
2424-
2425-
AssemblyBinder *pAssemblyBinder = pPEAssembly->GetAssemblyBinder();
2426-
// Assemblies loaded with CustomAssemblyBinder need to use a different LoaderAllocator if
2427-
// marked as collectible
2428-
pLoaderAllocator = pAssemblyBinder->GetLoaderAllocator();
2429-
if (pLoaderAllocator == NULL)
2430-
{
2431-
pLoaderAllocator = this->GetLoaderAllocator();
2432-
}
2433-
2434-
// Allocate the DomainAssembly a bit early to avoid GC mode problems. We could potentially avoid
2435-
// a rare redundant allocation by moving this closer to FileLoadLock::Create, but it's not worth it.
2436-
AllocMemTracker amTracker;
2437-
AllocMemTracker *pamTracker = &amTracker;
2438-
NewHolder<DomainAssembly> pDomainAssembly = new DomainAssembly(pPEAssembly, pLoaderAllocator, pamTracker);
2439-
24402446
LoadLockHolder lock(this);
24412447

24422448
// Find the list lock entry
@@ -2448,20 +2454,9 @@ Assembly *AppDomain::LoadAssemblyInternal(AssemblySpec* pIdentity,
24482454
result = FindAssembly(pPEAssembly, FindAssemblyOptions_IncludeFailedToLoad);
24492455
if (result == NULL)
24502456
{
2451-
// We are the first one in - create the DomainAssembly
2457+
// We are the first one in - create the FileLoadLock. Creation of the Assembly will happen at FILE_LOAD_ALLOCATE stage
24522458
registerNewAssembly = true;
2453-
fileLock = FileLoadLock::Create(lock, pPEAssembly, pDomainAssembly->GetAssembly());
2454-
pDomainAssembly.SuppressRelease();
2455-
pamTracker->SuppressRelease();
2456-
2457-
// Set the assembly module to be tenured now that we know it won't be deleted
2458-
pDomainAssembly->GetAssembly()->SetIsTenured();
2459-
if (pDomainAssembly->GetAssembly()->IsCollectible())
2460-
{
2461-
// We add the assembly to the LoaderAllocator only when we are sure that it can be added
2462-
// and won't be deleted in case of a concurrent load from the same ALC
2463-
((AssemblyLoaderAllocator *)pLoaderAllocator)->AddDomainAssembly(pDomainAssembly);
2464-
}
2459+
fileLock = FileLoadLock::Create(lock, pPEAssembly);
24652460
}
24662461
}
24672462
else
@@ -2479,6 +2474,8 @@ Assembly *AppDomain::LoadAssemblyInternal(AssemblySpec* pIdentity,
24792474
// so it will not be removed until app domain unload. So there is no need
24802475
// to release our ref count.
24812476
result = LoadAssembly(fileLock, targetLevel);
2477+
// By now FILE_LOAD_ALLOCATE should have run and the Assembly should exist
2478+
_ASSERTE(result != NULL);
24822479
}
24832480
else
24842481
{
@@ -2487,7 +2484,7 @@ Assembly *AppDomain::LoadAssemblyInternal(AssemblySpec* pIdentity,
24872484

24882485
if (registerNewAssembly)
24892486
{
2490-
pPEAssembly->GetAssemblyBinder()->AddLoadedAssembly(pDomainAssembly->GetAssembly());
2487+
pPEAssembly->GetAssemblyBinder()->AddLoadedAssembly(result);
24912488
}
24922489
}
24932490
else
@@ -2517,6 +2514,7 @@ Assembly *AppDomain::LoadAssembly(FileLoadLock *pLock, FileLoadLevel targetLevel
25172514
STANDARD_VM_CHECK;
25182515
PRECONDITION(CheckPointer(pLock));
25192516
PRECONDITION(AppDomain::GetCurrentDomain() == this);
2517+
PRECONDITION(targetLevel >= FILE_LOAD_ALLOCATE);
25202518
POSTCONDITION(RETVAL->GetLoadLevel() >= GetCurrentFileLoadLevel()
25212519
|| RETVAL->GetLoadLevel() >= targetLevel);
25222520
POSTCONDITION(RETVAL->CheckNoError(targetLevel));
@@ -2531,6 +2529,7 @@ Assembly *AppDomain::LoadAssembly(FileLoadLock *pLock, FileLoadLevel targetLevel
25312529
// Do a quick out check for the already loaded case.
25322530
if (pLock->GetLoadLevel() >= targetLevel)
25332531
{
2532+
_ASSERTE(pAssembly != nullptr);
25342533
pAssembly->ThrowIfError(targetLevel);
25352534

25362535
RETURN pAssembly;
@@ -2553,8 +2552,9 @@ Assembly *AppDomain::LoadAssembly(FileLoadLock *pLock, FileLoadLevel targetLevel
25532552
if (immediateTargetLevel > limit.GetLoadLevel())
25542553
immediateTargetLevel = limit.GetLoadLevel();
25552554

2555+
const char *simpleName = pLock->GetPEAssembly()->GetSimpleName();
25562556
LOG((LF_LOADER, LL_INFO100, "LOADER: ***%s*\t>>>Load initiated, %s/%s\n",
2557-
pAssembly->GetSimpleName(),
2557+
simpleName,
25582558
fileLoadLevelName[immediateTargetLevel], fileLoadLevelName[targetLevel]));
25592559

25602560
// Now loop and do the load incrementally to the target level.
@@ -2577,30 +2577,32 @@ Assembly *AppDomain::LoadAssembly(FileLoadLock *pLock, FileLoadLevel targetLevel
25772577

25782578
LOG((LF_LOADER,
25792579
(workLevel == FILE_LOAD_BEGIN
2580-
|| workLevel == FILE_LOADED
2581-
|| workLevel == FILE_ACTIVE)
2582-
? LL_INFO10 : LL_INFO1000,
2583-
"LOADER: %p:***%s*\t loading at level %s\n",
2584-
this, pAssembly->GetSimpleName(), fileLoadLevelName[workLevel]));
2580+
|| workLevel == FILE_LOADED
2581+
|| workLevel == FILE_ACTIVE)
2582+
? LL_INFO10 : LL_INFO1000,
2583+
"LOADER: %p:***%s*\t loading at level %s\n",
2584+
this, simpleName, fileLoadLevelName[workLevel]));
25852585

2586-
TryIncrementalLoad(pAssembly, workLevel, fileLock);
2586+
TryIncrementalLoad(workLevel, fileLock);
25872587
}
25882588
}
25892589

25902590
if (pLock->GetLoadLevel() == immediateTargetLevel-1)
25912591
{
25922592
LOG((LF_LOADER, LL_INFO100, "LOADER: ***%s*\t<<<Load limited due to detected deadlock, %s\n",
2593-
pAssembly->GetSimpleName(),
2593+
simpleName,
25942594
fileLoadLevelName[immediateTargetLevel-1]));
25952595
}
25962596
}
25972597

25982598
LOG((LF_LOADER, LL_INFO100, "LOADER: ***%s*\t<<<Load completed, %s\n",
2599-
pAssembly->GetSimpleName(),
2599+
simpleName,
26002600
fileLoadLevelName[pLock->GetLoadLevel()]));
2601-
26022601
}
26032602

2603+
pAssembly = pLock->GetAssembly();
2604+
_ASSERTE(pAssembly != nullptr); // We should always be loading to at least FILE_LOAD_ALLOCATE, so the assembly should be created
2605+
26042606
// There may have been an error stored on the domain file by another thread, or from a previous load
26052607
pAssembly->ThrowIfError(targetLevel);
26062608

@@ -2624,19 +2626,49 @@ Assembly *AppDomain::LoadAssembly(FileLoadLock *pLock, FileLoadLevel targetLevel
26242626
RETURN pAssembly;
26252627
}
26262628

2627-
void AppDomain::TryIncrementalLoad(Assembly *pAssembly, FileLoadLevel workLevel, FileLoadLockHolder &lockHolder)
2629+
void AppDomain::TryIncrementalLoad(FileLoadLevel workLevel, FileLoadLockHolder& lockHolder)
26282630
{
26292631
STANDARD_VM_CONTRACT;
26302632

26312633
// This is factored out so we don't call EX_TRY in a loop (EX_TRY can _alloca)
26322634

26332635
BOOL released = FALSE;
26342636
FileLoadLock* pLoadLock = lockHolder.GetValue();
2637+
Assembly* pAssembly = pLoadLock->GetAssembly();
26352638

26362639
EX_TRY
26372640
{
2638-
// Do the work
2639-
BOOL success = pAssembly->DoIncrementalLoad(workLevel);
2641+
BOOL success;
2642+
if (workLevel == FILE_LOAD_ALLOCATE)
2643+
{
2644+
// FileLoadLock should not have an assembly yet
2645+
_ASSERTE(pAssembly == NULL);
2646+
2647+
// Allocate DomainAssembly & Assembly
2648+
PEAssembly *pPEAssembly = pLoadLock->GetPEAssembly();
2649+
AssemblyBinder *pAssemblyBinder = pPEAssembly->GetAssemblyBinder();
2650+
LoaderAllocator *pLoaderAllocator = pAssemblyBinder->GetLoaderAllocator();
2651+
if (pLoaderAllocator == NULL)
2652+
pLoaderAllocator = this->GetLoaderAllocator();
2653+
2654+
AllocMemTracker amTracker;
2655+
AllocMemTracker *pamTracker = &amTracker;
2656+
NewHolder<DomainAssembly> pDomainAssembly = new DomainAssembly(pPEAssembly, pLoaderAllocator, pamTracker);
2657+
pLoadLock->SetAssembly(pDomainAssembly->GetAssembly());
2658+
pDomainAssembly->GetAssembly()->SetIsTenured();
2659+
if (pDomainAssembly->GetAssembly()->IsCollectible())
2660+
{
2661+
((AssemblyLoaderAllocator *)pLoaderAllocator)->AddDomainAssembly(pDomainAssembly);
2662+
}
2663+
pDomainAssembly.SuppressRelease();
2664+
pamTracker->SuppressRelease();
2665+
pAssembly = pLoadLock->GetAssembly();
2666+
success = TRUE;
2667+
}
2668+
else
2669+
{
2670+
success = pAssembly->DoIncrementalLoad(workLevel);
2671+
}
26402672

26412673
// Complete the level.
26422674
if (pLoadLock->CompleteLoadLevel(workLevel, success) &&
@@ -2651,9 +2683,9 @@ void AppDomain::TryIncrementalLoad(Assembly *pAssembly, FileLoadLevel workLevel,
26512683
{
26522684
Exception *pEx = GET_EXCEPTION();
26532685

2654-
//We will cache this error and wire this load to forever fail,
2686+
// We will cache this error and wire this load to forever fail,
26552687
// unless the exception is transient or the file is loaded OK but just cannot execute
2656-
if (!pEx->IsTransient() && !pAssembly->IsLoaded())
2688+
if (pAssembly != nullptr && !pEx->IsTransient() && !pAssembly->IsLoaded())
26572689
{
26582690
if (released)
26592691
{

src/runtime/src/coreclr/vm/appdomain.hpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -293,14 +293,15 @@ class FileLoadLock : public ListLockEntry
293293
{
294294
private:
295295
FileLoadLevel m_level;
296-
Assembly* m_pAssembly;
296+
Assembly* m_pAssembly; // Will be null until FILE_LOAD_ALLOCATE is completed successfully
297297
HRESULT m_cachedHR;
298298

299299
public:
300-
static FileLoadLock *Create(PEFileListLock *pLock, PEAssembly *pPEAssembly, Assembly *pAssembly);
300+
static FileLoadLock* Create(PEFileListLock* pLock, PEAssembly* pPEAssembly);
301301

302302
~FileLoadLock();
303303
Assembly *GetAssembly();
304+
PEAssembly* GetPEAssembly();
304305
FileLoadLevel GetLoadLevel();
305306

306307
// CanAcquire will return FALSE if Acquire will definitely not take the lock due
@@ -320,14 +321,17 @@ class FileLoadLock : public ListLockEntry
320321
// returns TRUE if it updated load level, FALSE if the level was set already
321322
BOOL CompleteLoadLevel(FileLoadLevel level, BOOL success);
322323

324+
// Associate an Assembly with this lock
325+
void SetAssembly(Assembly* pAssembly);
326+
323327
void SetError(Exception *ex);
324328

325329
void AddRef();
326330
UINT32 Release() DAC_EMPTY_RET(0);
327331

328332
private:
329333

330-
FileLoadLock(PEFileListLock *pLock, PEAssembly *pPEAssembly, Assembly *pAssembly);
334+
FileLoadLock(PEFileListLock* pLock, PEAssembly* pPEAssembly);
331335

332336
static void HolderLeave(FileLoadLock *pThis);
333337

@@ -1098,7 +1102,7 @@ class AppDomain final
10981102

10991103
Assembly *LoadAssembly(FileLoadLock *pLock, FileLoadLevel targetLevel);
11001104

1101-
void TryIncrementalLoad(Assembly *pFile, FileLoadLevel workLevel, FileLoadLockHolder &lockHolder);
1105+
void TryIncrementalLoad(FileLoadLevel workLevel, FileLoadLockHolder& lockHolder);
11021106

11031107
#ifndef DACCESS_COMPILE // needs AssemblySpec
11041108
public:

src/runtime/src/coreclr/vm/assemblyspec.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ enum FileLoadLevel
2727
// Note that semantics here are description is the LAST step done, not what is
2828
// currently being done.
2929

30-
FILE_LOAD_CREATE,
30+
FILE_LOAD_CREATE, // List entry + FileLoadLock created, no Assembly/DomainAssembly yet
31+
FILE_LOAD_ALLOCATE, // DomainAssembly & Assembly object allocated and associated with the lock
3132
FILE_LOAD_BEGIN,
3233
FILE_LOAD_BEFORE_TYPE_LOAD,
3334
FILE_LOAD_EAGER_FIXUPS,

src/runtime/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Emitter.cs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -612,7 +612,17 @@ private void GeneratePropMetadataInitFunc(SourceWriter writer, string propInitMe
612612
PropertyGenerationSpec property = properties[i];
613613
string propertyName = property.NameSpecifiedInSourceCode;
614614
string declaringTypeFQN = property.DeclaringType.FullyQualifiedName;
615-
string propertyTypeFQN = property.PropertyType.FullyQualifiedName;
615+
616+
// If the property is ignored and its type is not used anywhere else in the type graph,
617+
// emit a JsonPropertyInfo of type 'object' to avoid unnecessarily referencing the type.
618+
// STJ requires that all ignored properties be included so that it can perform
619+
// necessary run-time validations using configuration not known at compile time
620+
// such as the property naming policy and case sensitivity.
621+
bool isIgnoredPropertyOfUnusedType =
622+
property.DefaultIgnoreCondition is JsonIgnoreCondition.Always &&
623+
!_typeIndex.ContainsKey(property.PropertyType);
624+
625+
string propertyTypeFQN = isIgnoredPropertyOfUnusedType ? "object" : property.PropertyType.FullyQualifiedName;
616626

617627
string getterValue = property switch
618628
{
@@ -653,9 +663,12 @@ private void GeneratePropMetadataInitFunc(SourceWriter writer, string propInitMe
653663
: $"({JsonConverterTypeRef}<{propertyTypeFQN}>){ExpandConverterMethodName}(typeof({propertyTypeFQN}), new {converterFQN}(), {OptionsLocalVariableName})";
654664
}
655665

656-
string attributeProviderFactoryExpr = property.IsProperty
657-
? $"typeof({property.DeclaringType.FullyQualifiedName}).GetProperty({FormatStringLiteral(property.MemberName)}, {InstanceMemberBindingFlagsVariableName}, null, typeof({property.PropertyType.FullyQualifiedName}), {EmptyTypeArray}, null)"
658-
: $"typeof({property.DeclaringType.FullyQualifiedName}).GetField({FormatStringLiteral(property.MemberName)}, {InstanceMemberBindingFlagsVariableName})";
666+
string attributeProviderFactoryExpr = property switch
667+
{
668+
_ when isIgnoredPropertyOfUnusedType => "null",
669+
{ IsProperty: true } => $"typeof({property.DeclaringType.FullyQualifiedName}).GetProperty({FormatStringLiteral(property.MemberName)}, {InstanceMemberBindingFlagsVariableName}, null, typeof({propertyTypeFQN}), {EmptyTypeArray}, null)",
670+
_ => $"typeof({property.DeclaringType.FullyQualifiedName}).GetField({FormatStringLiteral(property.MemberName)}, {InstanceMemberBindingFlagsVariableName})",
671+
};
659672

660673
writer.WriteLine($$"""
661674
var {{InfoVarName}}{{i}} = new {{JsonPropertyInfoValuesTypeRef}}<{{propertyTypeFQN}}>

0 commit comments

Comments
 (0)