Example #1
0
        public NativeParser GetParserForUniversalNativeLayoutInfo(out NativeLayoutInfoLoadContext universalLayoutLoadContext, out NativeLayoutInfo universalLayoutInfo)
        {
            universalLayoutInfo        = new NativeLayoutInfo();
            universalLayoutLoadContext = null;
            TypeDesc universalTemplate = TemplateLocator.TryGetUniversalTypeTemplate(TypeBeingBuilt, ref universalLayoutInfo);

            if (universalTemplate == null)
            {
                return(new NativeParser());
            }

            FinishInitNativeLayoutInfo(TypeBeingBuilt, ref universalLayoutInfo);
            universalLayoutLoadContext = universalLayoutInfo.LoadContext;
            return(new NativeParser(universalLayoutInfo.Reader, universalLayoutInfo.Offset));
        }
Example #2
0
        private void EnsureNativeLayoutInfoComputed()
        {
            if (!_nativeLayoutComputed)
            {
                if (!_nativeLayoutTokenComputed)
                {
                    if (!_templateComputed)
                    {
                        // Attempt to compute native layout through as a non-ReadyToRun template
                        object _ = this.TemplateType;
                    }
                    if (!_nativeLayoutTokenComputed)
                    {
                        TemplateLocator.TryGetMetadataNativeLayout(TypeBeingBuilt, out _r2rnativeLayoutInfo.Module, out _r2rnativeLayoutInfo.Offset);

                        if (_r2rnativeLayoutInfo.Module != null)
                        {
                            _readyToRunNativeLayout = true;
                        }
                    }
                    _nativeLayoutTokenComputed = true;
                }

                if (_nativeLayoutInfo.Module != null)
                {
                    FinishInitNativeLayoutInfo(TypeBeingBuilt, ref _nativeLayoutInfo);
                }

                if (_r2rnativeLayoutInfo.Module != null)
                {
                    FinishInitNativeLayoutInfo(TypeBeingBuilt, ref _r2rnativeLayoutInfo);
                }

                _nativeLayoutComputed = true;
            }
        }
Example #3
0
        // This method computes the method pointer and dictionary pointer for a GVM.
        // Inputs:
        //      - targetTypeHanlde: target type on which the GVM is implemented
        //      - nameAndSignature: name and signature of the GVM method
        //      - genericMethodArgumentHandles: GVM instantiation arguments
        // Outputs:
        //      - methodPointer: pointer to the GVM's implementation
        //      - dictionaryPointer: (if applicable) pointer to the dictionary to be used with the GVM call
        public bool TryGetGenericVirtualMethodPointer(RuntimeTypeHandle targetTypeHandle, MethodNameAndSignature nameAndSignature, RuntimeTypeHandle[] genericMethodArgumentHandles, out IntPtr methodPointer, out IntPtr dictionaryPointer)
        {
            methodPointer = dictionaryPointer = IntPtr.Zero;

            TypeSystemContext context = TypeSystemContextFactory.Create();

            DefType            targetType          = (DefType)context.ResolveRuntimeTypeHandle(targetTypeHandle);
            Instantiation      methodInstantiation = context.ResolveRuntimeTypeHandles(genericMethodArgumentHandles);
            InstantiatedMethod method = (InstantiatedMethod)context.ResolveGenericMethodInstantiation(false, targetType, nameAndSignature, methodInstantiation, IntPtr.Zero, false);

            if (!method.CanShareNormalGenericCode())
            {
                // First see if we can find an exact method implementation for the GVM (avoid using USG implementations if we can,
                // because USG code is much slower).
                if (TryLookupExactMethodPointerForComponents(targetTypeHandle, nameAndSignature, genericMethodArgumentHandles, out methodPointer))
                {
                    Debug.Assert(methodPointer != IntPtr.Zero);
                    TypeSystemContextFactory.Recycle(context);
                    return(true);
                }
            }

            // If we cannot find an exact method entry point, look for an equivalent template and compute the generic dictinoary
            TemplateLocator    templateLocator  = new TemplateLocator();
            NativeLayoutInfo   nativeLayoutInfo = new NativeLayoutInfo();
            InstantiatedMethod templateMethod   = templateLocator.TryGetGenericMethodTemplate(method, out nativeLayoutInfo.Module, out nativeLayoutInfo.Token);

            if (templateMethod == null)
            {
                return(false);
            }

            methodPointer = templateMethod.IsCanonicalMethod(CanonicalFormKind.Universal) ?
                            templateMethod.UsgFunctionPointer :
                            templateMethod.FunctionPointer;

            if (!TryLookupGenericMethodDictionaryForComponents(targetTypeHandle, nameAndSignature, genericMethodArgumentHandles, out dictionaryPointer))
            {
                using (LockHolder.Hold(_typeLoaderLock))
                {
                    // Now that we hold the lock, we may find that existing types can now find
                    // their associated RuntimeTypeHandle. Flush the type builder states as a way
                    // to force the reresolution of RuntimeTypeHandles which couldn't be found before.
                    context.FlushTypeBuilderStates();

                    if (!TypeBuilder.TryBuildGenericMethod(method, out dictionaryPointer))
                    {
                        return(false);
                    }
                }
            }

            Debug.Assert(methodPointer != IntPtr.Zero && dictionaryPointer != IntPtr.Zero);

            if (templateMethod.IsCanonicalMethod(CanonicalFormKind.Universal))
            {
                // Check if we need to wrap the method pointer into a calling convention converter thunk
                if (!TypeLoaderEnvironment.Instance.MethodSignatureHasVarsNeedingCallingConventionConverter(context, nameAndSignature.Signature))
                {
                    TypeSystemContextFactory.Recycle(context);
                    return(true);
                }

                RuntimeTypeHandle[] typeArgs = Array.Empty <RuntimeTypeHandle>();

                if (RuntimeAugments.IsGenericType(targetTypeHandle))
                {
                    RuntimeAugments.GetGenericInstantiation(targetTypeHandle, out typeArgs);
                }

                // Create a CallingConventionConverter to call the method correctly
                IntPtr thunkPtr = CallConverterThunk.MakeThunk(
                    CallConverterThunk.ThunkKind.StandardToGenericInstantiating,
                    methodPointer,
                    nameAndSignature.Signature,
                    dictionaryPointer,
                    typeArgs,
                    genericMethodArgumentHandles);

                Debug.Assert(thunkPtr != IntPtr.Zero);

                methodPointer = thunkPtr;
                // Set dictionaryPointer to null so we don't make a fat function pointer around the whole thing.
                dictionaryPointer = IntPtr.Zero;

                // TODO! add a new call converter thunk that will pass the instantiating arg through and use a fat function pointer.
                // should allow us to make fewer thunks.
            }

            TypeSystemContextFactory.Recycle(context);
            return(true);
        }