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)); }
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; } }
// 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); }