Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NativeAOT: avoid helper calls for static fields #79709

Merged
merged 14 commits into from
Jan 21, 2023
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
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
3 changes: 1 addition & 2 deletions src/coreclr/inc/corinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -1685,7 +1685,7 @@ enum CORINFO_FIELD_ACCESSOR
CORINFO_FIELD_STATIC_ADDR_HELPER, // static field accessed using address-of helper (argument is FieldDesc *)
CORINFO_FIELD_STATIC_TLS, // unmanaged TLS access
CORINFO_FIELD_STATIC_READYTORUN_HELPER, // static field access using a runtime lookup helper

CORINFO_FIELD_STATIC_RELOCATABLE, // static field access using relocation (used in AOT)
CORINFO_FIELD_INTRINSIC_ZERO, // intrinsic zero (IntPtr.Zero, UIntPtr.Zero)
CORINFO_FIELD_INTRINSIC_EMPTY_STRING, // intrinsic emptry string (String.Empty)
CORINFO_FIELD_INTRINSIC_ISLITTLEENDIAN, // intrinsic BitConverter.IsLittleEndian
Expand All @@ -1698,7 +1698,6 @@ enum CORINFO_FIELD_FLAGS
CORINFO_FLG_FIELD_UNMANAGED = 0x00000002, // RVA field
CORINFO_FLG_FIELD_FINAL = 0x00000004,
CORINFO_FLG_FIELD_STATIC_IN_HEAP = 0x00000008, // See code:#StaticFields. This static field is in the GC heap as a boxed object
CORINFO_FLG_FIELD_SAFESTATIC_BYREF_RETURN = 0x00000010, // Field can be returned safely (has GC heap lifetime)
CORINFO_FLG_FIELD_INITCLASS = 0x00000020, // initClass has to be called before accessing the field
CORINFO_FLG_FIELD_PROTECTED = 0x00000040,
};
Expand Down
10 changes: 5 additions & 5 deletions src/coreclr/inc/jiteeversionguid.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,11 @@ typedef const GUID *LPCGUID;
#define GUID_DEFINED
#endif // !GUID_DEFINED

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

//////////////////////////////////////////////////////////////////////////////////////////////////////////
Expand Down
18 changes: 18 additions & 0 deletions src/coreclr/jit/importer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4235,6 +4235,22 @@ GenTree* Compiler::impImportStaticFieldAccess(CORINFO_RESOLVED_TOKEN* pResolvedT
break;
}

case CORINFO_FIELD_STATIC_RELOCATABLE:
{
#ifdef FEATURE_READYTORUN
assert(pFieldInfo->fieldLookup.accessType == InfoAccessType::IAT_VALUE);
assert(fieldKind == FieldSeq::FieldKind::SimpleStatic);
assert(innerFldSeq != nullptr);

GenTree* baseAddr = gtNewIconHandleNode((size_t)pFieldInfo->fieldLookup.addr, GTF_ICON_STATIC_HDL);
GenTree* offset = gtNewIconNode(pFieldInfo->offset, innerFldSeq);
op1 = gtNewOperNode(GT_ADD, TYP_I_IMPL, baseAddr, offset);
#else
unreached();
#endif // FEATURE_READYTORUN
}
break;

