public static void RegisterDebugDataForMethod(TypeBuilder typeBuilder, InstantiatedMethod method) { NativePrimitiveEncoder encoder = new NativePrimitiveEncoder(); encoder.Init(); byte sharedMethodFlags = 0; sharedMethodFlags |= (byte)(method.OwningType.IsGeneric() ? SharedMethodFlags.HasDeclaringTypeHandle : 0); SerializeDataBlobTypeAndFlags(ref encoder, SerializedDataBlobKind.SharedMethod, sharedMethodFlags); encoder.WriteUnsignedLong((ulong)method.RuntimeMethodDictionary.ToInt64()); encoder.WriteUnsigned((uint)method.Instantiation.Length); foreach (var instParam in method.Instantiation) { encoder.WriteUnsignedLong((ulong)typeBuilder.GetRuntimeTypeHandle(instParam).ToIntPtr().ToInt64()); } if (method.OwningType.IsGeneric()) { encoder.WriteUnsignedLong((ulong)typeBuilder.GetRuntimeTypeHandle(method.OwningType).ToIntPtr().ToInt64()); } Instance.ThreadSafeWriteBytes(encoder.GetBytes()); }
internal HandleBasedGenericMethodLookup(InstantiatedMethod methodToLookup) : base(methodToLookup) { Debug.Assert(methodToLookup != null); _declaringType = _methodToLookup.OwningType.RuntimeTypeHandle; _nameAndSignature = _methodToLookup.NameAndSignature; // _genericMethodArgumentHandles not initialized here to avoid allocation of a new array (and it's not used if we initialize _typeToLookup). }
internal override bool MatchParsedEntry(ref NativeParser entryParser, ref ExternalReferencesTable externalReferencesLookup, IntPtr moduleHandle) { // // Entries read from the hashtable are loaded as GenericMethodDescs, 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 GenericMethodDesc, but still need to look it up in case the // method dictionary statically really exists // TypeSystemContext context = _methodToLookup.Context; RuntimeTypeHandle parsedDeclaringTypeHandle = externalReferencesLookup.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned()); // Hash table names / sigs are indirected through to the native layout info MethodNameAndSignature nameAndSignature; if (!TypeLoaderEnvironment.Instance.TryGetMethodNameAndSignatureFromNativeLayoutOffset(moduleHandle, entryParser.GetUnsigned(), out nameAndSignature)) { return(false); } RuntimeTypeHandle[] parsedArgsHandles = GetTypeSequence(ref externalReferencesLookup, ref entryParser); DefType parsedDeclaringType = context.ResolveRuntimeTypeHandle(parsedDeclaringTypeHandle) as DefType; Instantiation parsedArgs = context.ResolveRuntimeTypeHandles(parsedArgsHandles); InstantiatedMethod parsedGenericMethod = (InstantiatedMethod)context.ResolveGenericMethodInstantiation(false, parsedDeclaringType, nameAndSignature, parsedArgs, IntPtr.Zero, false); return(parsedGenericMethod == _methodToLookup); }
// // Returns the template method for a generic method instantiation // public static InstantiatedMethod TryGetGenericMethodTemplate(InstantiatedMethod concreteMethod, out NativeFormatModuleInfo nativeLayoutInfoModule, out uint nativeLayoutInfoToken) { // First, see if there is a specific canonical template InstantiatedMethod result = TryGetGenericMethodTemplate_Internal(concreteMethod, CanonicalFormKind.Specific, out nativeLayoutInfoModule, out nativeLayoutInfoToken); // If not found, see if there's a universal canonical template result ??= TryGetGenericMethodTemplate_Internal(concreteMethod, CanonicalFormKind.Universal, out nativeLayoutInfoModule, out nativeLayoutInfoToken); return(result); }
internal override bool MatchGenericMethodEntry(GenericMethodEntry entry) { TypeSystemContext context = _methodToLookup.Context; DefType parsedDeclaringType = context.ResolveRuntimeTypeHandle(entry._declaringTypeHandle) as DefType; Instantiation parsedArgs = context.ResolveRuntimeTypeHandles(entry._genericMethodArgumentHandles); InstantiatedMethod parsedGenericMethod = (InstantiatedMethod)context.ResolveGenericMethodInstantiation(false, parsedDeclaringType, entry._methodNameAndSignature, parsedArgs, IntPtr.Zero, false); return(parsedGenericMethod == _methodToLookup); }
private static InstantiatedMethod TryGetGenericMethodTemplate_Internal(InstantiatedMethod concreteMethod, CanonicalFormKind kind, out NativeFormatModuleInfo nativeLayoutInfoModule, out uint nativeLayoutInfoToken) { nativeLayoutInfoModule = null; nativeLayoutInfoToken = 0; var canonForm = concreteMethod.GetCanonMethodTarget(kind); var hashCode = canonForm.GetHashCode(); foreach (NativeFormatModuleInfo moduleInfo in ModuleList.EnumerateModules()) { NativeReader nativeLayoutReader = TypeLoaderEnvironment.GetNativeLayoutInfoReader(moduleInfo.Handle); if (nativeLayoutReader == null) { continue; } NativeHashtable genericMethodTemplatesHashtable = LoadHashtable(moduleInfo, ReflectionMapBlob.GenericMethodsTemplateMap, out _); if (genericMethodTemplatesHashtable.IsNull) { continue; } var context = new NativeLayoutInfoLoadContext { _typeSystemContext = concreteMethod.Context, _typeArgumentHandles = concreteMethod.OwningType.Instantiation, _methodArgumentHandles = concreteMethod.Instantiation, _module = moduleInfo }; var enumerator = genericMethodTemplatesHashtable.Lookup(hashCode); NativeParser entryParser; while (!(entryParser = enumerator.GetNext()).IsNull) { var methodSignatureParser = new NativeParser(nativeLayoutReader, entryParser.GetUnsigned()); // Get the unified generic method holder and convert it to its canonical form var candidateTemplate = (InstantiatedMethod)context.GetMethod(ref methodSignatureParser); Debug.Assert(candidateTemplate.Instantiation.Length > 0); if (canonForm == candidateTemplate.GetCanonMethodTarget(kind)) { TypeLoaderLogger.WriteLine("Found template for generic method " + concreteMethod.ToString() + ": " + candidateTemplate.ToString()); nativeLayoutInfoModule = moduleInfo; nativeLayoutInfoToken = entryParser.GetUnsigned(); if (nativeLayoutInfoToken == BadTokenFixupValue) { // TODO: once multifile gets fixed up, make this throw a BadImageFormatException TypeLoaderLogger.WriteLine("ERROR: template not fixed up, skipping"); continue; } Debug.Assert( (kind != CanonicalFormKind.Universal) || (kind == CanonicalFormKind.Universal && candidateTemplate == candidateTemplate.GetCanonMethodTarget(kind))); return(candidateTemplate); } } } TypeLoaderLogger.WriteLine("ERROR: Cannot find a suitable template for generic method " + concreteMethod.ToString()); return(null); }
// 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); }
internal MethodDescBasedGenericMethodLookup(InstantiatedMethod methodToLookup) { _methodToLookup = methodToLookup; }
public string Visit(IMethod method, OutputSettings settings) { StringBuilder result = new StringBuilder(); result.Append(settings.EmitModifiers(base.GetString(method.Modifiers))); if (settings.IncludeReturnType && !settings.ReturnTypesLast && !method.IsConstructor && !method.IsFinalizer) { result.Append(GetString(method.ReturnType, settings)); result.Append(settings.Markup(" ")); } if (!settings.IncludeReturnType && settings.UseFullName) { result.Append(GetString(method.DeclaringType, OutputFlags.UseFullName)); result.Append(settings.Markup(".")); } AppendExplicitInterfaces(result, method, settings); if (method.IsConstructor) { result.Append(settings.EmitName(method, Format(FilterName(method.DeclaringType.Name)))); } else if (method.IsFinalizer) { result.Append(settings.EmitName(method, settings.Markup("~") + Format(FilterName(method.DeclaringType.Name)))); } else { result.Append(settings.EmitName(method, Format(FilterName(method.Name)))); } //this is only ever used if GeneralizeGenerics is true DomMethod.GenericMethodInstanceResolver resolver = null; if (settings.GeneralizeGenerics) { resolver = new DomMethod.GenericMethodInstanceResolver(); } if (settings.IncludeGenerics) { if (method.TypeParameters.Count > 0) { result.Append(settings.Markup("<")); InstantiatedMethod instantiatedMethod = method as InstantiatedMethod; for (int i = 0; i < method.TypeParameters.Count; i++) { if (i > 0) { result.Append(settings.Markup(settings.HideGenericParameterNames ? "," : ", ")); } if (!settings.HideGenericParameterNames) { if (instantiatedMethod != null) { result.Append(this.GetString(instantiatedMethod.GenericParameters[i], settings)); } else { if (settings.GeneralizeGenerics) { string generalizedName = "$M" + i; result.Append(generalizedName); var t = new DomReturnType(); t.Name = generalizedName; resolver.Add(method.DeclaringType.SourceProjectDom, new DomReturnType(method.TypeParameters[i].Name), t); } else { result.Append(NetToCSharpTypeName(method.TypeParameters[i].Name)); } } } } result.Append(settings.Markup(">")); } } if (settings.IncludeParameters) { CSharpFormattingPolicy policy = GetPolicy(settings); if (policy.BeforeMethodCallParentheses) { result.Append(settings.Markup(" ")); } result.Append(settings.Markup("(")); bool first = !settings.StaticUsage; if (method.Parameters != null) { foreach (IParameter parameter in method.Parameters) { if (settings.HideExtensionsParameter && method.IsExtension && first) { continue; } if (method.IsExtension && first) { result.Append(settings.Markup("this ")); } if (!first) { result.Append(settings.Markup(", ")); } if (settings.GeneralizeGenerics) { AppendParameter(settings, result, (IParameter)resolver.Visit(parameter, method)); } else { AppendParameter(settings, result, parameter); } first = false; } } result.Append(settings.Markup(")")); } OutputConstraints(result, settings, method.TypeParameters); if (settings.IncludeReturnType && settings.ReturnTypesLast && !method.IsConstructor && !method.IsFinalizer) { result.Append(settings.Markup(" : ")); result.Append(GetString(method.ReturnType, settings)); } return(result.ToString()); }
public JitGenericMethodDictionaryNode(InstantiatedMethod method) { Method = method; }
public string Visit(IMethod method, OutputSettings settings) { StringBuilder result = new StringBuilder(); result.Append(settings.EmitModifiers(base.GetString(method.Modifiers))); if (settings.IncludeReturnType && !method.IsConstructor && !method.IsFinalizer) { result.Append(GetString(method.ReturnType, settings)); result.Append(settings.Markup(" ")); } if (!settings.IncludeReturnType && settings.UseFullName) { result.Append(GetString(method.DeclaringType, OutputFlags.UseFullName)); result.Append(settings.Markup(".")); } AppendExplicitInterfaces(result, method, settings); if (method.IsConstructor) { result.Append(settings.EmitName(method, Format(method.DeclaringType.Name))); } else if (method.IsFinalizer) { result.Append(settings.EmitName(method, settings.Markup("~") + Format(method.DeclaringType.Name))); } else { result.Append(settings.EmitName(method, Format(method.Name))); } if (settings.IncludeGenerics) { if (method.TypeParameters.Count > 0) { result.Append(settings.Markup("<")); InstantiatedMethod instantiatedMethod = method as InstantiatedMethod; for (int i = 0; i < method.TypeParameters.Count; i++) { if (i > 0) { result.Append(settings.Markup(settings.HideGenericParameterNames ? "," : ", ")); } if (!settings.HideGenericParameterNames) { if (instantiatedMethod != null) { result.Append(this.GetString(instantiatedMethod.GenericParameters[i], settings)); } else { result.Append(NetToCSharpTypeName(method.TypeParameters[i].Name)); } } } result.Append(settings.Markup(">")); } } if (settings.IncludeParameters) { CSharpFormattingPolicy policy = GetPolicy(settings); if (policy.BeforeMethodCallParentheses) { result.Append(settings.Markup(" ")); } result.Append(settings.Markup("(")); bool first = true; if (method.Parameters != null) { foreach (IParameter parameter in method.Parameters) { if (settings.HideExtensionsParameter && method.IsExtension && parameter == method.Parameters[0]) { continue; } if (!first) { result.Append(settings.Markup(", ")); } AppendParameter(settings, result, parameter); first = false; } } result.Append(settings.Markup(")")); } return(result.ToString()); }
public static bool CanShareNormalGenericCode(this InstantiatedMethod method) { return(method != method.GetCanonMethodTarget(CanonicalFormKind.Specific)); }