Skip to content

Commit e3d319b

Browse files
Handle getting the address of an RVA static correctly in a composite image (dotnet#55301)
* Handle getting the address of an RVA static correctly in a composite image - Since composite images have the original RVA statics in the original files, use the value from there - This required re-enabling the ability of getFieldAddress to return an indirection - And adding some new processing for the fixup as needed * Silence pointless assert - There is an assert around incorrect handling of byref pointers, that isn't right. It fails for various issues with the Unsafe.* apis under jit stress, and this change makes it occur during one of our regular builds. As this is just an assert firing when it isn't appropriate, I'm disabling the warning as suggested by the JIT team.
1 parent ab21929 commit e3d319b

File tree

5 files changed

+61
-8
lines changed

5 files changed

+61
-8
lines changed

src/coreclr/jit/emitxarch.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12226,10 +12226,12 @@ BYTE* emitter::emitOutputRR(BYTE* dst, instrDesc* id)
1222612226
regMaskTP regMask;
1222712227
regMask = genRegMask(reg1) | genRegMask(reg2);
1222812228

12229-
// r1/r2 could have been a GCREF as GCREF + int=BYREF
12230-
// or BYREF+/-int=BYREF
12231-
assert(((regMask & emitThisGCrefRegs) && (ins == INS_add)) ||
12232-
((regMask & emitThisByrefRegs) && (ins == INS_add || ins == INS_sub)));
12229+
// Assert disabled as requested in PR 55301. A use of the Unsafe api
12230+
// which produces correct code, but isn't handled correctly here.
12231+
// r1/r2 could have been a GCREF as GCREF + int=BYREF
12232+
// or BYREF+/-int=BYREF
12233+
// assert(((regMask & emitThisGCrefRegs) && (ins == INS_add)) ||
12234+
// ((regMask & emitThisByrefRegs) && (ins == INS_add || ins == INS_sub)));
1223312235
#endif
1223412236
// Mark r1 as holding a byref
1223512237
emitGCregLiveUpd(GCT_BYREF, reg1, dst);

src/coreclr/jit/importer.cpp

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7704,14 +7704,24 @@ GenTree* Compiler::impImportStaticFieldAccess(CORINFO_RESOLVED_TOKEN* pResolvedT
77047704
void** pFldAddr = nullptr;
77057705
void* fldAddr = info.compCompHnd->getFieldAddress(pResolvedToken->hField, (void**)&pFldAddr);
77067706

7707-
// We should always be able to access this static's address directly
7708-
//
7707+
// We should always be able to access this static's address directly unless this is a field RVA
7708+
// used within a composite image during R2R composite image building.
7709+
//
7710+
#ifdef FEATURE_READYTORUN_COMPILER
7711+
assert((pFldAddr == nullptr) ||
7712+
(pFieldInfo->fieldAccessor == CORINFO_FIELD_STATIC_RVA_ADDRESS && opts.IsReadyToRun()));
7713+
#else
77097714
assert(pFldAddr == nullptr);
7715+
#endif
77107716

77117717
FieldSeqNode* fldSeq = GetFieldSeqStore()->CreateSingleton(pResolvedToken->hField);
77127718

77137719
/* Create the data member node */
7714-
op1 = gtNewIconHandleNode(pFldAddr == nullptr ? (size_t)fldAddr : (size_t)pFldAddr, GTF_ICON_STATIC_HDL,
7720+
op1 = gtNewIconHandleNode(pFldAddr == nullptr ? (size_t)fldAddr : (size_t)pFldAddr,
7721+
#ifdef FEATURE_READYTORUN_COMPILER
7722+
pFldAddr != nullptr ? GTF_ICON_CONST_PTR :
7723+
#endif
7724+
GTF_ICON_STATIC_HDL,
77157725
fldSeq);
77167726
#ifdef DEBUG
77177727
op1->AsIntCon()->gtTargetHandle = op1->AsIntCon()->gtIconVal;
@@ -7721,6 +7731,17 @@ GenTree* Compiler::impImportStaticFieldAccess(CORINFO_RESOLVED_TOKEN* pResolvedT
77217731
{
77227732
op1->gtFlags |= GTF_ICON_INITCLASS;
77237733
}
7734+
7735+
#ifdef FEATURE_READYTORUN_COMPILER
7736+
if (pFldAddr != nullptr)
7737+
{
7738+
// Indirection used to get to initial actual field RVA when building a composite image
7739+
// where the actual field does not move from the original file
7740+
assert(!varTypeIsGC(lclTyp));
7741+
op1 = gtNewOperNode(GT_IND, TYP_I_IMPL, op1);
7742+
op1->gtFlags |= GTF_IND_INVARIANT | GTF_IND_NONFAULTING;
7743+
}
7744+
#endif
77247745
}
77257746
else // We need the value of a static field
77267747
{

src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunSymbolNodeFactory.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,14 @@ private void CreateNodeCaches()
6464
new ReadyToRunInstructionSetSupportSignature(key));
6565
});
6666

67+
_precodeFieldAddressCache = new NodeCache<FieldDesc, ISymbolNode>(key =>
68+
{
69+
return new PrecodeHelperImport(
70+
_codegenNodeFactory,
71+
new FieldFixupSignature(ReadyToRunFixupKind.FieldAddress, key, _codegenNodeFactory)
72+
);
73+
});
74+
6775
_fieldAddressCache = new NodeCache<FieldDesc, ISymbolNode>(key =>
6876
{
6977
return new DelayLoadHelperImport(
@@ -398,6 +406,13 @@ public ISymbolNode FieldAddress(FieldDesc fieldDesc)
398406
return _fieldAddressCache.GetOrAdd(fieldDesc);
399407
}
400408

409+
private NodeCache<FieldDesc, ISymbolNode> _precodeFieldAddressCache;
410+
411+
public ISymbolNode PrecodeFieldAddress(FieldDesc fieldDesc)
412+
{
413+
return _precodeFieldAddressCache.GetOrAdd(fieldDesc);
414+
}
415+
401416
private NodeCache<FieldDesc, ISymbolNode> _fieldOffsetCache;
402417

403418
public ISymbolNode FieldOffset(FieldDesc fieldDesc)

src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -641,7 +641,7 @@ protected override void ComputeDependencyNodeDependencies(List<DependencyNodeCor
641641
}
642642
}
643643

644-
public ISymbolNode GetFieldRvaData(FieldDesc field) => NodeFactory.CopiedFieldRva(field);
644+
public ISymbolNode GetFieldRvaData(FieldDesc field) => NodeFactory.CompilationModuleGroup.IsCompositeBuildMode ? SymbolNodeFactory.PrecodeFieldAddress(field) : NodeFactory.CopiedFieldRva(field);
645645

646646
public override void Dispose()
647647
{

src/coreclr/vm/jitinterface.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14034,6 +14034,21 @@ BOOL LoadDynamicInfoEntry(Module *currentModule,
1403414034
break;
1403514035
#endif // PROFILING_SUPPORTED
1403614036

14037+
case ENCODE_FIELD_ADDRESS:
14038+
{
14039+
FieldDesc *pField = ZapSig::DecodeField(currentModule, pInfoModule, pBlob);
14040+
14041+
pField->GetEnclosingMethodTable()->CheckRestore();
14042+
14043+
// We can only take address of RVA field here as we don't handle scenarios where the static variable may move
14044+
// Also, this cannot be used with a ZapImage as it relies on a separate signatures block as an RVA static
14045+
// address may be unaligned which would interfere with the tagged pointer approach.
14046+
_ASSERTE(currentModule->IsReadyToRun());
14047+
_ASSERTE(pField->IsRVA());
14048+
result = (size_t)pField->GetStaticAddressHandle(NULL);
14049+
}
14050+
break;
14051+
1403714052
case ENCODE_STATIC_FIELD_ADDRESS:
1403814053
{
1403914054
FieldDesc *pField = ZapSig::DecodeField(currentModule, pInfoModule, pBlob);

0 commit comments

Comments
 (0)