Skip to content

Commit e5dcd3c

Browse files
NativeAOT: avoid helper calls for nongc static fields (#79709)
Co-authored-by: SingleAccretion <[email protected]>
1 parent 7ae5f77 commit e5dcd3c

File tree

7 files changed

+59
-48
lines changed

7 files changed

+59
-48
lines changed

src/coreclr/inc/corinfo.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1685,7 +1685,7 @@ enum CORINFO_FIELD_ACCESSOR
16851685
CORINFO_FIELD_STATIC_ADDR_HELPER, // static field accessed using address-of helper (argument is FieldDesc *)
16861686
CORINFO_FIELD_STATIC_TLS, // unmanaged TLS access
16871687
CORINFO_FIELD_STATIC_READYTORUN_HELPER, // static field access using a runtime lookup helper
1688-
1688+
CORINFO_FIELD_STATIC_RELOCATABLE, // static field access using relocation (used in AOT)
16891689
CORINFO_FIELD_INTRINSIC_ZERO, // intrinsic zero (IntPtr.Zero, UIntPtr.Zero)
16901690
CORINFO_FIELD_INTRINSIC_EMPTY_STRING, // intrinsic emptry string (String.Empty)
16911691
CORINFO_FIELD_INTRINSIC_ISLITTLEENDIAN, // intrinsic BitConverter.IsLittleEndian
@@ -1698,7 +1698,6 @@ enum CORINFO_FIELD_FLAGS
16981698
CORINFO_FLG_FIELD_UNMANAGED = 0x00000002, // RVA field
16991699
CORINFO_FLG_FIELD_FINAL = 0x00000004,
17001700
CORINFO_FLG_FIELD_STATIC_IN_HEAP = 0x00000008, // See code:#StaticFields. This static field is in the GC heap as a boxed object
1701-
CORINFO_FLG_FIELD_SAFESTATIC_BYREF_RETURN = 0x00000010, // Field can be returned safely (has GC heap lifetime)
17021701
CORINFO_FLG_FIELD_INITCLASS = 0x00000020, // initClass has to be called before accessing the field
17031702
CORINFO_FLG_FIELD_PROTECTED = 0x00000040,
17041703
};

src/coreclr/inc/jiteeversionguid.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,11 @@ typedef const GUID *LPCGUID;
4343
#define GUID_DEFINED
4444
#endif // !GUID_DEFINED
4545

