Example #1
0
        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);
            }
        }
Example #2
0
        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);
            }
        }
Example #3
0
        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);
        }
Example #4
0
        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));
        }
Example #5
0
        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));
            }
        }
Example #6
0
        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);
        }
Example #7
0
        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);
        }