From e6d60550e252435f093ff170da4f89e607d2745c Mon Sep 17 00:00:00 2001 From: Tomas Rylek Date: Fri, 20 Jul 2018 20:22:45 +0200 Subject: [PATCH] CorInfoImpl refactoring part #2 In this part I have mechanically moved parts of CorInfoImpl to be forked to both CorInfoImpl.RyuJit and CorInfoImpl.ReadyToRun. I decided not to move getFieldInfo for now as it's a lengthy method and right now I'm only changing one line in it so that conditional compilation should be sufficient. We can fork it later if the changes become more pronounced e.g. due to the differences in thread static bases. The full list of methods I'm moving in this change is as follows: (*) ComputeLookup (*) getReadyToRunHelper (*) getReadyToRunDelegateCtorHelper (*) GetHelperFtnUncached (*) getFunctionEntryPoint (*) constructStringLiteral Apart from the mechanical move I have made a few other minor changes: 1) I have changed the hard-coded CORINFO_RUNTIME_ABI to a symbolic constant that is defined in CII.RJ and CII.RTR. In this one simple case I have already "executed" the split by putting the appropriate constant into each file, otherwise I left the moved methods unchanged for now. 2) I have made one additional change I overlooked in my previous cleanup change: I modified getHelperFtn by adding optional support for indirection cells that are used for the helpers in R2R. As mentioned above, for now I assume that I'll deal with the differences in getCallInfo and getFieldInfo using Thanks Tomas --- .../JitInterface/CorInfoImpl.ReadyToRun.cs | 463 ++++++++++++++++- .../src/JitInterface/CorInfoImpl.RyuJit.cs | 464 +++++++++++++++++- src/JitInterface/src/CorInfoImpl.cs | 334 +------------ 3 files changed, 936 insertions(+), 325 deletions(-) diff --git a/src/ILCompiler.ReadyToRun/src/JitInterface/CorInfoImpl.ReadyToRun.cs b/src/ILCompiler.ReadyToRun/src/JitInterface/CorInfoImpl.ReadyToRun.cs index ccca2ef94bb..889f515cf15 100644 --- a/src/ILCompiler.ReadyToRun/src/JitInterface/CorInfoImpl.ReadyToRun.cs +++ b/src/ILCompiler.ReadyToRun/src/JitInterface/CorInfoImpl.ReadyToRun.cs @@ -5,14 +5,18 @@ using System; using System.Diagnostics; +using Internal.IL; using Internal.TypeSystem; using ILCompiler; +using ILCompiler.DependencyAnalysis; namespace Internal.JitInterface { - partial class CorInfoImpl + unsafe partial class CorInfoImpl { + private const CORINFO_RUNTIME_ABI TargetABI = CORINFO_RUNTIME_ABI.CORINFO_CORECLR_ABI; + private ReadyToRunCodegenCompilation _compilation; public CorInfoImpl(ReadyToRunCodegenCompilation compilation, JitConfigProvider jitConfig) @@ -20,5 +24,462 @@ public CorInfoImpl(ReadyToRunCodegenCompilation compilation, JitConfigProvider j { _compilation = compilation; } + private void ComputeLookup(ref CORINFO_RESOLVED_TOKEN pResolvedToken, object entity, ReadyToRunHelperId helperId, ref CORINFO_LOOKUP lookup) + { + if (_compilation.NeedsRuntimeLookup(helperId, entity)) + { + lookup.lookupKind.needsRuntimeLookup = true; + lookup.runtimeLookup.signature = null; + + MethodDesc contextMethod = methodFromContext(pResolvedToken.tokenContext); + + // Do not bother computing the runtime lookup if we are inlining. The JIT is going + // to abort the inlining attempt anyway. + if (contextMethod != MethodBeingCompiled) + return; + + // Necessary type handle is not something that can be in a dictionary (only a constructed type). + // We only use necessary type handles if we can do a constant lookup. + if (helperId == ReadyToRunHelperId.NecessaryTypeHandle) + helperId = ReadyToRunHelperId.TypeHandle; + + GenericDictionaryLookup genericLookup = _compilation.ComputeGenericLookup(contextMethod, helperId, entity); + + if (genericLookup.UseHelper) + { + lookup.runtimeLookup.indirections = CORINFO.USEHELPER; + lookup.lookupKind.runtimeLookupFlags = (ushort)helperId; + lookup.lookupKind.runtimeLookupArgs = (void*)ObjectToHandle(entity); + } + else + { + if (genericLookup.ContextSource == GenericContextSource.MethodParameter) + { + lookup.runtimeLookup.helper = CorInfoHelpFunc.CORINFO_HELP_RUNTIMEHANDLE_METHOD; + } + else + { + lookup.runtimeLookup.helper = CorInfoHelpFunc.CORINFO_HELP_RUNTIMEHANDLE_CLASS; + } + + lookup.runtimeLookup.indirections = (ushort)genericLookup.NumberOfIndirections; + lookup.runtimeLookup.offset0 = (IntPtr)genericLookup[0]; + if (genericLookup.NumberOfIndirections > 1) + lookup.runtimeLookup.offset1 = (IntPtr)genericLookup[1]; + lookup.runtimeLookup.testForFixup = false; // TODO: this will be needed in true multifile + lookup.runtimeLookup.testForNull = false; + lookup.runtimeLookup.indirectFirstOffset = false; + lookup.runtimeLookup.indirectSecondOffset = false; + lookup.lookupKind.runtimeLookupFlags = 0; + lookup.lookupKind.runtimeLookupArgs = null; + } + + lookup.lookupKind.runtimeLookupKind = GetLookupKindFromContextSource(genericLookup.ContextSource); + } + else + { + lookup.lookupKind.needsRuntimeLookup = false; + ISymbolNode constLookup = _compilation.ComputeConstantLookup(helperId, entity); + lookup.constLookup = CreateConstLookupToSymbol(constLookup); + } + } + + private bool getReadyToRunHelper(ref CORINFO_RESOLVED_TOKEN pResolvedToken, ref CORINFO_LOOKUP_KIND pGenericLookupKind, CorInfoHelpFunc id, ref CORINFO_CONST_LOOKUP pLookup) + { + switch (id) + { + case CorInfoHelpFunc.CORINFO_HELP_READYTORUN_NEW: + { + var type = HandleToObject(pResolvedToken.hClass); + Debug.Assert(type.IsDefType); + if (type.IsCanonicalSubtype(CanonicalFormKind.Any)) + return false; + + pLookup = CreateConstLookupToSymbol(_compilation.NodeFactory.ReadyToRunHelper(ReadyToRunHelperId.NewHelper, type)); + } + break; + case CorInfoHelpFunc.CORINFO_HELP_READYTORUN_NEWARR_1: + { + var type = HandleToObject(pResolvedToken.hClass); + Debug.Assert(type.IsSzArray); + if (type.IsCanonicalSubtype(CanonicalFormKind.Any)) + return false; + + pLookup = CreateConstLookupToSymbol(_compilation.NodeFactory.ReadyToRunHelper(ReadyToRunHelperId.NewArr1, type)); + } + break; + case CorInfoHelpFunc.CORINFO_HELP_READYTORUN_ISINSTANCEOF: + { + var type = HandleToObject(pResolvedToken.hClass); + if (type.IsCanonicalSubtype(CanonicalFormKind.Any)) + return false; + + // ECMA-335 III.4.3: If typeTok is a nullable type, Nullable, it is interpreted as "boxed" T + if (type.IsNullable) + type = type.Instantiation[0]; + + pLookup = CreateConstLookupToSymbol(_compilation.NodeFactory.ReadyToRunHelper(ReadyToRunHelperId.IsInstanceOf, type)); + } + break; + case CorInfoHelpFunc.CORINFO_HELP_READYTORUN_CHKCAST: + { + var type = HandleToObject(pResolvedToken.hClass); + if (type.IsCanonicalSubtype(CanonicalFormKind.Any)) + return false; + + // ECMA-335 III.4.3: If typeTok is a nullable type, Nullable, it is interpreted as "boxed" T + if (type.IsNullable) + type = type.Instantiation[0]; + + pLookup = CreateConstLookupToSymbol(_compilation.NodeFactory.ReadyToRunHelper(ReadyToRunHelperId.CastClass, type)); + } + break; + case CorInfoHelpFunc.CORINFO_HELP_READYTORUN_STATIC_BASE: + { + var type = HandleToObject(pResolvedToken.hClass); + if (type.IsCanonicalSubtype(CanonicalFormKind.Any)) + return false; + + pLookup = CreateConstLookupToSymbol(_compilation.NodeFactory.ReadyToRunHelper(ReadyToRunHelperId.GetNonGCStaticBase, type)); + } + break; + case CorInfoHelpFunc.CORINFO_HELP_READYTORUN_GENERIC_STATIC_BASE: + { + // Token == 0 means "initialize this class". We only expect RyuJIT to call it for this case. + Debug.Assert(pResolvedToken.token == 0 && pResolvedToken.tokenScope == null); + Debug.Assert(pGenericLookupKind.needsRuntimeLookup); + + DefType typeToInitialize = (DefType)MethodBeingCompiled.OwningType; + Debug.Assert(typeToInitialize.IsCanonicalSubtype(CanonicalFormKind.Any)); + + DefType helperArg = typeToInitialize.ConvertToSharedRuntimeDeterminedForm(); + ISymbolNode helper = GetGenericLookupHelper(pGenericLookupKind.runtimeLookupKind, ReadyToRunHelperId.GetNonGCStaticBase, helperArg); + pLookup = CreateConstLookupToSymbol(helper); + } + break; + case CorInfoHelpFunc.CORINFO_HELP_READYTORUN_GENERIC_HANDLE: + { + Debug.Assert(pGenericLookupKind.needsRuntimeLookup); + + ReadyToRunHelperId helperId = (ReadyToRunHelperId)pGenericLookupKind.runtimeLookupFlags; + object helperArg = HandleToObject((IntPtr)pGenericLookupKind.runtimeLookupArgs); + ISymbolNode helper = GetGenericLookupHelper(pGenericLookupKind.runtimeLookupKind, helperId, helperArg); + pLookup = CreateConstLookupToSymbol(helper); + } + break; + default: + throw new NotImplementedException("ReadyToRun: " + id.ToString()); + } + return true; + } + + private void getReadyToRunDelegateCtorHelper(ref CORINFO_RESOLVED_TOKEN pTargetMethod, CORINFO_CLASS_STRUCT_* delegateType, ref CORINFO_LOOKUP pLookup) + { +#if DEBUG + // In debug, write some bogus data to the struct to ensure we have filled everything + // properly. + fixed (CORINFO_LOOKUP* tmp = &pLookup) + MemoryHelper.FillMemory((byte*)tmp, 0xcc, sizeof(CORINFO_LOOKUP)); +#endif + + MethodDesc targetMethod = HandleToObject(pTargetMethod.hMethod); + TypeDesc delegateTypeDesc = HandleToObject(delegateType); + + if (targetMethod.IsSharedByGenericInstantiations) + { + // If the method is not exact, fetch it as a runtime determined method. + targetMethod = (MethodDesc)GetRuntimeDeterminedObjectForToken(ref pTargetMethod); + } + + bool isLdvirtftn = pTargetMethod.tokenType == CorInfoTokenKind.CORINFO_TOKENKIND_Ldvirtftn; + DelegateCreationInfo delegateInfo = _compilation.GetDelegateCtor(delegateTypeDesc, targetMethod, isLdvirtftn); + + if (delegateInfo.NeedsRuntimeLookup) + { + pLookup.lookupKind.needsRuntimeLookup = true; + + MethodDesc contextMethod = methodFromContext(pTargetMethod.tokenContext); + + // We should not be inlining these. RyuJIT should have aborted inlining already. + Debug.Assert(contextMethod == MethodBeingCompiled); + + pLookup.lookupKind.runtimeLookupKind = GetGenericRuntimeLookupKind(contextMethod); + pLookup.lookupKind.runtimeLookupFlags = (ushort)ReadyToRunHelperId.DelegateCtor; + pLookup.lookupKind.runtimeLookupArgs = (void*)ObjectToHandle(delegateInfo); + } + else + { + pLookup.lookupKind.needsRuntimeLookup = false; + pLookup.constLookup = CreateConstLookupToSymbol(_compilation.NodeFactory.ReadyToRunHelper(ReadyToRunHelperId.DelegateCtor, delegateInfo)); + } + } + + private ISymbolNode GetHelperFtnUncached(CorInfoHelpFunc ftnNum) + { + ReadyToRunHelper id; + + switch (ftnNum) + { + case CorInfoHelpFunc.CORINFO_HELP_THROW: + id = ReadyToRunHelper.Throw; + break; + case CorInfoHelpFunc.CORINFO_HELP_RETHROW: + id = ReadyToRunHelper.Rethrow; + break; + case CorInfoHelpFunc.CORINFO_HELP_USER_BREAKPOINT: + id = ReadyToRunHelper.DebugBreak; + break; + case CorInfoHelpFunc.CORINFO_HELP_OVERFLOW: + id = ReadyToRunHelper.Overflow; + break; + case CorInfoHelpFunc.CORINFO_HELP_RNGCHKFAIL: + id = ReadyToRunHelper.RngChkFail; + break; + case CorInfoHelpFunc.CORINFO_HELP_FAIL_FAST: + id = ReadyToRunHelper.FailFast; + break; + case CorInfoHelpFunc.CORINFO_HELP_THROWNULLREF: + id = ReadyToRunHelper.ThrowNullRef; + break; + case CorInfoHelpFunc.CORINFO_HELP_THROWDIVZERO: + id = ReadyToRunHelper.ThrowDivZero; + break; + case CorInfoHelpFunc.CORINFO_HELP_THROW_ARGUMENTOUTOFRANGEEXCEPTION: + id = ReadyToRunHelper.ThrowArgumentOutOfRange; + break; + case CorInfoHelpFunc.CORINFO_HELP_THROW_ARGUMENTEXCEPTION: + id = ReadyToRunHelper.ThrowArgument; + break; + case CorInfoHelpFunc.CORINFO_HELP_THROW_PLATFORM_NOT_SUPPORTED: + id = ReadyToRunHelper.ThrowPlatformNotSupported; + break; + + case CorInfoHelpFunc.CORINFO_HELP_ASSIGN_REF: + id = ReadyToRunHelper.WriteBarrier; + break; + case CorInfoHelpFunc.CORINFO_HELP_CHECKED_ASSIGN_REF: + id = ReadyToRunHelper.CheckedWriteBarrier; + break; + case CorInfoHelpFunc.CORINFO_HELP_ASSIGN_BYREF: + id = ReadyToRunHelper.ByRefWriteBarrier; + break; + + case CorInfoHelpFunc.CORINFO_HELP_ARRADDR_ST: + id = ReadyToRunHelper.Stelem_Ref; + break; + case CorInfoHelpFunc.CORINFO_HELP_LDELEMA_REF: + id = ReadyToRunHelper.Ldelema_Ref; + break; + + case CorInfoHelpFunc.CORINFO_HELP_MEMSET: + id = ReadyToRunHelper.MemSet; + break; + case CorInfoHelpFunc.CORINFO_HELP_MEMCPY: + id = ReadyToRunHelper.MemCpy; + break; + + case CorInfoHelpFunc.CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE: + id = ReadyToRunHelper.GetRuntimeTypeHandle; + break; + case CorInfoHelpFunc.CORINFO_HELP_METHODDESC_TO_STUBRUNTIMEMETHOD: + id = ReadyToRunHelper.GetRuntimeMethodHandle; + break; + case CorInfoHelpFunc.CORINFO_HELP_FIELDDESC_TO_STUBRUNTIMEFIELD: + id = ReadyToRunHelper.GetRuntimeFieldHandle; + break; + + case CorInfoHelpFunc.CORINFO_HELP_BOX: + id = ReadyToRunHelper.Box; + break; + case CorInfoHelpFunc.CORINFO_HELP_BOX_NULLABLE: + id = ReadyToRunHelper.Box_Nullable; + break; + case CorInfoHelpFunc.CORINFO_HELP_UNBOX: + id = ReadyToRunHelper.Unbox; + break; + case CorInfoHelpFunc.CORINFO_HELP_UNBOX_NULLABLE: + id = ReadyToRunHelper.Unbox_Nullable; + break; + case CorInfoHelpFunc.CORINFO_HELP_NEW_MDARR_NONVARARG: + id = ReadyToRunHelper.NewMultiDimArr_NonVarArg; + break; + case CorInfoHelpFunc.CORINFO_HELP_NEWFAST: + id = ReadyToRunHelper.NewObject; + break; + case CorInfoHelpFunc.CORINFO_HELP_NEWARR_1_DIRECT: + id = ReadyToRunHelper.NewArray; + break; + + case CorInfoHelpFunc.CORINFO_HELP_LMUL: + id = ReadyToRunHelper.LMul; + break; + case CorInfoHelpFunc.CORINFO_HELP_LMUL_OVF: + id = ReadyToRunHelper.LMulOfv; + break; + case CorInfoHelpFunc.CORINFO_HELP_ULMUL_OVF: + id = ReadyToRunHelper.ULMulOvf; + break; + case CorInfoHelpFunc.CORINFO_HELP_LDIV: + id = ReadyToRunHelper.LDiv; + break; + case CorInfoHelpFunc.CORINFO_HELP_LMOD: + id = ReadyToRunHelper.LMod; + break; + case CorInfoHelpFunc.CORINFO_HELP_ULDIV: + id = ReadyToRunHelper.ULDiv; + break; + case CorInfoHelpFunc.CORINFO_HELP_ULMOD: + id = ReadyToRunHelper.ULMod; + break; + case CorInfoHelpFunc.CORINFO_HELP_LLSH: + id = ReadyToRunHelper.LLsh; + break; + case CorInfoHelpFunc.CORINFO_HELP_LRSH: + id = ReadyToRunHelper.LRsh; + break; + case CorInfoHelpFunc.CORINFO_HELP_LRSZ: + id = ReadyToRunHelper.LRsz; + break; + case CorInfoHelpFunc.CORINFO_HELP_LNG2DBL: + id = ReadyToRunHelper.Lng2Dbl; + break; + case CorInfoHelpFunc.CORINFO_HELP_ULNG2DBL: + id = ReadyToRunHelper.ULng2Dbl; + break; + + case CorInfoHelpFunc.CORINFO_HELP_DIV: + id = ReadyToRunHelper.Div; + break; + case CorInfoHelpFunc.CORINFO_HELP_MOD: + id = ReadyToRunHelper.Mod; + break; + case CorInfoHelpFunc.CORINFO_HELP_UDIV: + id = ReadyToRunHelper.UDiv; + break; + case CorInfoHelpFunc.CORINFO_HELP_UMOD: + id = ReadyToRunHelper.UMod; + break; + + case CorInfoHelpFunc.CORINFO_HELP_DBL2INT: + id = ReadyToRunHelper.Dbl2Int; + break; + case CorInfoHelpFunc.CORINFO_HELP_DBL2INT_OVF: + id = ReadyToRunHelper.Dbl2IntOvf; + break; + case CorInfoHelpFunc.CORINFO_HELP_DBL2LNG: + id = ReadyToRunHelper.Dbl2Lng; + break; + case CorInfoHelpFunc.CORINFO_HELP_DBL2LNG_OVF: + id = ReadyToRunHelper.Dbl2LngOvf; + break; + case CorInfoHelpFunc.CORINFO_HELP_DBL2UINT: + id = ReadyToRunHelper.Dbl2UInt; + break; + case CorInfoHelpFunc.CORINFO_HELP_DBL2UINT_OVF: + id = ReadyToRunHelper.Dbl2UIntOvf; + break; + case CorInfoHelpFunc.CORINFO_HELP_DBL2ULNG: + id = ReadyToRunHelper.Dbl2ULng; + break; + case CorInfoHelpFunc.CORINFO_HELP_DBL2ULNG_OVF: + id = ReadyToRunHelper.Dbl2ULngOvf; + break; + + case CorInfoHelpFunc.CORINFO_HELP_FLTREM: + id = ReadyToRunHelper.FltRem; + break; + case CorInfoHelpFunc.CORINFO_HELP_DBLREM: + id = ReadyToRunHelper.DblRem; + break; + case CorInfoHelpFunc.CORINFO_HELP_FLTROUND: + id = ReadyToRunHelper.FltRound; + break; + case CorInfoHelpFunc.CORINFO_HELP_DBLROUND: + id = ReadyToRunHelper.DblRound; + break; + + case CorInfoHelpFunc.CORINFO_HELP_JIT_PINVOKE_BEGIN: + id = ReadyToRunHelper.PInvokeBegin; + break; + case CorInfoHelpFunc.CORINFO_HELP_JIT_PINVOKE_END: + id = ReadyToRunHelper.PInvokeEnd; + break; + + case CorInfoHelpFunc.CORINFO_HELP_JIT_REVERSE_PINVOKE_ENTER: + id = ReadyToRunHelper.ReversePInvokeEnter; + break; + case CorInfoHelpFunc.CORINFO_HELP_JIT_REVERSE_PINVOKE_EXIT: + id = ReadyToRunHelper.ReversePInvokeExit; + break; + + case CorInfoHelpFunc.CORINFO_HELP_CHKCASTANY: + id = ReadyToRunHelper.CheckCastAny; + break; + case CorInfoHelpFunc.CORINFO_HELP_ISINSTANCEOFANY: + id = ReadyToRunHelper.CheckInstanceAny; + break; + + case CorInfoHelpFunc.CORINFO_HELP_MON_ENTER: + id = ReadyToRunHelper.MonitorEnter; + break; + case CorInfoHelpFunc.CORINFO_HELP_MON_EXIT: + id = ReadyToRunHelper.MonitorExit; + break; + + case CorInfoHelpFunc.CORINFO_HELP_MON_ENTER_STATIC: + id = ReadyToRunHelper.MonitorEnterStatic; + break; + case CorInfoHelpFunc.CORINFO_HELP_MON_EXIT_STATIC: + id = ReadyToRunHelper.MonitorExitStatic; + break; + + case CorInfoHelpFunc.CORINFO_HELP_GVMLOOKUP_FOR_SLOT: + id = ReadyToRunHelper.GVMLookupForSlot; + break; + + case CorInfoHelpFunc.CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE_MAYBENULL: + id = ReadyToRunHelper.TypeHandleToRuntimeType; + break; + case CorInfoHelpFunc.CORINFO_HELP_GETREFANY: + id = ReadyToRunHelper.GetRefAny; + break; + + default: + throw new NotImplementedException(ftnNum.ToString()); + } + + string mangledName; + MethodDesc methodDesc; + JitHelper.GetEntryPoint(_compilation.TypeSystemContext, id, out mangledName, out methodDesc); + Debug.Assert(mangledName != null || methodDesc != null); + + ISymbolNode entryPoint; + if (mangledName != null) + entryPoint = _compilation.NodeFactory.ExternSymbol(mangledName); + else + entryPoint = _compilation.NodeFactory.MethodEntrypoint(methodDesc); + + return entryPoint; + } + + private void getFunctionEntryPoint(CORINFO_METHOD_STRUCT_* ftn, ref CORINFO_CONST_LOOKUP pResult, CORINFO_ACCESS_FLAGS accessFlags) + { + MethodDesc method = HandleToObject(ftn); + + // TODO: Implement MapMethodDeclToMethodImpl from CoreCLR + if (method.IsVirtual) + throw new NotImplementedException("getFunctionEntryPoint"); + + pResult = CreateConstLookupToSymbol(_compilation.NodeFactory.MethodEntrypoint(method)); + } + + private InfoAccessType constructStringLiteral(CORINFO_MODULE_STRUCT_* module, mdToken metaTok, ref void* ppValue) + { + MethodIL methodIL = (MethodIL)HandleToObject((IntPtr)module); + object literal = methodIL.GetObject((int)metaTok); + ISymbolNode stringObject = _compilation.NodeFactory.SerializedStringObject((string)literal); + ppValue = (void*)ObjectToHandle(stringObject); + return stringObject.RepresentsIndirectionCell ? InfoAccessType.IAT_PVALUE : InfoAccessType.IAT_VALUE; + } } } diff --git a/src/ILCompiler.RyuJit/src/JitInterface/CorInfoImpl.RyuJit.cs b/src/ILCompiler.RyuJit/src/JitInterface/CorInfoImpl.RyuJit.cs index da09447417b..7afdc566d54 100644 --- a/src/ILCompiler.RyuJit/src/JitInterface/CorInfoImpl.RyuJit.cs +++ b/src/ILCompiler.RyuJit/src/JitInterface/CorInfoImpl.RyuJit.cs @@ -5,14 +5,18 @@ using System; using System.Diagnostics; +using Internal.IL; using Internal.TypeSystem; using ILCompiler; +using ILCompiler.DependencyAnalysis; namespace Internal.JitInterface { - partial class CorInfoImpl + unsafe partial class CorInfoImpl { + private const CORINFO_RUNTIME_ABI TargetABI = CORINFO_RUNTIME_ABI.CORINFO_CORERT_ABI; + private Compilation _compilation; public CorInfoImpl(Compilation compilation, JitConfigProvider jitConfig) @@ -20,5 +24,463 @@ public CorInfoImpl(Compilation compilation, JitConfigProvider jitConfig) { _compilation = compilation; } + + private void ComputeLookup(ref CORINFO_RESOLVED_TOKEN pResolvedToken, object entity, ReadyToRunHelperId helperId, ref CORINFO_LOOKUP lookup) + { + if (_compilation.NeedsRuntimeLookup(helperId, entity)) + { + lookup.lookupKind.needsRuntimeLookup = true; + lookup.runtimeLookup.signature = null; + + MethodDesc contextMethod = methodFromContext(pResolvedToken.tokenContext); + + // Do not bother computing the runtime lookup if we are inlining. The JIT is going + // to abort the inlining attempt anyway. + if (contextMethod != MethodBeingCompiled) + return; + + // Necessary type handle is not something that can be in a dictionary (only a constructed type). + // We only use necessary type handles if we can do a constant lookup. + if (helperId == ReadyToRunHelperId.NecessaryTypeHandle) + helperId = ReadyToRunHelperId.TypeHandle; + + GenericDictionaryLookup genericLookup = _compilation.ComputeGenericLookup(contextMethod, helperId, entity); + + if (genericLookup.UseHelper) + { + lookup.runtimeLookup.indirections = CORINFO.USEHELPER; + lookup.lookupKind.runtimeLookupFlags = (ushort)helperId; + lookup.lookupKind.runtimeLookupArgs = (void*)ObjectToHandle(entity); + } + else + { + if (genericLookup.ContextSource == GenericContextSource.MethodParameter) + { + lookup.runtimeLookup.helper = CorInfoHelpFunc.CORINFO_HELP_RUNTIMEHANDLE_METHOD; + } + else + { + lookup.runtimeLookup.helper = CorInfoHelpFunc.CORINFO_HELP_RUNTIMEHANDLE_CLASS; + } + + lookup.runtimeLookup.indirections = (ushort)genericLookup.NumberOfIndirections; + lookup.runtimeLookup.offset0 = (IntPtr)genericLookup[0]; + if (genericLookup.NumberOfIndirections > 1) + lookup.runtimeLookup.offset1 = (IntPtr)genericLookup[1]; + lookup.runtimeLookup.testForFixup = false; // TODO: this will be needed in true multifile + lookup.runtimeLookup.testForNull = false; + lookup.runtimeLookup.indirectFirstOffset = false; + lookup.runtimeLookup.indirectSecondOffset = false; + lookup.lookupKind.runtimeLookupFlags = 0; + lookup.lookupKind.runtimeLookupArgs = null; + } + + lookup.lookupKind.runtimeLookupKind = GetLookupKindFromContextSource(genericLookup.ContextSource); + } + else + { + lookup.lookupKind.needsRuntimeLookup = false; + ISymbolNode constLookup = _compilation.ComputeConstantLookup(helperId, entity); + lookup.constLookup = CreateConstLookupToSymbol(constLookup); + } + } + + private bool getReadyToRunHelper(ref CORINFO_RESOLVED_TOKEN pResolvedToken, ref CORINFO_LOOKUP_KIND pGenericLookupKind, CorInfoHelpFunc id, ref CORINFO_CONST_LOOKUP pLookup) + { + switch (id) + { + case CorInfoHelpFunc.CORINFO_HELP_READYTORUN_NEW: + { + var type = HandleToObject(pResolvedToken.hClass); + Debug.Assert(type.IsDefType); + if (type.IsCanonicalSubtype(CanonicalFormKind.Any)) + return false; + + pLookup = CreateConstLookupToSymbol(_compilation.NodeFactory.ReadyToRunHelper(ReadyToRunHelperId.NewHelper, type)); + } + break; + case CorInfoHelpFunc.CORINFO_HELP_READYTORUN_NEWARR_1: + { + var type = HandleToObject(pResolvedToken.hClass); + Debug.Assert(type.IsSzArray); + if (type.IsCanonicalSubtype(CanonicalFormKind.Any)) + return false; + + pLookup = CreateConstLookupToSymbol(_compilation.NodeFactory.ReadyToRunHelper(ReadyToRunHelperId.NewArr1, type)); + } + break; + case CorInfoHelpFunc.CORINFO_HELP_READYTORUN_ISINSTANCEOF: + { + var type = HandleToObject(pResolvedToken.hClass); + if (type.IsCanonicalSubtype(CanonicalFormKind.Any)) + return false; + + // ECMA-335 III.4.3: If typeTok is a nullable type, Nullable, it is interpreted as "boxed" T + if (type.IsNullable) + type = type.Instantiation[0]; + + pLookup = CreateConstLookupToSymbol(_compilation.NodeFactory.ReadyToRunHelper(ReadyToRunHelperId.IsInstanceOf, type)); + } + break; + case CorInfoHelpFunc.CORINFO_HELP_READYTORUN_CHKCAST: + { + var type = HandleToObject(pResolvedToken.hClass); + if (type.IsCanonicalSubtype(CanonicalFormKind.Any)) + return false; + + // ECMA-335 III.4.3: If typeTok is a nullable type, Nullable, it is interpreted as "boxed" T + if (type.IsNullable) + type = type.Instantiation[0]; + + pLookup = CreateConstLookupToSymbol(_compilation.NodeFactory.ReadyToRunHelper(ReadyToRunHelperId.CastClass, type)); + } + break; + case CorInfoHelpFunc.CORINFO_HELP_READYTORUN_STATIC_BASE: + { + var type = HandleToObject(pResolvedToken.hClass); + if (type.IsCanonicalSubtype(CanonicalFormKind.Any)) + return false; + + pLookup = CreateConstLookupToSymbol(_compilation.NodeFactory.ReadyToRunHelper(ReadyToRunHelperId.GetNonGCStaticBase, type)); + } + break; + case CorInfoHelpFunc.CORINFO_HELP_READYTORUN_GENERIC_STATIC_BASE: + { + // Token == 0 means "initialize this class". We only expect RyuJIT to call it for this case. + Debug.Assert(pResolvedToken.token == 0 && pResolvedToken.tokenScope == null); + Debug.Assert(pGenericLookupKind.needsRuntimeLookup); + + DefType typeToInitialize = (DefType)MethodBeingCompiled.OwningType; + Debug.Assert(typeToInitialize.IsCanonicalSubtype(CanonicalFormKind.Any)); + + DefType helperArg = typeToInitialize.ConvertToSharedRuntimeDeterminedForm(); + ISymbolNode helper = GetGenericLookupHelper(pGenericLookupKind.runtimeLookupKind, ReadyToRunHelperId.GetNonGCStaticBase, helperArg); + pLookup = CreateConstLookupToSymbol(helper); + } + break; + case CorInfoHelpFunc.CORINFO_HELP_READYTORUN_GENERIC_HANDLE: + { + Debug.Assert(pGenericLookupKind.needsRuntimeLookup); + + ReadyToRunHelperId helperId = (ReadyToRunHelperId)pGenericLookupKind.runtimeLookupFlags; + object helperArg = HandleToObject((IntPtr)pGenericLookupKind.runtimeLookupArgs); + ISymbolNode helper = GetGenericLookupHelper(pGenericLookupKind.runtimeLookupKind, helperId, helperArg); + pLookup = CreateConstLookupToSymbol(helper); + } + break; + default: + throw new NotImplementedException("ReadyToRun: " + id.ToString()); + } + return true; + } + + private void getReadyToRunDelegateCtorHelper(ref CORINFO_RESOLVED_TOKEN pTargetMethod, CORINFO_CLASS_STRUCT_* delegateType, ref CORINFO_LOOKUP pLookup) + { +#if DEBUG + // In debug, write some bogus data to the struct to ensure we have filled everything + // properly. + fixed (CORINFO_LOOKUP* tmp = &pLookup) + MemoryHelper.FillMemory((byte*)tmp, 0xcc, sizeof(CORINFO_LOOKUP)); +#endif + + MethodDesc targetMethod = HandleToObject(pTargetMethod.hMethod); + TypeDesc delegateTypeDesc = HandleToObject(delegateType); + + if (targetMethod.IsSharedByGenericInstantiations) + { + // If the method is not exact, fetch it as a runtime determined method. + targetMethod = (MethodDesc)GetRuntimeDeterminedObjectForToken(ref pTargetMethod); + } + + bool isLdvirtftn = pTargetMethod.tokenType == CorInfoTokenKind.CORINFO_TOKENKIND_Ldvirtftn; + DelegateCreationInfo delegateInfo = _compilation.GetDelegateCtor(delegateTypeDesc, targetMethod, isLdvirtftn); + + if (delegateInfo.NeedsRuntimeLookup) + { + pLookup.lookupKind.needsRuntimeLookup = true; + + MethodDesc contextMethod = methodFromContext(pTargetMethod.tokenContext); + + // We should not be inlining these. RyuJIT should have aborted inlining already. + Debug.Assert(contextMethod == MethodBeingCompiled); + + pLookup.lookupKind.runtimeLookupKind = GetGenericRuntimeLookupKind(contextMethod); + pLookup.lookupKind.runtimeLookupFlags = (ushort)ReadyToRunHelperId.DelegateCtor; + pLookup.lookupKind.runtimeLookupArgs = (void*)ObjectToHandle(delegateInfo); + } + else + { + pLookup.lookupKind.needsRuntimeLookup = false; + pLookup.constLookup = CreateConstLookupToSymbol(_compilation.NodeFactory.ReadyToRunHelper(ReadyToRunHelperId.DelegateCtor, delegateInfo)); + } + } + + private ISymbolNode GetHelperFtnUncached(CorInfoHelpFunc ftnNum) + { + ReadyToRunHelper id; + + switch (ftnNum) + { + case CorInfoHelpFunc.CORINFO_HELP_THROW: + id = ReadyToRunHelper.Throw; + break; + case CorInfoHelpFunc.CORINFO_HELP_RETHROW: + id = ReadyToRunHelper.Rethrow; + break; + case CorInfoHelpFunc.CORINFO_HELP_USER_BREAKPOINT: + id = ReadyToRunHelper.DebugBreak; + break; + case CorInfoHelpFunc.CORINFO_HELP_OVERFLOW: + id = ReadyToRunHelper.Overflow; + break; + case CorInfoHelpFunc.CORINFO_HELP_RNGCHKFAIL: + id = ReadyToRunHelper.RngChkFail; + break; + case CorInfoHelpFunc.CORINFO_HELP_FAIL_FAST: + id = ReadyToRunHelper.FailFast; + break; + case CorInfoHelpFunc.CORINFO_HELP_THROWNULLREF: + id = ReadyToRunHelper.ThrowNullRef; + break; + case CorInfoHelpFunc.CORINFO_HELP_THROWDIVZERO: + id = ReadyToRunHelper.ThrowDivZero; + break; + case CorInfoHelpFunc.CORINFO_HELP_THROW_ARGUMENTOUTOFRANGEEXCEPTION: + id = ReadyToRunHelper.ThrowArgumentOutOfRange; + break; + case CorInfoHelpFunc.CORINFO_HELP_THROW_ARGUMENTEXCEPTION: + id = ReadyToRunHelper.ThrowArgument; + break; + case CorInfoHelpFunc.CORINFO_HELP_THROW_PLATFORM_NOT_SUPPORTED: + id = ReadyToRunHelper.ThrowPlatformNotSupported; + break; + + case CorInfoHelpFunc.CORINFO_HELP_ASSIGN_REF: + id = ReadyToRunHelper.WriteBarrier; + break; + case CorInfoHelpFunc.CORINFO_HELP_CHECKED_ASSIGN_REF: + id = ReadyToRunHelper.CheckedWriteBarrier; + break; + case CorInfoHelpFunc.CORINFO_HELP_ASSIGN_BYREF: + id = ReadyToRunHelper.ByRefWriteBarrier; + break; + + case CorInfoHelpFunc.CORINFO_HELP_ARRADDR_ST: + id = ReadyToRunHelper.Stelem_Ref; + break; + case CorInfoHelpFunc.CORINFO_HELP_LDELEMA_REF: + id = ReadyToRunHelper.Ldelema_Ref; + break; + + case CorInfoHelpFunc.CORINFO_HELP_MEMSET: + id = ReadyToRunHelper.MemSet; + break; + case CorInfoHelpFunc.CORINFO_HELP_MEMCPY: + id = ReadyToRunHelper.MemCpy; + break; + + case CorInfoHelpFunc.CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE: + id = ReadyToRunHelper.GetRuntimeTypeHandle; + break; + case CorInfoHelpFunc.CORINFO_HELP_METHODDESC_TO_STUBRUNTIMEMETHOD: + id = ReadyToRunHelper.GetRuntimeMethodHandle; + break; + case CorInfoHelpFunc.CORINFO_HELP_FIELDDESC_TO_STUBRUNTIMEFIELD: + id = ReadyToRunHelper.GetRuntimeFieldHandle; + break; + + case CorInfoHelpFunc.CORINFO_HELP_BOX: + id = ReadyToRunHelper.Box; + break; + case CorInfoHelpFunc.CORINFO_HELP_BOX_NULLABLE: + id = ReadyToRunHelper.Box_Nullable; + break; + case CorInfoHelpFunc.CORINFO_HELP_UNBOX: + id = ReadyToRunHelper.Unbox; + break; + case CorInfoHelpFunc.CORINFO_HELP_UNBOX_NULLABLE: + id = ReadyToRunHelper.Unbox_Nullable; + break; + case CorInfoHelpFunc.CORINFO_HELP_NEW_MDARR_NONVARARG: + id = ReadyToRunHelper.NewMultiDimArr_NonVarArg; + break; + case CorInfoHelpFunc.CORINFO_HELP_NEWFAST: + id = ReadyToRunHelper.NewObject; + break; + case CorInfoHelpFunc.CORINFO_HELP_NEWARR_1_DIRECT: + id = ReadyToRunHelper.NewArray; + break; + + case CorInfoHelpFunc.CORINFO_HELP_LMUL: + id = ReadyToRunHelper.LMul; + break; + case CorInfoHelpFunc.CORINFO_HELP_LMUL_OVF: + id = ReadyToRunHelper.LMulOfv; + break; + case CorInfoHelpFunc.CORINFO_HELP_ULMUL_OVF: + id = ReadyToRunHelper.ULMulOvf; + break; + case CorInfoHelpFunc.CORINFO_HELP_LDIV: + id = ReadyToRunHelper.LDiv; + break; + case CorInfoHelpFunc.CORINFO_HELP_LMOD: + id = ReadyToRunHelper.LMod; + break; + case CorInfoHelpFunc.CORINFO_HELP_ULDIV: + id = ReadyToRunHelper.ULDiv; + break; + case CorInfoHelpFunc.CORINFO_HELP_ULMOD: + id = ReadyToRunHelper.ULMod; + break; + case CorInfoHelpFunc.CORINFO_HELP_LLSH: + id = ReadyToRunHelper.LLsh; + break; + case CorInfoHelpFunc.CORINFO_HELP_LRSH: + id = ReadyToRunHelper.LRsh; + break; + case CorInfoHelpFunc.CORINFO_HELP_LRSZ: + id = ReadyToRunHelper.LRsz; + break; + case CorInfoHelpFunc.CORINFO_HELP_LNG2DBL: + id = ReadyToRunHelper.Lng2Dbl; + break; + case CorInfoHelpFunc.CORINFO_HELP_ULNG2DBL: + id = ReadyToRunHelper.ULng2Dbl; + break; + + case CorInfoHelpFunc.CORINFO_HELP_DIV: + id = ReadyToRunHelper.Div; + break; + case CorInfoHelpFunc.CORINFO_HELP_MOD: + id = ReadyToRunHelper.Mod; + break; + case CorInfoHelpFunc.CORINFO_HELP_UDIV: + id = ReadyToRunHelper.UDiv; + break; + case CorInfoHelpFunc.CORINFO_HELP_UMOD: + id = ReadyToRunHelper.UMod; + break; + + case CorInfoHelpFunc.CORINFO_HELP_DBL2INT: + id = ReadyToRunHelper.Dbl2Int; + break; + case CorInfoHelpFunc.CORINFO_HELP_DBL2INT_OVF: + id = ReadyToRunHelper.Dbl2IntOvf; + break; + case CorInfoHelpFunc.CORINFO_HELP_DBL2LNG: + id = ReadyToRunHelper.Dbl2Lng; + break; + case CorInfoHelpFunc.CORINFO_HELP_DBL2LNG_OVF: + id = ReadyToRunHelper.Dbl2LngOvf; + break; + case CorInfoHelpFunc.CORINFO_HELP_DBL2UINT: + id = ReadyToRunHelper.Dbl2UInt; + break; + case CorInfoHelpFunc.CORINFO_HELP_DBL2UINT_OVF: + id = ReadyToRunHelper.Dbl2UIntOvf; + break; + case CorInfoHelpFunc.CORINFO_HELP_DBL2ULNG: + id = ReadyToRunHelper.Dbl2ULng; + break; + case CorInfoHelpFunc.CORINFO_HELP_DBL2ULNG_OVF: + id = ReadyToRunHelper.Dbl2ULngOvf; + break; + + case CorInfoHelpFunc.CORINFO_HELP_FLTREM: + id = ReadyToRunHelper.FltRem; + break; + case CorInfoHelpFunc.CORINFO_HELP_DBLREM: + id = ReadyToRunHelper.DblRem; + break; + case CorInfoHelpFunc.CORINFO_HELP_FLTROUND: + id = ReadyToRunHelper.FltRound; + break; + case CorInfoHelpFunc.CORINFO_HELP_DBLROUND: + id = ReadyToRunHelper.DblRound; + break; + + case CorInfoHelpFunc.CORINFO_HELP_JIT_PINVOKE_BEGIN: + id = ReadyToRunHelper.PInvokeBegin; + break; + case CorInfoHelpFunc.CORINFO_HELP_JIT_PINVOKE_END: + id = ReadyToRunHelper.PInvokeEnd; + break; + + case CorInfoHelpFunc.CORINFO_HELP_JIT_REVERSE_PINVOKE_ENTER: + id = ReadyToRunHelper.ReversePInvokeEnter; + break; + case CorInfoHelpFunc.CORINFO_HELP_JIT_REVERSE_PINVOKE_EXIT: + id = ReadyToRunHelper.ReversePInvokeExit; + break; + + case CorInfoHelpFunc.CORINFO_HELP_CHKCASTANY: + id = ReadyToRunHelper.CheckCastAny; + break; + case CorInfoHelpFunc.CORINFO_HELP_ISINSTANCEOFANY: + id = ReadyToRunHelper.CheckInstanceAny; + break; + + case CorInfoHelpFunc.CORINFO_HELP_MON_ENTER: + id = ReadyToRunHelper.MonitorEnter; + break; + case CorInfoHelpFunc.CORINFO_HELP_MON_EXIT: + id = ReadyToRunHelper.MonitorExit; + break; + + case CorInfoHelpFunc.CORINFO_HELP_MON_ENTER_STATIC: + id = ReadyToRunHelper.MonitorEnterStatic; + break; + case CorInfoHelpFunc.CORINFO_HELP_MON_EXIT_STATIC: + id = ReadyToRunHelper.MonitorExitStatic; + break; + + case CorInfoHelpFunc.CORINFO_HELP_GVMLOOKUP_FOR_SLOT: + id = ReadyToRunHelper.GVMLookupForSlot; + break; + + case CorInfoHelpFunc.CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE_MAYBENULL: + id = ReadyToRunHelper.TypeHandleToRuntimeType; + break; + case CorInfoHelpFunc.CORINFO_HELP_GETREFANY: + id = ReadyToRunHelper.GetRefAny; + break; + + default: + throw new NotImplementedException(ftnNum.ToString()); + } + + string mangledName; + MethodDesc methodDesc; + JitHelper.GetEntryPoint(_compilation.TypeSystemContext, id, out mangledName, out methodDesc); + Debug.Assert(mangledName != null || methodDesc != null); + + ISymbolNode entryPoint; + if (mangledName != null) + entryPoint = _compilation.NodeFactory.ExternSymbol(mangledName); + else + entryPoint = _compilation.NodeFactory.MethodEntrypoint(methodDesc); + + return entryPoint; + } + + private void getFunctionEntryPoint(CORINFO_METHOD_STRUCT_* ftn, ref CORINFO_CONST_LOOKUP pResult, CORINFO_ACCESS_FLAGS accessFlags) + { + MethodDesc method = HandleToObject(ftn); + + // TODO: Implement MapMethodDeclToMethodImpl from CoreCLR + if (method.IsVirtual) + throw new NotImplementedException("getFunctionEntryPoint"); + + pResult = CreateConstLookupToSymbol(_compilation.NodeFactory.MethodEntrypoint(method)); + } + + private InfoAccessType constructStringLiteral(CORINFO_MODULE_STRUCT_* module, mdToken metaTok, ref void* ppValue) + { + MethodIL methodIL = (MethodIL)HandleToObject((IntPtr)module); + object literal = methodIL.GetObject((int)metaTok); + ISymbolNode stringObject = _compilation.NodeFactory.SerializedStringObject((string)literal); + ppValue = (void*)ObjectToHandle(stringObject); + return stringObject.RepresentsIndirectionCell ? InfoAccessType.IAT_PVALUE : InfoAccessType.IAT_VALUE; + } } } diff --git a/src/JitInterface/src/CorInfoImpl.cs b/src/JitInterface/src/CorInfoImpl.cs index 3d1559d85c9..c093b402e63 100644 --- a/src/JitInterface/src/CorInfoImpl.cs +++ b/src/JitInterface/src/CorInfoImpl.cs @@ -923,66 +923,6 @@ private void getMethodVTableOffset(CORINFO_METHOD_STRUCT_* method, ref uint offs return impl != null ? ObjectToHandle(impl) : null; } - private void ComputeLookup(ref CORINFO_RESOLVED_TOKEN pResolvedToken, object entity, ReadyToRunHelperId helperId, ref CORINFO_LOOKUP lookup) - { - if (_compilation.NeedsRuntimeLookup(helperId, entity)) - { - lookup.lookupKind.needsRuntimeLookup = true; - lookup.runtimeLookup.signature = null; - - MethodDesc contextMethod = methodFromContext(pResolvedToken.tokenContext); - - // Do not bother computing the runtime lookup if we are inlining. The JIT is going - // to abort the inlining attempt anyway. - if (contextMethod != MethodBeingCompiled) - return; - - // Necessary type handle is not something that can be in a dictionary (only a constructed type). - // We only use necessary type handles if we can do a constant lookup. - if (helperId == ReadyToRunHelperId.NecessaryTypeHandle) - helperId = ReadyToRunHelperId.TypeHandle; - - GenericDictionaryLookup genericLookup = _compilation.ComputeGenericLookup(contextMethod, helperId, entity); - - if (genericLookup.UseHelper) - { - lookup.runtimeLookup.indirections = CORINFO.USEHELPER; - lookup.lookupKind.runtimeLookupFlags = (ushort)helperId; - lookup.lookupKind.runtimeLookupArgs = (void*)ObjectToHandle(entity); - } - else - { - if (genericLookup.ContextSource == GenericContextSource.MethodParameter) - { - lookup.runtimeLookup.helper = CorInfoHelpFunc.CORINFO_HELP_RUNTIMEHANDLE_METHOD; - } - else - { - lookup.runtimeLookup.helper = CorInfoHelpFunc.CORINFO_HELP_RUNTIMEHANDLE_CLASS; - } - - lookup.runtimeLookup.indirections = (ushort)genericLookup.NumberOfIndirections; - lookup.runtimeLookup.offset0 = (IntPtr)genericLookup[0]; - if (genericLookup.NumberOfIndirections > 1) - lookup.runtimeLookup.offset1 = (IntPtr)genericLookup[1]; - lookup.runtimeLookup.testForFixup = false; // TODO: this will be needed in true multifile - lookup.runtimeLookup.testForNull = false; - lookup.runtimeLookup.indirectFirstOffset = false; - lookup.runtimeLookup.indirectSecondOffset = false; - lookup.lookupKind.runtimeLookupFlags = 0; - lookup.lookupKind.runtimeLookupArgs = null; - } - - lookup.lookupKind.runtimeLookupKind = GetLookupKindFromContextSource(genericLookup.ContextSource); - } - else - { - lookup.lookupKind.needsRuntimeLookup = false; - ISymbolNode constLookup = _compilation.ComputeConstantLookup(helperId, entity); - lookup.constLookup = CreateConstLookupToSymbol(constLookup); - } - } - private CORINFO_METHOD_STRUCT_* getUnboxedEntry(CORINFO_METHOD_STRUCT_* ftn, byte* requiresInstMethodTableArg) { throw new NotImplementedException(); } @@ -1626,136 +1566,6 @@ private ISymbolNode GetGenericLookupHelper(CORINFO_RUNTIME_LOOKUP_KIND runtimeLo return _compilation.NodeFactory.ReadyToRunHelperFromDictionaryLookup(helperId, helperArgument, MethodBeingCompiled); } - private bool getReadyToRunHelper(ref CORINFO_RESOLVED_TOKEN pResolvedToken, ref CORINFO_LOOKUP_KIND pGenericLookupKind, CorInfoHelpFunc id, ref CORINFO_CONST_LOOKUP pLookup) - { - switch (id) - { - case CorInfoHelpFunc.CORINFO_HELP_READYTORUN_NEW: - { - var type = HandleToObject(pResolvedToken.hClass); - Debug.Assert(type.IsDefType); - if (type.IsCanonicalSubtype(CanonicalFormKind.Any)) - return false; - - pLookup = CreateConstLookupToSymbol(_compilation.NodeFactory.ReadyToRunHelper(ReadyToRunHelperId.NewHelper, type)); - } - break; - case CorInfoHelpFunc.CORINFO_HELP_READYTORUN_NEWARR_1: - { - var type = HandleToObject(pResolvedToken.hClass); - Debug.Assert(type.IsSzArray); - if (type.IsCanonicalSubtype(CanonicalFormKind.Any)) - return false; - - pLookup = CreateConstLookupToSymbol(_compilation.NodeFactory.ReadyToRunHelper(ReadyToRunHelperId.NewArr1, type)); - } - break; - case CorInfoHelpFunc.CORINFO_HELP_READYTORUN_ISINSTANCEOF: - { - var type = HandleToObject(pResolvedToken.hClass); - if (type.IsCanonicalSubtype(CanonicalFormKind.Any)) - return false; - - // ECMA-335 III.4.3: If typeTok is a nullable type, Nullable, it is interpreted as "boxed" T - if (type.IsNullable) - type = type.Instantiation[0]; - - pLookup = CreateConstLookupToSymbol(_compilation.NodeFactory.ReadyToRunHelper(ReadyToRunHelperId.IsInstanceOf, type)); - } - break; - case CorInfoHelpFunc.CORINFO_HELP_READYTORUN_CHKCAST: - { - var type = HandleToObject(pResolvedToken.hClass); - if (type.IsCanonicalSubtype(CanonicalFormKind.Any)) - return false; - - // ECMA-335 III.4.3: If typeTok is a nullable type, Nullable, it is interpreted as "boxed" T - if (type.IsNullable) - type = type.Instantiation[0]; - - pLookup = CreateConstLookupToSymbol(_compilation.NodeFactory.ReadyToRunHelper(ReadyToRunHelperId.CastClass, type)); - } - break; - case CorInfoHelpFunc.CORINFO_HELP_READYTORUN_STATIC_BASE: - { - var type = HandleToObject(pResolvedToken.hClass); - if (type.IsCanonicalSubtype(CanonicalFormKind.Any)) - return false; - - pLookup = CreateConstLookupToSymbol(_compilation.NodeFactory.ReadyToRunHelper(ReadyToRunHelperId.GetNonGCStaticBase, type)); - } - break; - case CorInfoHelpFunc.CORINFO_HELP_READYTORUN_GENERIC_STATIC_BASE: - { - // Token == 0 means "initialize this class". We only expect RyuJIT to call it for this case. - Debug.Assert(pResolvedToken.token == 0 && pResolvedToken.tokenScope == null); - Debug.Assert(pGenericLookupKind.needsRuntimeLookup); - - DefType typeToInitialize = (DefType)MethodBeingCompiled.OwningType; - Debug.Assert(typeToInitialize.IsCanonicalSubtype(CanonicalFormKind.Any)); - - DefType helperArg = typeToInitialize.ConvertToSharedRuntimeDeterminedForm(); - ISymbolNode helper = GetGenericLookupHelper(pGenericLookupKind.runtimeLookupKind, ReadyToRunHelperId.GetNonGCStaticBase, helperArg); - pLookup = CreateConstLookupToSymbol(helper); - } - break; - case CorInfoHelpFunc.CORINFO_HELP_READYTORUN_GENERIC_HANDLE: - { - Debug.Assert(pGenericLookupKind.needsRuntimeLookup); - - ReadyToRunHelperId helperId = (ReadyToRunHelperId)pGenericLookupKind.runtimeLookupFlags; - object helperArg = HandleToObject((IntPtr)pGenericLookupKind.runtimeLookupArgs); - ISymbolNode helper = GetGenericLookupHelper(pGenericLookupKind.runtimeLookupKind, helperId, helperArg); - pLookup = CreateConstLookupToSymbol(helper); - } - break; - default: - throw new NotImplementedException("ReadyToRun: " + id.ToString()); - } - return true; - } - - private void getReadyToRunDelegateCtorHelper(ref CORINFO_RESOLVED_TOKEN pTargetMethod, CORINFO_CLASS_STRUCT_* delegateType, ref CORINFO_LOOKUP pLookup) - { -#if DEBUG - // In debug, write some bogus data to the struct to ensure we have filled everything - // properly. - fixed (CORINFO_LOOKUP* tmp = &pLookup) - MemoryHelper.FillMemory((byte*)tmp, 0xcc, sizeof(CORINFO_LOOKUP)); -#endif - - MethodDesc targetMethod = HandleToObject(pTargetMethod.hMethod); - TypeDesc delegateTypeDesc = HandleToObject(delegateType); - - if (targetMethod.IsSharedByGenericInstantiations) - { - // If the method is not exact, fetch it as a runtime determined method. - targetMethod = (MethodDesc)GetRuntimeDeterminedObjectForToken(ref pTargetMethod); - } - - bool isLdvirtftn = pTargetMethod.tokenType == CorInfoTokenKind.CORINFO_TOKENKIND_Ldvirtftn; - DelegateCreationInfo delegateInfo = _compilation.GetDelegateCtor(delegateTypeDesc, targetMethod, isLdvirtftn); - - if (delegateInfo.NeedsRuntimeLookup) - { - pLookup.lookupKind.needsRuntimeLookup = true; - - MethodDesc contextMethod = methodFromContext(pTargetMethod.tokenContext); - - // We should not be inlining these. RyuJIT should have aborted inlining already. - Debug.Assert(contextMethod == MethodBeingCompiled); - - pLookup.lookupKind.runtimeLookupKind = GetGenericRuntimeLookupKind(contextMethod); - pLookup.lookupKind.runtimeLookupFlags = (ushort)ReadyToRunHelperId.DelegateCtor; - pLookup.lookupKind.runtimeLookupArgs = (void*)ObjectToHandle(delegateInfo); - } - else - { - pLookup.lookupKind.needsRuntimeLookup = false; - pLookup.constLookup = CreateConstLookupToSymbol(_compilation.NodeFactory.ReadyToRunHelper(ReadyToRunHelperId.DelegateCtor, delegateInfo)); - } - } - private byte* getHelperName(CorInfoHelpFunc helpFunc) { return (byte*)GetPin(StringToUTF8(helpFunc.ToString())); @@ -2564,7 +2374,7 @@ private void getEEInfo(ref CORINFO_EE_INFO pEEInfoOut) pEEInfoOut.maxUncheckedOffsetForNullObject = (_compilation.NodeFactory.Target.IsWindows) ? new UIntPtr(32 * 1024 - 1) : new UIntPtr((uint)pEEInfoOut.osPageSize / 2 - 1); - pEEInfoOut.targetAbi = CORINFO_RUNTIME_ABI.CORINFO_CORERT_ABI; + pEEInfoOut.targetAbi = TargetABI; } private string getJitTimeLogFilename() @@ -2678,116 +2488,6 @@ private uint getThreadTLSIndex(ref void* ppIndirection) { throw new NotImplementedException("getAddrOfCaptureThreadGlobal"); } private Dictionary _helperCache = new Dictionary(); - private ISymbolNode GetHelperFtnUncached(CorInfoHelpFunc ftnNum) - { - ReadyToRunHelper id; - - switch (ftnNum) - { - case CorInfoHelpFunc.CORINFO_HELP_THROW: id = ReadyToRunHelper.Throw; break; - case CorInfoHelpFunc.CORINFO_HELP_RETHROW: id = ReadyToRunHelper.Rethrow; break; - case CorInfoHelpFunc.CORINFO_HELP_USER_BREAKPOINT: id = ReadyToRunHelper.DebugBreak; break; - case CorInfoHelpFunc.CORINFO_HELP_OVERFLOW: id = ReadyToRunHelper.Overflow; break; - case CorInfoHelpFunc.CORINFO_HELP_RNGCHKFAIL: id = ReadyToRunHelper.RngChkFail; break; - case CorInfoHelpFunc.CORINFO_HELP_FAIL_FAST: id = ReadyToRunHelper.FailFast; break; - case CorInfoHelpFunc.CORINFO_HELP_THROWNULLREF: id = ReadyToRunHelper.ThrowNullRef; break; - case CorInfoHelpFunc.CORINFO_HELP_THROWDIVZERO: id = ReadyToRunHelper.ThrowDivZero; break; - case CorInfoHelpFunc.CORINFO_HELP_THROW_ARGUMENTOUTOFRANGEEXCEPTION: id = ReadyToRunHelper.ThrowArgumentOutOfRange; break; - case CorInfoHelpFunc.CORINFO_HELP_THROW_ARGUMENTEXCEPTION: id = ReadyToRunHelper.ThrowArgument; break; - case CorInfoHelpFunc.CORINFO_HELP_THROW_PLATFORM_NOT_SUPPORTED: id = ReadyToRunHelper.ThrowPlatformNotSupported; break; - - case CorInfoHelpFunc.CORINFO_HELP_ASSIGN_REF: id = ReadyToRunHelper.WriteBarrier; break; - case CorInfoHelpFunc.CORINFO_HELP_CHECKED_ASSIGN_REF: id = ReadyToRunHelper.CheckedWriteBarrier; break; - case CorInfoHelpFunc.CORINFO_HELP_ASSIGN_BYREF: id = ReadyToRunHelper.ByRefWriteBarrier; break; - - case CorInfoHelpFunc.CORINFO_HELP_ARRADDR_ST: id = ReadyToRunHelper.Stelem_Ref; break; - case CorInfoHelpFunc.CORINFO_HELP_LDELEMA_REF: id = ReadyToRunHelper.Ldelema_Ref; break; - - case CorInfoHelpFunc.CORINFO_HELP_MEMSET: id = ReadyToRunHelper.MemSet; break; - case CorInfoHelpFunc.CORINFO_HELP_MEMCPY: id = ReadyToRunHelper.MemCpy; break; - - case CorInfoHelpFunc.CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE: id = ReadyToRunHelper.GetRuntimeTypeHandle; break; - case CorInfoHelpFunc.CORINFO_HELP_METHODDESC_TO_STUBRUNTIMEMETHOD: id = ReadyToRunHelper.GetRuntimeMethodHandle; break; - case CorInfoHelpFunc.CORINFO_HELP_FIELDDESC_TO_STUBRUNTIMEFIELD: id = ReadyToRunHelper.GetRuntimeFieldHandle; break; - - case CorInfoHelpFunc.CORINFO_HELP_BOX: id = ReadyToRunHelper.Box; break; - case CorInfoHelpFunc.CORINFO_HELP_BOX_NULLABLE: id = ReadyToRunHelper.Box_Nullable; break; - case CorInfoHelpFunc.CORINFO_HELP_UNBOX: id = ReadyToRunHelper.Unbox; break; - case CorInfoHelpFunc.CORINFO_HELP_UNBOX_NULLABLE: id = ReadyToRunHelper.Unbox_Nullable; break; - case CorInfoHelpFunc.CORINFO_HELP_NEW_MDARR_NONVARARG: id = ReadyToRunHelper.NewMultiDimArr_NonVarArg; break; - case CorInfoHelpFunc.CORINFO_HELP_NEWFAST: id = ReadyToRunHelper.NewObject; break; - case CorInfoHelpFunc.CORINFO_HELP_NEWARR_1_DIRECT: id = ReadyToRunHelper.NewArray; break; - - case CorInfoHelpFunc.CORINFO_HELP_LMUL: id = ReadyToRunHelper.LMul; break; - case CorInfoHelpFunc.CORINFO_HELP_LMUL_OVF: id = ReadyToRunHelper.LMulOfv; break; - case CorInfoHelpFunc.CORINFO_HELP_ULMUL_OVF: id = ReadyToRunHelper.ULMulOvf; break; - case CorInfoHelpFunc.CORINFO_HELP_LDIV: id = ReadyToRunHelper.LDiv; break; - case CorInfoHelpFunc.CORINFO_HELP_LMOD: id = ReadyToRunHelper.LMod; break; - case CorInfoHelpFunc.CORINFO_HELP_ULDIV: id = ReadyToRunHelper.ULDiv; break; - case CorInfoHelpFunc.CORINFO_HELP_ULMOD: id = ReadyToRunHelper.ULMod; break; - case CorInfoHelpFunc.CORINFO_HELP_LLSH: id = ReadyToRunHelper.LLsh; break; - case CorInfoHelpFunc.CORINFO_HELP_LRSH: id = ReadyToRunHelper.LRsh; break; - case CorInfoHelpFunc.CORINFO_HELP_LRSZ: id = ReadyToRunHelper.LRsz; break; - case CorInfoHelpFunc.CORINFO_HELP_LNG2DBL: id = ReadyToRunHelper.Lng2Dbl; break; - case CorInfoHelpFunc.CORINFO_HELP_ULNG2DBL: id = ReadyToRunHelper.ULng2Dbl; break; - - case CorInfoHelpFunc.CORINFO_HELP_DIV: id = ReadyToRunHelper.Div; break; - case CorInfoHelpFunc.CORINFO_HELP_MOD: id = ReadyToRunHelper.Mod; break; - case CorInfoHelpFunc.CORINFO_HELP_UDIV: id = ReadyToRunHelper.UDiv; break; - case CorInfoHelpFunc.CORINFO_HELP_UMOD: id = ReadyToRunHelper.UMod; break; - - case CorInfoHelpFunc.CORINFO_HELP_DBL2INT: id = ReadyToRunHelper.Dbl2Int; break; - case CorInfoHelpFunc.CORINFO_HELP_DBL2INT_OVF: id = ReadyToRunHelper.Dbl2IntOvf; break; - case CorInfoHelpFunc.CORINFO_HELP_DBL2LNG: id = ReadyToRunHelper.Dbl2Lng; break; - case CorInfoHelpFunc.CORINFO_HELP_DBL2LNG_OVF: id = ReadyToRunHelper.Dbl2LngOvf; break; - case CorInfoHelpFunc.CORINFO_HELP_DBL2UINT: id = ReadyToRunHelper.Dbl2UInt; break; - case CorInfoHelpFunc.CORINFO_HELP_DBL2UINT_OVF: id = ReadyToRunHelper.Dbl2UIntOvf; break; - case CorInfoHelpFunc.CORINFO_HELP_DBL2ULNG: id = ReadyToRunHelper.Dbl2ULng; break; - case CorInfoHelpFunc.CORINFO_HELP_DBL2ULNG_OVF: id = ReadyToRunHelper.Dbl2ULngOvf; break; - - case CorInfoHelpFunc.CORINFO_HELP_FLTREM: id = ReadyToRunHelper.FltRem; break; - case CorInfoHelpFunc.CORINFO_HELP_DBLREM: id = ReadyToRunHelper.DblRem; break; - case CorInfoHelpFunc.CORINFO_HELP_FLTROUND: id = ReadyToRunHelper.FltRound; break; - case CorInfoHelpFunc.CORINFO_HELP_DBLROUND: id = ReadyToRunHelper.DblRound; break; - - case CorInfoHelpFunc.CORINFO_HELP_JIT_PINVOKE_BEGIN: id = ReadyToRunHelper.PInvokeBegin; break; - case CorInfoHelpFunc.CORINFO_HELP_JIT_PINVOKE_END: id = ReadyToRunHelper.PInvokeEnd; break; - - case CorInfoHelpFunc.CORINFO_HELP_JIT_REVERSE_PINVOKE_ENTER: id = ReadyToRunHelper.ReversePInvokeEnter; break; - case CorInfoHelpFunc.CORINFO_HELP_JIT_REVERSE_PINVOKE_EXIT: id = ReadyToRunHelper.ReversePInvokeExit; break; - - case CorInfoHelpFunc.CORINFO_HELP_CHKCASTANY: id = ReadyToRunHelper.CheckCastAny; break; - case CorInfoHelpFunc.CORINFO_HELP_ISINSTANCEOFANY: id = ReadyToRunHelper.CheckInstanceAny; break; - - case CorInfoHelpFunc.CORINFO_HELP_MON_ENTER: id = ReadyToRunHelper.MonitorEnter; break; - case CorInfoHelpFunc.CORINFO_HELP_MON_EXIT: id = ReadyToRunHelper.MonitorExit; break; - - case CorInfoHelpFunc.CORINFO_HELP_MON_ENTER_STATIC: id = ReadyToRunHelper.MonitorEnterStatic; break; - case CorInfoHelpFunc.CORINFO_HELP_MON_EXIT_STATIC: id = ReadyToRunHelper.MonitorExitStatic; break; - - case CorInfoHelpFunc.CORINFO_HELP_GVMLOOKUP_FOR_SLOT: id = ReadyToRunHelper.GVMLookupForSlot; break; - - case CorInfoHelpFunc.CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE_MAYBENULL: id = ReadyToRunHelper.TypeHandleToRuntimeType; break; - case CorInfoHelpFunc.CORINFO_HELP_GETREFANY: id = ReadyToRunHelper.GetRefAny; break; - - default: - throw new NotImplementedException(ftnNum.ToString()); - } - - string mangledName; - MethodDesc methodDesc; - JitHelper.GetEntryPoint(_compilation.TypeSystemContext, id, out mangledName, out methodDesc); - Debug.Assert(mangledName != null || methodDesc != null); - - ISymbolNode entryPoint; - if (mangledName != null) - entryPoint = _compilation.NodeFactory.ExternSymbol(mangledName); - else - entryPoint = _compilation.NodeFactory.MethodEntrypoint(methodDesc); - - return entryPoint; - } - private void* getHelperFtn(CorInfoHelpFunc ftnNum, ref void* ppIndirection) { ISymbolNode entryPoint; @@ -2796,19 +2496,16 @@ private ISymbolNode GetHelperFtnUncached(CorInfoHelpFunc ftnNum) entryPoint = GetHelperFtnUncached(ftnNum); _helperCache.Add(ftnNum, entryPoint); } - ppIndirection = null; - return (void*)ObjectToHandle(entryPoint); - } - - private void getFunctionEntryPoint(CORINFO_METHOD_STRUCT_* ftn, ref CORINFO_CONST_LOOKUP pResult, CORINFO_ACCESS_FLAGS accessFlags) - { - MethodDesc method = HandleToObject(ftn); - - // TODO: Implement MapMethodDeclToMethodImpl from CoreCLR - if (method.IsVirtual) - throw new NotImplementedException("getFunctionEntryPoint"); - - pResult = CreateConstLookupToSymbol(_compilation.NodeFactory.MethodEntrypoint(method)); + if (entryPoint.RepresentsIndirectionCell) + { + ppIndirection = (void*)ObjectToHandle(entryPoint); + return null; + } + else + { + ppIndirection = null; + return (void*)ObjectToHandle(entryPoint); + } } private void getFunctionFixedEntryPoint(CORINFO_METHOD_STRUCT_* ftn, ref CORINFO_CONST_LOOKUP pResult) @@ -3438,15 +3135,6 @@ private IntPtr getVarArgsHandle(CORINFO_SIG_INFO* pSig, ref void* ppIndirection) private bool canGetVarArgsHandle(CORINFO_SIG_INFO* pSig) { throw new NotImplementedException("canGetVarArgsHandle"); } - private InfoAccessType constructStringLiteral(CORINFO_MODULE_STRUCT_* module, mdToken metaTok, ref void* ppValue) - { - MethodIL methodIL = (MethodIL)HandleToObject((IntPtr)module); - object literal = methodIL.GetObject((int)metaTok); - ISymbolNode stringObject = _compilation.NodeFactory.SerializedStringObject((string)literal); - ppValue = (void*)ObjectToHandle(stringObject); - return stringObject.RepresentsIndirectionCell ? InfoAccessType.IAT_PVALUE : InfoAccessType.IAT_VALUE; - } - private InfoAccessType emptyStringLiteral(ref void* ppValue) { throw new NotImplementedException("emptyStringLiteral"); } private uint getFieldThreadLocalStoreID(CORINFO_FIELD_STRUCT_* field, ref void* ppIndirection)