case CORINFO_FIELD_STATIC_READYTORUN_HELPER:
{
#ifdef FEATURE_READYTORUN
Expand Down Expand Up @@ -9237,6 +9253,7 @@ void Compiler::impImportBlockCode(BasicBlock* block)
case CORINFO_FIELD_STATIC_RVA_ADDRESS:
case CORINFO_FIELD_STATIC_GENERICS_STATIC_HELPER:
case CORINFO_FIELD_STATIC_READYTORUN_HELPER:
case CORINFO_FIELD_STATIC_RELOCATABLE:
op1 = impImportStaticFieldAccess(&resolvedToken, (CORINFO_ACCESS_FLAGS)aflags, &fieldInfo,
lclTyp);
break;
Expand Down Expand Up @@ -9487,6 +9504,7 @@ void Compiler::impImportBlockCode(BasicBlock* block)
case CORINFO_FIELD_STATIC_SHARED_STATIC_HELPER:
case CORINFO_FIELD_STATIC_GENERICS_STATIC_HELPER:
case CORINFO_FIELD_STATIC_READYTORUN_HELPER:
case CORINFO_FIELD_STATIC_RELOCATABLE:
op1 = impImportStaticFieldAccess(&resolvedToken, (CORINFO_ACCESS_FLAGS)aflags, &fieldInfo,
lclTyp);
break;
Expand Down
27 changes: 25 additions & 2 deletions src/coreclr/jit/valuenum.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8547,6 +8547,21 @@ void Compiler::fgValueNumberSsaVarDef(GenTreeLclVarCommon* lcl)
static bool GetStaticFieldSeqAndAddress(ValueNumStore* vnStore, GenTree* tree, ssize_t* pAddress, FieldSeq** pFseq)
{
ssize_t val = 0;

// Special case for NativeAOT: ADD(ICON_STATIC, CNS_INT) where CNS_INT has field sequence corresponding to field's
// offset
if (tree->OperIs(GT_ADD) && tree->gtGetOp1()->IsIconHandle(GTF_ICON_STATIC_HDL) && tree->gtGetOp2()->IsCnsIntOrI())
{
GenTreeIntCon* cns1 = tree->gtGetOp1()->AsIntCon();
GenTreeIntCon* cns2 = tree->gtGetOp2()->AsIntCon();
if (cns2->gtFieldSeq != nullptr)
{
*pAddress = -1;
*pFseq = cns2->gtFieldSeq;
return true;
}
}

// Accumulate final offset
while (tree->OperIs(GT_ADD))
{
Expand Down Expand Up @@ -8612,10 +8627,18 @@ bool Compiler::fgValueNumberConstLoad(GenTreeIndir* tree)
FieldSeq* fieldSeq = nullptr;
if (varTypeIsIntegral(tree) && GetStaticFieldSeqAndAddress(vnStore, tree->gtGetOp1(), &address, &fieldSeq))
{
assert(fieldSeq->GetKind() == FieldSeq::FieldKind::SimpleStaticKnownAddress);
CORINFO_FIELD_HANDLE fieldHandle = fieldSeq->GetFieldHandle();
ssize_t byteOffset = 0;
if (fieldSeq->GetKind() == FieldSeq::FieldKind::SimpleStaticKnownAddress)
{
byteOffset = address - fieldSeq->GetOffset();
}
else
{
assert(address == -1);
assert(fieldSeq->GetKind() == FieldSeq::FieldKind::SimpleStatic);
}

ssize_t byteOffset = address - fieldSeq->GetOffset();
int size = (int)genTypeSize(tree->TypeGet());
const int maxElementSize = sizeof(int64_t);
if ((fieldHandle != nullptr) && (size > 0) && (size <= maxElementSize) && ((size_t)byteOffset < INT_MAX))
Expand Down
3 changes: 1 addition & 2 deletions src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1115,7 +1115,7 @@ public enum CORINFO_FIELD_ACCESSOR
CORINFO_FIELD_STATIC_ADDR_HELPER, // static field accessed using address-of helper (argument is FieldDesc *)
CORINFO_FIELD_STATIC_TLS, // unmanaged TLS access
CORINFO_FIELD_STATIC_READYTORUN_HELPER, // static field access using a runtime lookup helper

CORINFO_FIELD_STATIC_RELOCATABLE, // static field access from the data segment
CORINFO_FIELD_INTRINSIC_ZERO, // intrinsic zero (IntPtr.Zero, UIntPtr.Zero)
CORINFO_FIELD_INTRINSIC_EMPTY_STRING, // intrinsic emptry string (String.Empty)
CORINFO_FIELD_INTRINSIC_ISLITTLEENDIAN, // intrinsic BitConverter.IsLittleEndian
Expand All @@ -1128,7 +1128,6 @@ public enum CORINFO_FIELD_FLAGS
CORINFO_FLG_FIELD_UNMANAGED = 0x00000002, // RVA field
CORINFO_FLG_FIELD_FINAL = 0x00000004,
CORINFO_FLG_FIELD_STATIC_IN_HEAP = 0x00000008, // See code:#StaticFields. This static field is in the GC heap as a boxed object
CORINFO_FLG_FIELD_SAFESTATIC_BYREF_RETURN = 0x00000010, // Field can be returned safely (has GC heap lifetime)
CORINFO_FLG_FIELD_INITCLASS = 0x00000020, // initClass has to be called before accessing the field
CORINFO_FLG_FIELD_PROTECTED = 0x00000040,
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2141,6 +2141,13 @@ private void getFieldInfo(ref CORINFO_RESOLVED_TOKEN pResolvedToken, CORINFO_MET
pResult->helper = CorInfoHelpFunc.CORINFO_HELP_READYTORUN_THREADSTATIC_BASE;
helperId = ReadyToRunHelperId.GetThreadStaticBase;
}
else if (!_compilation.HasLazyStaticConstructor(field.OwningType) && !field.HasGCStaticBase)
{
fieldAccessor = CORINFO_FIELD_ACCESSOR.CORINFO_FIELD_STATIC_RELOCATABLE;
ISymbolNode baseAddress = _compilation.NodeFactory.TypeNonGCStaticsSymbol((MetadataType)field.OwningType);
pResult->fieldLookup.accessType = InfoAccessType.IAT_VALUE;
pResult->fieldLookup.addr = (void*)ObjectToHandle(baseAddress);
}
else
{
if (field.HasGCStaticBase)
Expand All @@ -2153,17 +2160,6 @@ private void getFieldInfo(ref CORINFO_RESOLVED_TOKEN pResolvedToken, CORINFO_MET
pResult->helper = CorInfoHelpFunc.CORINFO_HELP_READYTORUN_NONGCSTATIC_BASE;
helperId = ReadyToRunHelperId.GetNonGCStaticBase;
}

//
// Currently, we only do this optimization for regular statics, but it
// looks like it may be permissible to do this optimization for
// thread statics as well.
//
if ((flags & CORINFO_ACCESS_FLAGS.CORINFO_ACCESS_ADDRESS) != 0 &&
(fieldAccessor != CORINFO_FIELD_ACCESSOR.CORINFO_FIELD_STATIC_TLS))
{
fieldFlags |= CORINFO_FIELD_FLAGS.CORINFO_FLG_FIELD_SAFESTATIC_BYREF_RETURN;
}
}

if (helperId != ReadyToRunHelperId.Invalid)
Expand Down
12 changes: 0 additions & 12 deletions src/coreclr/vm/jitinterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1576,18 +1576,6 @@ void CEEInfo::getFieldInfo (CORINFO_RESOLVED_TOKEN * pResolvedToken,
}
}
}

//
// Currently, we only this optimization for regular statics, but it
// looks like it may be permissible to do this optimization for
// thread statics as well.
//
if ((flags & CORINFO_ACCESS_ADDRESS) &&
!pField->IsThreadStatic() &&
(fieldAccessor != CORINFO_FIELD_STATIC_TLS))
{
fieldFlags |= CORINFO_FLG_FIELD_SAFESTATIC_BYREF_RETURN;
}
}
else
{
Expand Down