Skip to content

Commit 8c10a98

Browse files
authored
Move getFieldInfo to CorInfoImpl.ReadyToRun (#32159)
1 parent 659aec4 commit 8c10a98

2 files changed

Lines changed: 149 additions & 215 deletions

File tree

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

Lines changed: 0 additions & 215 deletions
Original file line numberDiff line numberDiff line change
@@ -2061,221 +2061,6 @@ private CORINFO_FIELD_ACCESSOR getFieldIntrinsic(FieldDesc field)
20612061
return (CORINFO_FIELD_ACCESSOR)(-1);
20622062
}
20632063

2064-
private void getFieldInfo(ref CORINFO_RESOLVED_TOKEN pResolvedToken, CORINFO_METHOD_STRUCT_* callerHandle, CORINFO_ACCESS_FLAGS flags, CORINFO_FIELD_INFO* pResult)
2065-
{
2066-
#if DEBUG
2067-
// In debug, write some bogus data to the struct to ensure we have filled everything
2068-
// properly.
2069-
MemoryHelper.FillMemory((byte*)pResult, 0xcc, Marshal.SizeOf<CORINFO_FIELD_INFO>());
2070-
#endif
2071-
2072-
Debug.Assert(((int)flags & ((int)CORINFO_ACCESS_FLAGS.CORINFO_ACCESS_GET |
2073-
(int)CORINFO_ACCESS_FLAGS.CORINFO_ACCESS_SET |
2074-
(int)CORINFO_ACCESS_FLAGS.CORINFO_ACCESS_ADDRESS |
2075-
(int)CORINFO_ACCESS_FLAGS.CORINFO_ACCESS_INIT_ARRAY)) != 0);
2076-
2077-
var field = HandleToObject(pResolvedToken.hField);
2078-
#if READYTORUN
2079-
MethodDesc callerMethod = HandleToObject(callerHandle);
2080-
2081-
if (field.Offset.IsIndeterminate)
2082-
throw new RequiresRuntimeJitException(field);
2083-
#endif
2084-
2085-
CORINFO_FIELD_ACCESSOR fieldAccessor;
2086-
CORINFO_FIELD_FLAGS fieldFlags = (CORINFO_FIELD_FLAGS)0;
2087-
uint fieldOffset = (field.IsStatic && field.HasRva ? 0xBAADF00D : (uint)field.Offset.AsInt);
2088-
2089-
if (field.IsStatic)
2090-
{
2091-
fieldFlags |= CORINFO_FIELD_FLAGS.CORINFO_FLG_FIELD_STATIC;
2092-
2093-
#if READYTORUN
2094-
if (field.FieldType.IsValueType && field.HasGCStaticBase && !field.HasRva)
2095-
{
2096-
// statics of struct types are stored as implicitly boxed in CoreCLR i.e.
2097-
// we need to modify field access flags appropriately
2098-
fieldFlags |= CORINFO_FIELD_FLAGS.CORINFO_FLG_FIELD_STATIC_IN_HEAP;
2099-
}
2100-
#endif
2101-
2102-
if (field.HasRva)
2103-
{
2104-
fieldFlags |= CORINFO_FIELD_FLAGS.CORINFO_FLG_FIELD_UNMANAGED;
2105-
2106-
// TODO: Handle the case when the RVA is in the TLS range
2107-
fieldAccessor = CORINFO_FIELD_ACCESSOR.CORINFO_FIELD_STATIC_RVA_ADDRESS;
2108-
2109-
// We are not going through a helper. The constructor has to be triggered explicitly.
2110-
#if READYTORUN
2111-
if (!IsClassPreInited(field.OwningType))
2112-
#else
2113-
if (_compilation.HasLazyStaticConstructor(field.OwningType))
2114-
#endif
2115-
{
2116-
fieldFlags |= CORINFO_FIELD_FLAGS.CORINFO_FLG_FIELD_INITCLASS;
2117-
}
2118-
}
2119-
else if (field.OwningType.IsCanonicalSubtype(CanonicalFormKind.Any))
2120-
{
2121-
// The JIT wants to know how to access a static field on a generic type. We need a runtime lookup.
2122-
#if READYTORUN
2123-
fieldAccessor = CORINFO_FIELD_ACCESSOR.CORINFO_FIELD_STATIC_GENERICS_STATIC_HELPER;
2124-
if (field.IsThreadStatic)
2125-
{
2126-
pResult->helper = (field.HasGCStaticBase ?
2127-
CorInfoHelpFunc.CORINFO_HELP_GETGENERICS_GCTHREADSTATIC_BASE:
2128-
CorInfoHelpFunc.CORINFO_HELP_GETGENERICS_NONGCTHREADSTATIC_BASE);
2129-
}
2130-
else
2131-
{
2132-
pResult->helper = (field.HasGCStaticBase ?
2133-
CorInfoHelpFunc.CORINFO_HELP_GETGENERICS_GCSTATIC_BASE:
2134-
CorInfoHelpFunc.CORINFO_HELP_GETGENERICS_NONGCSTATIC_BASE);
2135-
}
2136-
#else
2137-
fieldAccessor = CORINFO_FIELD_ACCESSOR.CORINFO_FIELD_STATIC_READYTORUN_HELPER;
2138-
pResult->helper = CorInfoHelpFunc.CORINFO_HELP_READYTORUN_GENERIC_STATIC_BASE;
2139-
2140-
// Don't try to compute the runtime lookup if we're inlining. The JIT is going to abort the inlining
2141-
// attempt anyway.
2142-
MethodDesc contextMethod = methodFromContext(pResolvedToken.tokenContext);
2143-
if (contextMethod == MethodBeingCompiled)
2144-
{
2145-
FieldDesc runtimeDeterminedField = (FieldDesc)GetRuntimeDeterminedObjectForToken(ref pResolvedToken);
2146-
2147-
ReadyToRunHelperId helperId;
2148-
2149-
// Find out what kind of base do we need to look up.
2150-
if (field.IsThreadStatic)
2151-
{
2152-
helperId = ReadyToRunHelperId.GetThreadStaticBase;
2153-
}
2154-
else if (field.HasGCStaticBase)
2155-
{
2156-
helperId = ReadyToRunHelperId.GetGCStaticBase;
2157-
}
2158-
else
2159-
{
2160-
helperId = ReadyToRunHelperId.GetNonGCStaticBase;
2161-
}
2162-
2163-
// What generic context do we look up the base from.
2164-
ISymbolNode helper;
2165-
if (contextMethod.AcquiresInstMethodTableFromThis() || contextMethod.RequiresInstMethodTableArg())
2166-
{
2167-
helper = _compilation.NodeFactory.ReadyToRunHelperFromTypeLookup(
2168-
helperId, runtimeDeterminedField.OwningType, contextMethod.OwningType);
2169-
}
2170-
else
2171-
{
2172-
Debug.Assert(contextMethod.RequiresInstMethodDescArg());
2173-
helper = _compilation.NodeFactory.ReadyToRunHelperFromDictionaryLookup(
2174-
helperId, runtimeDeterminedField.OwningType, contextMethod);
2175-
}
2176-
2177-
pResult->fieldLookup = CreateConstLookupToSymbol(helper);
2178-
}
2179-
#endif // READYTORUN
2180-
}
2181-
else
2182-
{
2183-
fieldAccessor = CORINFO_FIELD_ACCESSOR.CORINFO_FIELD_STATIC_SHARED_STATIC_HELPER;
2184-
pResult->helper = CorInfoHelpFunc.CORINFO_HELP_READYTORUN_STATIC_BASE;
2185-
2186-
ReadyToRunHelperId helperId = ReadyToRunHelperId.Invalid;
2187-
CORINFO_FIELD_ACCESSOR intrinsicAccessor;
2188-
if (field.IsIntrinsic &&
2189-
(flags & CORINFO_ACCESS_FLAGS.CORINFO_ACCESS_GET) != 0 &&
2190-
(intrinsicAccessor = getFieldIntrinsic(field)) != (CORINFO_FIELD_ACCESSOR)(-1))
2191-
{
2192-
fieldAccessor = intrinsicAccessor;
2193-
}
2194-
else if (field.IsThreadStatic)
2195-
{
2196-
#if READYTORUN
2197-
if (field.HasGCStaticBase)
2198-
{
2199-
helperId = ReadyToRunHelperId.GetThreadStaticBase;
2200-
}
2201-
else
2202-
{
2203-
helperId = ReadyToRunHelperId.GetThreadNonGcStaticBase;
2204-
}
2205-
#else
2206-
helperId = ReadyToRunHelperId.GetThreadStaticBase;
2207-
#endif
2208-
}
2209-
else
2210-
{
2211-
helperId = field.HasGCStaticBase ?
2212-
ReadyToRunHelperId.GetGCStaticBase :
2213-
ReadyToRunHelperId.GetNonGCStaticBase;
2214-
2215-
//
2216-
// Currently, we only do this optimization for regular statics, but it
2217-
// looks like it may be permissible to do this optimization for
2218-
// thread statics as well.
2219-
//
2220-
if ((flags & CORINFO_ACCESS_FLAGS.CORINFO_ACCESS_ADDRESS) != 0 &&
2221-
(fieldAccessor != CORINFO_FIELD_ACCESSOR.CORINFO_FIELD_STATIC_TLS))
2222-
{
2223-
fieldFlags |= CORINFO_FIELD_FLAGS.CORINFO_FLG_FIELD_SAFESTATIC_BYREF_RETURN;
2224-
}
2225-
}
2226-
2227-
#if READYTORUN
2228-
if (!_compilation.NodeFactory.CompilationModuleGroup.VersionsWithType(field.OwningType) &&
2229-
fieldAccessor == CORINFO_FIELD_ACCESSOR.CORINFO_FIELD_STATIC_SHARED_STATIC_HELPER)
2230-
{
2231-
PreventRecursiveFieldInlinesOutsideVersionBubble(field, callerMethod);
2232-
2233-
// Static fields outside of the version bubble need to be accessed using the ENCODE_FIELD_ADDRESS
2234-
// helper in accordance with ZapInfo::getFieldInfo in CoreCLR.
2235-
pResult->fieldLookup = CreateConstLookupToSymbol(_compilation.SymbolNodeFactory.FieldAddress(field));
2236-
2237-
pResult->helper = CorInfoHelpFunc.CORINFO_HELP_READYTORUN_STATIC_BASE;
2238-
2239-
fieldFlags &= ~CORINFO_FIELD_FLAGS.CORINFO_FLG_FIELD_STATIC_IN_HEAP; // The dynamic helper takes care of the unboxing
2240-
fieldOffset = 0;
2241-
}
2242-
else
2243-
#endif
2244-
2245-
if (helperId != ReadyToRunHelperId.Invalid)
2246-
{
2247-
pResult->fieldLookup = CreateConstLookupToSymbol(
2248-
#if READYTORUN
2249-
_compilation.SymbolNodeFactory.CreateReadyToRunHelper(helperId, field.OwningType)
2250-
#else
2251-
_compilation.NodeFactory.ReadyToRunHelper(helperId, field.OwningType)
2252-
#endif
2253-
);
2254-
}
2255-
}
2256-
}
2257-
else
2258-
{
2259-
fieldAccessor = CORINFO_FIELD_ACCESSOR.CORINFO_FIELD_INSTANCE;
2260-
}
2261-
2262-
if (field.IsInitOnly)
2263-
fieldFlags |= CORINFO_FIELD_FLAGS.CORINFO_FLG_FIELD_FINAL;
2264-
2265-
pResult->fieldAccessor = fieldAccessor;
2266-
pResult->fieldFlags = fieldFlags;
2267-
pResult->fieldType = getFieldType(pResolvedToken.hField, &pResult->structType, pResolvedToken.hClass);
2268-
pResult->accessAllowed = CorInfoIsAccessAllowedResult.CORINFO_ACCESS_ALLOWED;
2269-
pResult->offset = fieldOffset;
2270-
2271-
#if READYTORUN
2272-
EncodeFieldBaseOffset(field, pResult, callerMethod);
2273-
#endif
2274-
2275-
// TODO: We need to implement access checks for fields and methods. See JitInterface.cpp in mrtjit
2276-
// and STS::AccessCheck::CanAccess.
2277-
}
2278-
22792064
private bool isFieldStatic(CORINFO_FIELD_STRUCT_* fldHnd)
22802065
{
22812066
return HandleToObject(fldHnd).IsStatic;

src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -921,6 +921,155 @@ private bool IsGenericTooDeeplyNested(Instantiation instantiation)
921921
return IsGenericTooDeeplyNested(instantiation, 0);
922922
}
923923