46-
constexpr GUID JITEEVersionIdentifier = { /* 9c013880-b9b8-4f91-bea4-d4dd4368ab93 */
47-
0x9c013880,
48-
0xb9b8,
49-
0x4f91,
50-
{0xbe, 0xa4, 0xd4, 0xdd, 0x43, 0x68, 0xab, 0x93}
46+
constexpr GUID JITEEVersionIdentifier = { /* 91a3d851-74df-4be2-a270-432a8fab6955 */
47+
0x91a3d851,
48+
0x74df,
49+
0x4be2,
50+
{0xa2, 0x70, 0x43, 0x2a, 0x8f, 0xab, 0x69, 0x55}
5151
};
5252

5353
//////////////////////////////////////////////////////////////////////////////////////////////////////////

src/coreclr/jit/importer.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4235,6 +4235,22 @@ GenTree* Compiler::impImportStaticFieldAccess(CORINFO_RESOLVED_TOKEN* pResolvedT
42354235
break;
42364236
}
42374237

4238+
case CORINFO_FIELD_STATIC_RELOCATABLE:
4239+
{
4240+
#ifdef FEATURE_READYTORUN
4241+
assert(pFieldInfo->fieldLookup.accessType == InfoAccessType::IAT_VALUE);
4242+
assert(fieldKind == FieldSeq::FieldKind::SimpleStatic);
4243+
assert(innerFldSeq != nullptr);
4244+
4245+
GenTree* baseAddr = gtNewIconHandleNode((size_t)pFieldInfo->fieldLookup.addr, GTF_ICON_STATIC_HDL);
4246+
GenTree* offset = gtNewIconNode(pFieldInfo->offset, innerFldSeq);
4247+
op1 = gtNewOperNode(GT_ADD, TYP_I_IMPL, baseAddr, offset);
4248+
#else
4249+
unreached();
4250+
#endif // FEATURE_READYTORUN
4251+
}
4252+
break;
4253+
42384254
case CORINFO_FIELD_STATIC_READYTORUN_HELPER:
42394255
{
42404256
#ifdef FEATURE_READYTORUN
@@ -9260,6 +9276,7 @@ void Compiler::impImportBlockCode(BasicBlock* block)
92609276
case CORINFO_FIELD_STATIC_RVA_ADDRESS:
92619277
case CORINFO_FIELD_STATIC_GENERICS_STATIC_HELPER:
92629278
case CORINFO_FIELD_STATIC_READYTORUN_HELPER:
9279+
case CORINFO_FIELD_STATIC_RELOCATABLE:
92639280
op1 = impImportStaticFieldAccess(&resolvedToken, (CORINFO_ACCESS_FLAGS)aflags, &fieldInfo,
92649281
lclTyp);
92659282
break;
@@ -9510,6 +9527,7 @@ void Compiler::impImportBlockCode(BasicBlock* block)
95109527
case CORINFO_FIELD_STATIC_SHARED_STATIC_HELPER:
95119528
case CORINFO_FIELD_STATIC_GENERICS_STATIC_HELPER:
95129529
case CORINFO_FIELD_STATIC_READYTORUN_HELPER:
9530+
case CORINFO_FIELD_STATIC_RELOCATABLE:
95139531
op1 = impImportStaticFieldAccess(&resolvedToken, (CORINFO_ACCESS_FLAGS)aflags, &fieldInfo,
95149532
lclTyp);
95159533
break;

src/coreclr/jit/valuenum.cpp

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8536,17 +8536,31 @@ void Compiler::fgValueNumberSsaVarDef(GenTreeLclVarCommon* lcl)
85368536
// tree where only one of the constants is expected to have a field sequence.
85378537
//
85388538
// Arguments:
8539-
// vnStore - ValueNumStore object
8540-
// tree - tree node to inspect
8541-
// pAddress - [Out] resulting address with all offsets combined
8542-
// pFseq - [Out] field sequence
8539+
// vnStore - ValueNumStore object
8540+
// tree - tree node to inspect
8541+
// byteOffset - [Out] resulting byte offset
8542+
// pFseq - [Out] field sequence
85438543
//
85448544
// Return Value:
85458545
// true if the given tree is a static field address
85468546
//
8547-
static bool GetStaticFieldSeqAndAddress(ValueNumStore* vnStore, GenTree* tree, ssize_t* pAddress, FieldSeq** pFseq)
8547+
static bool GetStaticFieldSeqAndAddress(ValueNumStore* vnStore, GenTree* tree, ssize_t* byteOffset, FieldSeq** pFseq)
85488548
{
85498549
ssize_t val = 0;
8550+
8551+
// Special case for NativeAOT: ADD(ICON_STATIC, CNS_INT) where CNS_INT has field sequence corresponding to field's
8552+
// offset
8553+
if (tree->OperIs(GT_ADD) && tree->gtGetOp1()->IsIconHandle(GTF_ICON_STATIC_HDL) && tree->gtGetOp2()->IsCnsIntOrI())
8554+
{
8555+
GenTreeIntCon* cns2 = tree->gtGetOp2()->AsIntCon();
8556+
if (cns2->gtFieldSeq != nullptr)
8557+
{
8558+
*byteOffset = cns2->IconValue() - cns2->gtFieldSeq->GetOffset();
8559+
*pFseq = cns2->gtFieldSeq;
8560+
return true;
8561+
}
8562+
}
8563+
85508564
// Accumulate final offset
85518565
while (tree->OperIs(GT_ADD))
85528566
{
@@ -8578,8 +8592,8 @@ static bool GetStaticFieldSeqAndAddress(ValueNumStore* vnStore, GenTree* tree, s
85788592
if ((tree->IsCnsIntOrI()) && (tree->AsIntCon()->gtFieldSeq != nullptr) &&
85798593
(tree->AsIntCon()->gtFieldSeq->GetKind() == FieldSeq::FieldKind::SimpleStaticKnownAddress))
85808594
{
8581-
*pFseq = tree->AsIntCon()->gtFieldSeq;
8582-
*pAddress = tree->AsIntCon()->IconValue() + val;
8595+
*pFseq = tree->AsIntCon()->gtFieldSeq;
8596+
*byteOffset = tree->AsIntCon()->IconValue() + val - tree->AsIntCon()->gtFieldSeq->GetOffset();
85838597
return true;
85848598
}
85858599
return false;
@@ -8608,17 +8622,14 @@ bool Compiler::fgValueNumberConstLoad(GenTreeIndir* tree)
86088622
//
86098623
// sbyte GetVal() => RVA[1]; // fold to '100'
86108624
//
8611-
ssize_t address = 0;
8612-
FieldSeq* fieldSeq = nullptr;
8625+
ssize_t byteOffset = 0;
8626+
FieldSeq* fieldSeq = nullptr;
86138627
if ((varTypeIsIntegral(tree) || varTypeIsFloating(tree)) &&
8614-
GetStaticFieldSeqAndAddress(vnStore, tree->gtGetOp1(), &address, &fieldSeq))
8628+
GetStaticFieldSeqAndAddress(vnStore, tree->gtGetOp1(), &byteOffset, &fieldSeq))
86158629
{
8616-
assert(fieldSeq->GetKind() == FieldSeq::FieldKind::SimpleStaticKnownAddress);
8617-
CORINFO_FIELD_HANDLE fieldHandle = fieldSeq->GetFieldHandle();
8618-
8619-
ssize_t byteOffset = address - fieldSeq->GetOffset();
8620-
int size = (int)genTypeSize(tree->TypeGet());
8621-
const int maxElementSize = sizeof(int64_t);
8630+
CORINFO_FIELD_HANDLE fieldHandle = fieldSeq->GetFieldHandle();
8631+
int size = (int)genTypeSize(tree->TypeGet());
8632+
const int maxElementSize = sizeof(int64_t);
86228633
if ((fieldHandle != nullptr) && (size > 0) && (size <= maxElementSize) && ((size_t)byteOffset < INT_MAX))
86238634
{
86248635
uint8_t buffer[maxElementSize] = {0};

src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1115,7 +1115,7 @@ public enum CORINFO_FIELD_ACCESSOR
11151115
CORINFO_FIELD_STATIC_ADDR_HELPER, // static field accessed using address-of helper (argument is FieldDesc *)
11161116
CORINFO_FIELD_STATIC_TLS, // unmanaged TLS access
11171117
CORINFO_FIELD_STATIC_READYTORUN_HELPER, // static field access using a runtime lookup helper
1118-
1118+
CORINFO_FIELD_STATIC_RELOCATABLE, // static field access from the data segment
11191119
CORINFO_FIELD_INTRINSIC_ZERO, // intrinsic zero (IntPtr.Zero, UIntPtr.Zero)
11201120
CORINFO_FIELD_INTRINSIC_EMPTY_STRING, // intrinsic emptry string (String.Empty)
11211121
CORINFO_FIELD_INTRINSIC_ISLITTLEENDIAN, // intrinsic BitConverter.IsLittleEndian
@@ -1128,7 +1128,6 @@ public enum CORINFO_FIELD_FLAGS
11281128
CORINFO_FLG_FIELD_UNMANAGED = 0x00000002, // RVA field
11291129
CORINFO_FLG_FIELD_FINAL = 0x00000004,
11301130
CORINFO_FLG_FIELD_STATIC_IN_HEAP = 0x00000008, // See code:#StaticFields. This static field is in the GC heap as a boxed object
1131-
CORINFO_FLG_FIELD_SAFESTATIC_BYREF_RETURN = 0x00000010, // Field can be returned safely (has GC heap lifetime)
11321131
CORINFO_FLG_FIELD_INITCLASS = 0x00000020, // initClass has to be called before accessing the field
11331132
CORINFO_FLG_FIELD_PROTECTED = 0x00000040,
11341133
}

src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2141,6 +2141,13 @@ private void getFieldInfo(ref CORINFO_RESOLVED_TOKEN pResolvedToken, CORINFO_MET
21412141
pResult->helper = CorInfoHelpFunc.CORINFO_HELP_READYTORUN_THREADSTATIC_BASE;
21422142
helperId = ReadyToRunHelperId.GetThreadStaticBase;
21432143
}
2144+
else if (!_compilation.HasLazyStaticConstructor(field.OwningType) && !field.HasGCStaticBase)
2145+
{
2146+
fieldAccessor = CORINFO_FIELD_ACCESSOR.CORINFO_FIELD_STATIC_RELOCATABLE;
2147+
ISymbolNode baseAddress = _compilation.NodeFactory.TypeNonGCStaticsSymbol((MetadataType)field.OwningType);
2148+
pResult->fieldLookup.accessType = InfoAccessType.IAT_VALUE;
2149+
pResult->fieldLookup.addr = (void*)ObjectToHandle(baseAddress);
2150+
}
21442151
else
21452152
{
21462153
if (field.HasGCStaticBase)
@@ -2153,17 +2160,6 @@ private void getFieldInfo(ref CORINFO_RESOLVED_TOKEN pResolvedToken, CORINFO_MET
21532160
pResult->helper = CorInfoHelpFunc.CORINFO_HELP_READYTORUN_NONGCSTATIC_BASE;
21542161
helperId = ReadyToRunHelperId.GetNonGCStaticBase;
21552162
}
2156-
2157-
//
2158-
// Currently, we only do this optimization for regular statics, but it
2159-
// looks like it may be permissible to do this optimization for
2160-
// thread statics as well.
2161-
//
2162-
if ((flags & CORINFO_ACCESS_FLAGS.CORINFO_ACCESS_ADDRESS) != 0 &&
2163-
(fieldAccessor != CORINFO_FIELD_ACCESSOR.CORINFO_FIELD_STATIC_TLS))
2164-
{
2165-
fieldFlags |= CORINFO_FIELD_FLAGS.CORINFO_FLG_FIELD_SAFESTATIC_BYREF_RETURN;
2166-
}
21672163
}
21682164

21692165
if (helperId != ReadyToRunHelperId.Invalid)

src/coreclr/vm/jitinterface.cpp

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1576,18 +1576,6 @@ void CEEInfo::getFieldInfo (CORINFO_RESOLVED_TOKEN * pResolvedToken,
15761576
}
15771577
}
15781578
}
1579-
1580-
//
1581-
// Currently, we only this optimization for regular statics, but it
1582-
// looks like it may be permissible to do this optimization for
1583-
// thread statics as well.
1584-
//
1585-
if ((flags & CORINFO_ACCESS_ADDRESS) &&
1586-
!pField->IsThreadStatic() &&
1587-
(fieldAccessor != CORINFO_FIELD_STATIC_TLS))
1588-
{
1589-
fieldFlags |= CORINFO_FLG_FIELD_SAFESTATIC_BYREF_RETURN;
1590-
}
15911579
}
15921580
else
15931581
{

0 commit comments

Comments
 (0)