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 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 != _methodCodeNode.Method) { return; } // There is a pathological case where invalid IL refereces __Canon type directly, but there is no dictionary available to store the lookup. // All callers of ComputeRuntimeLookupForSharedGenericToken have to filter out this case. We can't do much about it here. Debug.Assert(contextMethod.IsSharedByGenericInstantiations); if (contextMethod.RequiresInstMethodDescArg()) { lookup.lookupKind.runtimeLookupKind = CORINFO_RUNTIME_LOOKUP_KIND.CORINFO_LOOKUP_METHODPARAM; } else { if (contextMethod.RequiresInstMethodTableArg()) { lookup.lookupKind.runtimeLookupKind = CORINFO_RUNTIME_LOOKUP_KIND.CORINFO_LOOKUP_CLASSPARAM; } else { lookup.lookupKind.runtimeLookupKind = CORINFO_RUNTIME_LOOKUP_KIND.CORINFO_LOOKUP_THISOBJ; } } // Unless we decide otherwise, just do the lookup via a helper function lookup.runtimeLookup.indirections = CORINFO.USEHELPER; lookup.lookupKind.runtimeLookupFlags = (ushort)helperId; lookup.lookupKind.runtimeLookupArgs = (void *)ObjectToHandle(entity); lookup.runtimeLookup.indirectFirstOffset = false; lookup.runtimeLookup.indirectSecondOffset = false; // For R2R compilations, we don't generate the dictionary lookup signatures (dictionary lookups are done in a // different way that is more version resilient... plus we can't have pointers to existing MTs/MDs in the sigs) } else { lookup.lookupKind.needsRuntimeLookup = false; ISymbolNode constLookup = _compilation.SymbolNodeFactory.ComputeConstantLookup(helperId, entity, _signatureContext); 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: case CorInfoHelpFunc.CORINFO_HELP_READYTORUN_NEWARR_1: case CorInfoHelpFunc.CORINFO_HELP_READYTORUN_ISINSTANCEOF: case CorInfoHelpFunc.CORINFO_HELP_READYTORUN_CHKCAST: return(false); 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); pLookup.lookupKind.needsRuntimeLookup = false; pLookup.constLookup = CreateConstLookupToSymbol(_compilation.SymbolNodeFactory.DelegateCtor( delegateTypeDesc, targetMethod, new ModuleToken(_tokenContext, (mdToken)pTargetMethod.token), _signatureContext)); }
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); } /* TODO * 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.SymbolNodeFactory.DelegateCtor( delegateTypeDesc, targetMethod, new ModuleToken(_tokenContext, (mdToken)pTargetMethod.token), _signatureContext)); } }
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.SymbolNodeFactory.ReadyToRunHelper(ReadyToRunHelperId.NewHelper, type, _signatureContext)); } 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.SymbolNodeFactory.ReadyToRunHelper(ReadyToRunHelperId.NewArr1, type, _signatureContext)); } 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<T>, it is interpreted as "boxed" T if (type.IsNullable) { type = type.Instantiation[0]; } pLookup = CreateConstLookupToSymbol(_compilation.SymbolNodeFactory.ReadyToRunHelper(ReadyToRunHelperId.IsInstanceOf, type, _signatureContext)); } 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<T>, it is interpreted as "boxed" T if (type.IsNullable) { type = type.Instantiation[0]; } pLookup = CreateConstLookupToSymbol(_compilation.SymbolNodeFactory.ReadyToRunHelper(ReadyToRunHelperId.CastClass, type, _signatureContext)); } break; case CorInfoHelpFunc.CORINFO_HELP_READYTORUN_STATIC_BASE: { var type = HandleToObject(pResolvedToken.hClass); if (type.IsCanonicalSubtype(CanonicalFormKind.Any)) { return(false); } pLookup = CreateConstLookupToSymbol(_compilation.SymbolNodeFactory.ReadyToRunHelper(ReadyToRunHelperId.CctorTrigger, type, _signatureContext)); } break; case CorInfoHelpFunc.CORINFO_HELP_READYTORUN_GENERIC_HANDLE: { Debug.Assert(pGenericLookupKind.needsRuntimeLookup); ReadyToRunHelperId helperId = (ReadyToRunHelperId)pGenericLookupKind.runtimeLookupFlags; object helperArg = HandleToObject((IntPtr)pGenericLookupKind.runtimeLookupArgs); if (helperArg is MethodDesc methodArg) { helperArg = new MethodWithToken(methodArg, new ModuleToken(_tokenContext, pResolvedToken.token)); } GenericContext methodContext = new GenericContext(entityFromContext(pResolvedToken.tokenContext)); ISymbolNode helper = _compilation.SymbolNodeFactory.GenericLookupHelper( pGenericLookupKind.runtimeLookupKind, helperId, helperArg, methodContext, _signatureContext); pLookup = CreateConstLookupToSymbol(helper); } break; default: throw new NotImplementedException("ReadyToRun: " + id.ToString()); } return(true); }
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.SymbolNodeFactory.ReadyToRunHelper(ReadyToRunHelperId.NewHelper, type, _signatureContext)); } 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.SymbolNodeFactory.ReadyToRunHelper(ReadyToRunHelperId.NewArr1, type, _signatureContext)); } 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<T>, it is interpreted as "boxed" T if (type.IsNullable) { type = type.Instantiation[0]; } pLookup = CreateConstLookupToSymbol(_compilation.SymbolNodeFactory.ReadyToRunHelper(ReadyToRunHelperId.IsInstanceOf, type, _signatureContext)); } 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<T>, it is interpreted as "boxed" T if (type.IsNullable) { type = type.Instantiation[0]; } pLookup = CreateConstLookupToSymbol(_compilation.SymbolNodeFactory.ReadyToRunHelper(ReadyToRunHelperId.CastClass, type, _signatureContext)); } break; case CorInfoHelpFunc.CORINFO_HELP_READYTORUN_STATIC_BASE: { var type = HandleToObject(pResolvedToken.hClass); if (type.IsCanonicalSubtype(CanonicalFormKind.Any)) { return(false); } pLookup = CreateConstLookupToSymbol(_compilation.SymbolNodeFactory.ReadyToRunHelper(ReadyToRunHelperId.GetNonGCStaticBase, type, _signatureContext)); } 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(); TypeDesc contextType; if (pGenericLookupKind.runtimeLookupKind == CORINFO_RUNTIME_LOOKUP_KIND.CORINFO_LOOKUP_THISOBJ) { contextType = methodFromContext(pResolvedToken.tokenContext).OwningType; } else { contextType = null; } ISymbolNode helper = _compilation.SymbolNodeFactory.GenericLookupHelper( pGenericLookupKind.runtimeLookupKind, ReadyToRunHelperId.GetNonGCStaticBase, helperArg, contextType, _signatureContext); 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); if (helperArg is MethodDesc methodArg) { helperArg = new MethodWithToken(methodArg, new ModuleToken(_tokenContext, pResolvedToken.token)); } TypeDesc contextType; if (pGenericLookupKind.runtimeLookupKind == CORINFO_RUNTIME_LOOKUP_KIND.CORINFO_LOOKUP_THISOBJ) { contextType = methodFromContext(pResolvedToken.tokenContext).OwningType; } else { contextType = null; } ISymbolNode helper = _compilation.SymbolNodeFactory.GenericLookupHelper( pGenericLookupKind.runtimeLookupKind, helperId, helperArg, contextType, _signatureContext); pLookup = CreateConstLookupToSymbol(helper); } break; default: throw new NotImplementedException("ReadyToRun: " + id.ToString()); } return(true); }