Helper to get ready to run, shared, generic, static base.
#if COR_JIT_EE_VERSION > 460
CORINFO_HELP_READYTORUN_GENERIC_HANDLE,
CORINFO_HELP_READYTORUN_DELEGATE_CTOR,
+ CORINFO_HELP_READYTORUN_GENERIC_STATIC_BASE,
#else
#define CORINFO_HELP_READYTORUN_DELEGATE_CTOR CORINFO_HELP_EE_PRESTUB
#endif // COR_JIT_EE_VERSION
CORINFO_FIELD_STATIC_GENERICS_STATIC_HELPER, // static field access using the "generic static" helper (argument is MethodTable *)
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_INTRINSIC_ZERO, // intrinsic zero (IntPtr.Zero, UIntPtr.Zero)
CORINFO_FIELD_INTRINSIC_EMPTY_STRING, // intrinsic emptry string (String.Empty)
JITHELPER(CORINFO_HELP_VIRTUAL_FUNC_PTR, JIT_VirtualFunctionPointer, CORINFO_HELP_SIG_4_STACK)
//JITHELPER(CORINFO_HELP_VIRTUAL_FUNC_PTR_LOG,JIT_VirtualFunctionPointerLogging)
- JITHELPER(CORINFO_HELP_READYTORUN_NEW, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB)
- JITHELPER(CORINFO_HELP_READYTORUN_NEWARR_1, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB)
- JITHELPER(CORINFO_HELP_READYTORUN_ISINSTANCEOF, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB)
- JITHELPER(CORINFO_HELP_READYTORUN_CHKCAST, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB)
- JITHELPER(CORINFO_HELP_READYTORUN_STATIC_BASE, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB)
- JITHELPER(CORINFO_HELP_READYTORUN_VIRTUAL_FUNC_PTR, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB)
+ JITHELPER(CORINFO_HELP_READYTORUN_NEW, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB)
+ JITHELPER(CORINFO_HELP_READYTORUN_NEWARR_1, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB)
+ JITHELPER(CORINFO_HELP_READYTORUN_ISINSTANCEOF, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB)
+ JITHELPER(CORINFO_HELP_READYTORUN_CHKCAST, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB)
+ JITHELPER(CORINFO_HELP_READYTORUN_STATIC_BASE, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB)
+ JITHELPER(CORINFO_HELP_READYTORUN_VIRTUAL_FUNC_PTR, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB)
#if COR_JIT_EE_VERSION > 460
- JITHELPER(CORINFO_HELP_READYTORUN_GENERIC_HANDLE, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB)
- JITHELPER(CORINFO_HELP_READYTORUN_DELEGATE_CTOR, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB)
+ JITHELPER(CORINFO_HELP_READYTORUN_GENERIC_HANDLE, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB)
+ JITHELPER(CORINFO_HELP_READYTORUN_DELEGATE_CTOR, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB)
+ JITHELPER(CORINFO_HELP_READYTORUN_GENERIC_STATIC_BASE, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB)
#endif // COR_JIT_EE_VERSION
JITHELPER(CORINFO_HELP_EE_PRESTUB, ThePreStub, CORINFO_HELP_SIG_NO_ALIGN_STUB)
unsigned flags,
void* compileTimeHandle);
+ GenTreePtr getRuntimeContextTree(CORINFO_LOOKUP* pLookup);
+
GenTreePtr impRuntimeLookupToTree(CORINFO_RESOLVED_TOKEN* pResolvedToken,
CORINFO_LOOKUP* pLookup,
void* compileTimeHandle);
helper == CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_DYNAMICCLASS ||
helper == CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_DYNAMICCLASS ||
#ifdef FEATURE_READYTORUN_COMPILER
- helper == CORINFO_HELP_READYTORUN_STATIC_BASE ||
+ helper == CORINFO_HELP_READYTORUN_STATIC_BASE || helper == CORINFO_HELP_READYTORUN_GENERIC_STATIC_BASE ||
#endif
helper == CORINFO_HELP_CLASSINIT_SHARED_DYNAMICCLASS;
#if 0
return op1;
}
+GenTreePtr Compiler::getRuntimeContextTree(CORINFO_LOOKUP* pLookup)
+{
+ GenTreePtr ctxTree = nullptr;
+ CORINFO_RUNTIME_LOOKUP_KIND kind = pLookup->lookupKind.runtimeLookupKind;
+
+ // Collectible types requires that for shared generic code, if we use the generic context parameter
+ // that we report it. (This is a conservative approach, we could detect some cases particularly when the
+ // context parameter is this that we don't need the eager reporting logic.)
+ lvaGenericsContextUsed = true;
+
+ if (kind == CORINFO_LOOKUP_THISOBJ)
+ {
+ // this Object
+ ctxTree = gtNewLclvNode(info.compThisArg, TYP_REF);
+
+ // Vtable pointer of this object
+ ctxTree = gtNewOperNode(GT_IND, TYP_I_IMPL, ctxTree);
+ ctxTree->gtFlags |= GTF_EXCEPT; // Null-pointer exception
+ ctxTree->gtFlags |= GTF_IND_INVARIANT;
+ }
+ else
+ {
+ assert(kind == CORINFO_LOOKUP_METHODPARAM || kind == CORINFO_LOOKUP_CLASSPARAM);
+
+ ctxTree = gtNewLclvNode(info.compTypeCtxtArg, TYP_I_IMPL); // Exact method descriptor as passed in as last arg
+ }
+ return ctxTree;
+}
+
/*****************************************************************************/
/* Import a dictionary lookup to access a handle in code shared between
generic instantiations.
CORINFO_LOOKUP* pLookup,
void* compileTimeHandle)
{
- CORINFO_RUNTIME_LOOKUP_KIND kind = pLookup->lookupKind.runtimeLookupKind;
- CORINFO_RUNTIME_LOOKUP* pRuntimeLookup = &pLookup->runtimeLookup;
// This method can only be called from the importer instance of the Compiler.
// In other word, it cannot be called by the instance of the Compiler for the inlinee.
assert(!compIsForInlining());
- GenTreePtr ctxTree;
-
- // Collectible types requires that for shared generic code, if we use the generic context parameter
- // that we report it. (This is a conservative approach, we could detect some cases particularly when the
- // context parameter is this that we don't need the eager reporting logic.)
- lvaGenericsContextUsed = true;
-
- if (kind == CORINFO_LOOKUP_THISOBJ)
- {
- // this Object
- ctxTree = gtNewLclvNode(info.compThisArg, TYP_REF);
-
- // Vtable pointer of this object
- ctxTree = gtNewOperNode(GT_IND, TYP_I_IMPL, ctxTree);
- ctxTree->gtFlags |= GTF_EXCEPT; // Null-pointer exception
- ctxTree->gtFlags |= GTF_IND_INVARIANT;
- }
- else
- {
- assert(kind == CORINFO_LOOKUP_METHODPARAM || kind == CORINFO_LOOKUP_CLASSPARAM);
-
- ctxTree = gtNewLclvNode(info.compTypeCtxtArg, TYP_I_IMPL); // Exact method descriptor as passed in as last arg
- }
+ GenTreePtr ctxTree = getRuntimeContextTree(pLookup);
#ifdef FEATURE_READYTORUN_COMPILER
if (opts.IsReadyToRun())
}
#endif
+ CORINFO_RUNTIME_LOOKUP* pRuntimeLookup = &pLookup->runtimeLookup;
// It's available only via the run-time helper function
if (pRuntimeLookup->indirections == CORINFO_USEHELPER)
{
FieldSeqNode* fs = GetFieldSeqStore()->CreateSingleton(pResolvedToken->hField);
op1 = gtNewOperNode(GT_ADD, type, op1,
new (this, GT_CNS_INT) GenTreeIntCon(TYP_I_IMPL, pFieldInfo->offset, fs));
+ break;
}
- break;
-
case CORINFO_FIELD_STATIC_SHARED_STATIC_HELPER:
+ {
#ifdef FEATURE_READYTORUN_COMPILER
if (opts.IsReadyToRun())
{
new (this, GT_CNS_INT) GenTreeIntCon(TYP_INT, pFieldInfo->offset, fs));
}
break;
+ }
+ case CORINFO_FIELD_STATIC_READYTORUN_HELPER:
+ {
+ noway_assert(opts.IsReadyToRun());
+ CORINFO_GENERICHANDLE_RESULT embedInfo;
+ info.compCompHnd->embedGenericHandle(pResolvedToken, FALSE, &embedInfo);
+ assert(embedInfo.lookup.lookupKind.needsRuntimeLookup);
+ GenTreePtr ctxTree = getRuntimeContextTree(&embedInfo.lookup);
+
+ var_types type = TYP_BYREF;
+ op1 = impReadyToRunHelperToTree(pResolvedToken, pFieldInfo->helper, type, gtNewArgList(ctxTree),
+ &embedInfo.lookup.lookupKind);
+ FieldSeqNode* fs = GetFieldSeqStore()->CreateSingleton(pResolvedToken->hField);
+ op1 = gtNewOperNode(GT_ADD, type, op1,
+ new (this, GT_CNS_INT) GenTreeIntCon(TYP_I_IMPL, pFieldInfo->offset, fs));
+ break;
+ }
default:
+ {
if (!(access & CORINFO_ACCESS_ADDRESS))
{
// In future, it may be better to just create the right tree here instead of folding it later.
}
}
break;
+ }
}
if (pFieldInfo->fieldFlags & CORINFO_FLG_FIELD_STATIC_IN_HEAP)
case CORINFO_FIELD_STATIC_RVA_ADDRESS:
case CORINFO_FIELD_STATIC_SHARED_STATIC_HELPER:
case CORINFO_FIELD_STATIC_GENERICS_STATIC_HELPER:
+ case CORINFO_FIELD_STATIC_READYTORUN_HELPER:
op1 = impImportStaticFieldAccess(&resolvedToken, (CORINFO_ACCESS_FLAGS)aflags, &fieldInfo,
lclTyp);
break;
case CORINFO_FIELD_STATIC_RVA_ADDRESS:
case CORINFO_FIELD_STATIC_SHARED_STATIC_HELPER:
case CORINFO_FIELD_STATIC_GENERICS_STATIC_HELPER:
+ case CORINFO_FIELD_STATIC_READYTORUN_HELPER:
op1 = impImportStaticFieldAccess(&resolvedToken, (CORINFO_ACCESS_FLAGS)aflags, &fieldInfo,
lclTyp);
break;
case CORINFO_HELP_GETGENERICS_GCSTATIC_BASE:
case CORINFO_HELP_GETGENERICS_NONGCSTATIC_BASE:
case CORINFO_HELP_READYTORUN_STATIC_BASE:
+ case CORINFO_HELP_READYTORUN_GENERIC_STATIC_BASE:
// These may invoke static class constructors
// These can throw InvalidProgram exception if the class can not be constructed
case CORINFO_HELP_READYTORUN_STATIC_BASE:
vnf = VNF_ReadyToRunStaticBase;
break;
+ case CORINFO_HELP_READYTORUN_GENERIC_STATIC_BASE:
+ vnf = VNF_ReadyToRunGenericStaticBase;
+ break;
case CORINFO_HELP_GETSHARED_GCSTATIC_BASE_DYNAMICCLASS:
vnf = VNF_GetsharedGcstaticBaseDynamicclass;
break;
ValueNumFuncDef(GetsharedGcstaticBaseNoctor, 1, false, true, true)
ValueNumFuncDef(GetsharedNongcstaticBaseNoctor, 1, false, true, true)
ValueNumFuncDef(ReadyToRunStaticBase, 1, false, true, true)
+ValueNumFuncDef(ReadyToRunGenericStaticBase, 1, false, true, true)
ValueNumFuncDef(GetsharedGcstaticBaseDynamicclass, 2, false, true, true)
ValueNumFuncDef(GetsharedNongcstaticBaseDynamicclass, 2, false, true, true)
ValueNumFuncDef(GetgenericsGcthreadstaticBase, 1, false, true, true)