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)