public bool ConversionToCanonFormIsAChange(RuntimeTypeHandle[] genericArgHandles, CanonicalFormKind kind) { // Todo: support for universal canon type? TypeSystemContext context = TypeSystemContextFactory.Create(); Instantiation genericArgs = context.ResolveRuntimeTypeHandles(genericArgHandles); bool result; context.ConvertInstantiationToCanonForm(genericArgs, kind, out result); TypeSystemContextFactory.Recycle(context); return result; }
internal override bool MatchParsedEntry(RuntimeTypeHandle tentativeType) { // // Entries read from the hashtable are loaded as DefTypes, and compared to the input. // This lookup is slower than the lookups using RuntimeTypeHandles, but can handle cases where we don't have // RuntimeTypeHandle values for all of the components of the input DefType, but still need to look it up in case the type // statically exists and has an existing RuntimeTypeHandle value. // TypeSystemContext context = _typeToLookup.Context; RuntimeTypeHandle[] parsedArgsHandles; RuntimeTypeHandle parsedTypeDefinitionHandle = RuntimeAugments.GetGenericInstantiation(tentativeType, out parsedArgsHandles); DefType parsedTypeDefinition = (DefType)context.ResolveRuntimeTypeHandle(parsedTypeDefinitionHandle); Instantiation parsedArgs = context.ResolveRuntimeTypeHandles(parsedArgsHandles); DefType parsedGenericType = context.ResolveGenericInstantiation(parsedTypeDefinition, parsedArgs); return(parsedGenericType == _typeToLookup); }
// // Lazily parse the method signature, and construct the call converter data // private void EnsureCallConversionInfoLoaded() { if (_signatureParsed) { return; } lock (this) { // Check if race was won by another thread and the signature got parsed if (_signatureParsed) { return; } TypeSystemContext context = TypeSystemContextFactory.Create(); { Instantiation typeInstantiation = Instantiation.Empty; Instantiation methodInstantiation = Instantiation.Empty; if (_typeArgs != null && _typeArgs.Length > 0) { typeInstantiation = context.ResolveRuntimeTypeHandles(_typeArgs); } if (_methodArgs != null && _methodArgs.Length > 0) { methodInstantiation = context.ResolveRuntimeTypeHandles(_methodArgs); } bool hasThis; TypeDesc[] parameters; bool[] paramsByRefForced; if (!TypeLoaderEnvironment.Instance.GetCallingConverterDataFromMethodSignature(context, _methodSignature, typeInstantiation, methodInstantiation, out hasThis, out parameters, out paramsByRefForced)) { Debug.Assert(false); Environment.FailFast("Failed to get type handles for parameters in method signature"); } Debug.Assert(parameters != null && parameters.Length >= 1); bool[] byRefParameters = new bool[parameters.Length]; RuntimeTypeHandle[] parameterHandles = new RuntimeTypeHandle[parameters.Length]; for (int j = 0; j < parameters.Length; j++) { ByRefType parameterAsByRefType = parameters[j] as ByRefType; if (parameterAsByRefType != null) { parameterAsByRefType.ParameterType.RetrieveRuntimeTypeHandleIfPossible(); parameterHandles[j] = parameterAsByRefType.ParameterType.RuntimeTypeHandle; byRefParameters[j] = true; } else { parameters[j].RetrieveRuntimeTypeHandleIfPossible(); parameterHandles[j] = parameters[j].RuntimeTypeHandle; byRefParameters[j] = false; } Debug.Assert(!parameterHandles[j].IsNull()); } // Build thunk data TypeHandle thReturnType = new TypeHandle(CallConverterThunk.GetByRefIndicatorAtIndex(0, byRefParameters), parameterHandles[0]); TypeHandle[] thParameters = null; if (parameters.Length > 1) { thParameters = new TypeHandle[parameters.Length - 1]; for (int i = 1; i < parameters.Length; i++) { thParameters[i - 1] = new TypeHandle(CallConverterThunk.GetByRefIndicatorAtIndex(i, byRefParameters), parameterHandles[i]); } } _argIteratorData = new ArgIteratorData(hasThis, false, thParameters, thReturnType); // StandardToStandard thunks don't actually need any parameters to change their ABI // so don't force any params to be adjusted if (!StandardToStandardThunk) { _paramsByRefForced = paramsByRefForced; } } TypeSystemContextFactory.Recycle(context); _signatureParsed = 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); }
private bool ResolveGenericVirtualMethodTarget(RuntimeTypeHandle targetTypeHandle, RuntimeTypeHandle declaringTypeHandle, RuntimeTypeHandle[] genericArguments, MethodNameAndSignature callingMethodNameAndSignature, out IntPtr methodPointer, out IntPtr dictionaryPointer) { if (IsPregeneratedOrTemplateRuntimeTypeHandle(targetTypeHandle)) { // If the target type isn't dynamic, or at least is template type generated, the static lookup logic is what we want. return(ResolveGenericVirtualMethodTarget_Static(targetTypeHandle, declaringTypeHandle, genericArguments, callingMethodNameAndSignature, out methodPointer, out dictionaryPointer)); } else { #if SUPPORTS_NATIVE_METADATA_TYPE_LOADING methodPointer = IntPtr.Zero; dictionaryPointer = IntPtr.Zero; TypeSystemContext context = TypeSystemContextFactory.Create(); DefType targetType = (DefType)context.ResolveRuntimeTypeHandle(targetTypeHandle); // Method being called... MethodDesc targetVirtualMethod = ResolveTypeHandleAndMethodNameAndSigToVirtualMethodDesc(context, declaringTypeHandle, callingMethodNameAndSignature); if (targetVirtualMethod == null) { // If we can't find the method in the type system, it must only be present in the static environment. Search there instead. TypeSystemContextFactory.Recycle(context); return(ResolveGenericVirtualMethodTarget_Static(targetTypeHandle, declaringTypeHandle, genericArguments, callingMethodNameAndSignature, out methodPointer, out dictionaryPointer)); } MethodDesc dispatchMethod = targetType.FindVirtualFunctionTargetMethodOnObjectType(targetVirtualMethod); if (dispatchMethod == null) { return(false); } Instantiation targetMethodInstantiation = context.ResolveRuntimeTypeHandles(genericArguments); MethodDesc instantiatedDispatchMethod = dispatchMethod.Context.ResolveGenericMethodInstantiation(dispatchMethod.OwningType.IsValueType /* get the unboxing stub */, dispatchMethod.OwningType.GetClosestDefType(), dispatchMethod.NameAndSignature, targetMethodInstantiation, IntPtr.Zero, false); GenericDictionaryCell cell = GenericDictionaryCell.CreateMethodCell(instantiatedDispatchMethod, false); 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(); TypeBuilder.ResolveSingleCell(cell, out methodPointer); } TypeSystemContextFactory.Recycle(context); return(true); #else methodPointer = IntPtr.Zero; dictionaryPointer = IntPtr.Zero; Environment.FailFast("GVM Resolution for non template or pregenerated type"); return(false); #endif } }