924+
private void getFieldInfo(ref CORINFO_RESOLVED_TOKEN pResolvedToken, CORINFO_METHOD_STRUCT_* callerHandle, CORINFO_ACCESS_FLAGS flags, CORINFO_FIELD_INFO* pResult)
925+
{
926+
#if DEBUG
927+
// In debug, write some bogus data to the struct to ensure we have filled everything
928+
// properly.
929+
MemoryHelper.FillMemory((byte*)pResult, 0xcc, Marshal.SizeOf<CORINFO_FIELD_INFO>());
930+
#endif
931+
932+
Debug.Assert(((int)flags & ((int)CORINFO_ACCESS_FLAGS.CORINFO_ACCESS_GET |
933+
(int)CORINFO_ACCESS_FLAGS.CORINFO_ACCESS_SET |
934+
(int)CORINFO_ACCESS_FLAGS.CORINFO_ACCESS_ADDRESS |
935+
(int)CORINFO_ACCESS_FLAGS.CORINFO_ACCESS_INIT_ARRAY)) != 0);
936+
937+
var field = HandleToObject(pResolvedToken.hField);
938+
MethodDesc callerMethod = HandleToObject(callerHandle);
939+
940+
if (field.Offset.IsIndeterminate)
941+
throw new RequiresRuntimeJitException(field);
942+
943+
CORINFO_FIELD_ACCESSOR fieldAccessor;
944+
CORINFO_FIELD_FLAGS fieldFlags = (CORINFO_FIELD_FLAGS)0;
945+
uint fieldOffset = (field.IsStatic && field.HasRva ? 0xBAADF00D : (uint)field.Offset.AsInt);
946+
947+
if (field.IsStatic)
948+
{
949+
fieldFlags |= CORINFO_FIELD_FLAGS.CORINFO_FLG_FIELD_STATIC;
950+
951+
if (field.FieldType.IsValueType && field.HasGCStaticBase && !field.HasRva)
952+
{
953+
// statics of struct types are stored as implicitly boxed in CoreCLR i.e.
954+
// we need to modify field access flags appropriately
955+
fieldFlags |= CORINFO_FIELD_FLAGS.CORINFO_FLG_FIELD_STATIC_IN_HEAP;
956+
}
957+
958+
if (field.HasRva)
959+
{
960+
fieldFlags |= CORINFO_FIELD_FLAGS.CORINFO_FLG_FIELD_UNMANAGED;
961+
962+
// TODO: Handle the case when the RVA is in the TLS range
963+
fieldAccessor = CORINFO_FIELD_ACCESSOR.CORINFO_FIELD_STATIC_RVA_ADDRESS;
964+
965+
// We are not going through a helper. The constructor has to be triggered explicitly.
966+
if (!IsClassPreInited(field.OwningType))
967+
{
968+
fieldFlags |= CORINFO_FIELD_FLAGS.CORINFO_FLG_FIELD_INITCLASS;
969+
}
970+
}
971+
else if (field.OwningType.IsCanonicalSubtype(CanonicalFormKind.Any))
972+
{
973+
// The JIT wants to know how to access a static field on a generic type. We need a runtime lookup.
974+
fieldAccessor = CORINFO_FIELD_ACCESSOR.CORINFO_FIELD_STATIC_GENERICS_STATIC_HELPER;
975+
if (field.IsThreadStatic)
976+
{
977+
pResult->helper = (field.HasGCStaticBase ?
978+
CorInfoHelpFunc.CORINFO_HELP_GETGENERICS_GCTHREADSTATIC_BASE :
979+
CorInfoHelpFunc.CORINFO_HELP_GETGENERICS_NONGCTHREADSTATIC_BASE);
980+
}
981+
else
982+
{
983+
pResult->helper = (field.HasGCStaticBase ?
984+
CorInfoHelpFunc.CORINFO_HELP_GETGENERICS_GCSTATIC_BASE :
985+
CorInfoHelpFunc.CORINFO_HELP_GETGENERICS_NONGCSTATIC_BASE);
986+
}
987+
}
988+
else
989+
{
990+
fieldAccessor = CORINFO_FIELD_ACCESSOR.CORINFO_FIELD_STATIC_SHARED_STATIC_HELPER;
991+
pResult->helper = CorInfoHelpFunc.CORINFO_HELP_READYTORUN_STATIC_BASE;
992+
993+
ReadyToRunHelperId helperId = ReadyToRunHelperId.Invalid;
994+
CORINFO_FIELD_ACCESSOR intrinsicAccessor;
995+
if (field.IsIntrinsic &&
996+
(flags & CORINFO_ACCESS_FLAGS.CORINFO_ACCESS_GET) != 0 &&
997+
(intrinsicAccessor = getFieldIntrinsic(field)) != (CORINFO_FIELD_ACCESSOR)(-1))
998+
{
999+
fieldAccessor = intrinsicAccessor;
1000+
}
1001+
else if (field.IsThreadStatic)
1002+
{
1003+
if (field.HasGCStaticBase)
1004+
{
1005+
helperId = ReadyToRunHelperId.GetThreadStaticBase;
1006+
}
1007+
else
1008+
{
1009+
helperId = ReadyToRunHelperId.GetThreadNonGcStaticBase;
1010+
}
1011+
}
1012+
else
1013+
{
1014+
helperId = field.HasGCStaticBase ?
1015+
ReadyToRunHelperId.GetGCStaticBase :
1016+
ReadyToRunHelperId.GetNonGCStaticBase;
1017+
1018+
//
1019+
// Currently, we only do this optimization for regular statics, but it
1020+
// looks like it may be permissible to do this optimization for
1021+
// thread statics as well.
1022+
//
1023+
if ((flags & CORINFO_ACCESS_FLAGS.CORINFO_ACCESS_ADDRESS) != 0 &&
1024+
(fieldAccessor != CORINFO_FIELD_ACCESSOR.CORINFO_FIELD_STATIC_TLS))
1025+
{
1026+
fieldFlags |= CORINFO_FIELD_FLAGS.CORINFO_FLG_FIELD_SAFESTATIC_BYREF_RETURN;
1027+
}
1028+
}
1029+
1030+
if (!_compilation.NodeFactory.CompilationModuleGroup.VersionsWithType(field.OwningType) &&
1031+
fieldAccessor == CORINFO_FIELD_ACCESSOR.CORINFO_FIELD_STATIC_SHARED_STATIC_HELPER)
1032+
{
1033+
PreventRecursiveFieldInlinesOutsideVersionBubble(field, callerMethod);
1034+
1035+
// Static fields outside of the version bubble need to be accessed using the ENCODE_FIELD_ADDRESS
1036+
// helper in accordance with ZapInfo::getFieldInfo in CoreCLR.
1037+
pResult->fieldLookup = CreateConstLookupToSymbol(_compilation.SymbolNodeFactory.FieldAddress(field));
1038+
1039+
pResult->helper = CorInfoHelpFunc.CORINFO_HELP_READYTORUN_STATIC_BASE;
1040+
1041+
fieldFlags &= ~CORINFO_FIELD_FLAGS.CORINFO_FLG_FIELD_STATIC_IN_HEAP; // The dynamic helper takes care of the unboxing
1042+
fieldOffset = 0;
1043+
}
1044+
else
1045+
if (helperId != ReadyToRunHelperId.Invalid)
1046+
{
1047+
pResult->fieldLookup = CreateConstLookupToSymbol(
1048+
_compilation.SymbolNodeFactory.CreateReadyToRunHelper(helperId, field.OwningType)
1049+
);
1050+
}
1051+
}
1052+
}
1053+
else
1054+
{
1055+
fieldAccessor = CORINFO_FIELD_ACCESSOR.CORINFO_FIELD_INSTANCE;
1056+
}
1057+
1058+
if (field.IsInitOnly)
1059+
fieldFlags |= CORINFO_FIELD_FLAGS.CORINFO_FLG_FIELD_FINAL;
1060+
1061+
pResult->fieldAccessor = fieldAccessor;
1062+
pResult->fieldFlags = fieldFlags;
1063+
pResult->fieldType = getFieldType(pResolvedToken.hField, &pResult->structType, pResolvedToken.hClass);
1064+
pResult->accessAllowed = CorInfoIsAccessAllowedResult.CORINFO_ACCESS_ALLOWED;
1065+
pResult->offset = fieldOffset;
1066+
1067+
EncodeFieldBaseOffset(field, pResult, callerMethod);
1068+
1069+
// TODO: We need to implement access checks for fields and methods. See JitInterface.cpp in mrtjit
1070+
// and STS::AccessCheck::CanAccess.
1071+
}
1072+
9241073
private void ceeInfoGetCallInfo(
9251074
ref CORINFO_RESOLVED_TOKEN pResolvedToken,
9261075
CORINFO_RESOLVED_TOKEN* pConstrainedResolvedToken,

0 commit comments

Comments
 (0)