/// <summary> /// Returns the result of canonicalizing this method over the given kind of Canon /// </summary> public override MethodDesc GetCanonMethodTarget(CanonicalFormKind kind) { InstantiatedMethod canonicalMethodResult = GetCachedCanonValue(kind); if (canonicalMethodResult == null) { bool instantiationChanged; Instantiation canonInstantiation = Context.ConvertInstantiationToCanonForm(Instantiation, kind, out instantiationChanged); MethodDesc openMethodOnCanonicalizedType = _methodDef.GetCanonMethodTarget(kind); if (instantiationChanged || (openMethodOnCanonicalizedType != _methodDef)) { canonicalMethodResult = Context.GetInstantiatedMethod(openMethodOnCanonicalizedType, canonInstantiation); } else { canonicalMethodResult = this; } // If the method instantiation is universal, we use a __UniversalCanon for all instantiation arguments for simplicity. // This is to not end up having method instantiations like Foo<__UniversalCanon>.Method<int> or Foo<__UniversalCanon>.Method<string> // or Foo<__UniversalCanon>.Method<__Canon> or Foo<int>.Method<__UniversalCanon> // It should just be Foo<__UniversalCanon>.Method<__UniversalCanon> if ((kind == CanonicalFormKind.Specific) && canonicalMethodResult.IsCanonicalMethod(CanonicalFormKind.Universal)) { canonicalMethodResult = (InstantiatedMethod)canonicalMethodResult.GetCanonMethodTarget(CanonicalFormKind.Universal); } SetCachedCanonValue(kind, canonicalMethodResult); } return(canonicalMethodResult); }
private void InitializeMethodInstantiation(Cts.MethodDesc entity, MethodInstantiation record) { Cts.InstantiatedMethod instantiation = (Cts.InstantiatedMethod)entity; record.Method = HandleQualifiedMethod(instantiation.GetMethodDefinition()); record.GenericTypeArguments.Capacity = instantiation.Instantiation.Length; foreach (Cts.TypeDesc typeArgument in instantiation.Instantiation) { record.GenericTypeArguments.Add(HandleType(typeArgument)); } }
void SetCachedCanonValue(CanonicalFormKind kind, InstantiatedMethod value) { switch(kind) { case CanonicalFormKind.Specific: Debug.Assert(_specificCanonCache == null || _specificCanonCache == value); _specificCanonCache = value; break; case CanonicalFormKind.Universal: Debug.Assert(_universalCanonCache == null || _universalCanonCache == value); _universalCanonCache = value; break; default: Debug.Fail("Invalid CanonicalFormKind: " + kind); break; } }
void SetCachedCanonValue(CanonicalFormKind kind, InstantiatedMethod value) { switch (kind) { case CanonicalFormKind.Specific: Debug.Assert(_specificCanonCache == null || _specificCanonCache == value); _specificCanonCache = value; break; case CanonicalFormKind.Universal: Debug.Assert(_universalCanonCache == null || _universalCanonCache == value); _universalCanonCache = value; break; default: Debug.Fail("Invalid CanonicalFormKind: " + kind); break; } }
/// <summary> /// Returns the result of canonicalizing this method over the given kind of Canon /// </summary> public override MethodDesc GetCanonMethodTarget(CanonicalFormKind kind) { InstantiatedMethod canonicalMethodResult = GetCachedCanonValue(kind); if (canonicalMethodResult != null) { return(canonicalMethodResult); } MethodDesc openMethodOnCanonicalizedType = _methodDef.GetCanonMethodTarget(kind); // TODO: We should avoid the array allocation if conversion to canon is not change (take hint from MethodDesc.InstantiateSignature) Instantiation newInstantiation = CanonUtilites.ConvertInstantiationToCanonForm(Context, Instantiation, kind); canonicalMethodResult = Context.GetInstantiatedMethod(openMethodOnCanonicalizedType, newInstantiation); SetCachedCanonValue(kind, canonicalMethodResult); return(GetCachedCanonValue(kind)); }
/// <summary> /// Returns the result of canonicalizing this method over the given kind of Canon /// </summary> public override MethodDesc GetCanonMethodTarget(CanonicalFormKind kind) { InstantiatedMethod canonicalMethodResult = GetCachedCanonValue(kind); if (canonicalMethodResult == null) { bool needsChange; Instantiation canonInstantiation = CanonUtilites.ConvertInstantiationToCanonForm(Instantiation, kind, out needsChange); if (needsChange) { MethodDesc openMethodOnCanonicalizedType = _methodDef.GetCanonMethodTarget(kind); canonicalMethodResult = Context.GetInstantiatedMethod(openMethodOnCanonicalizedType, canonInstantiation); } else { canonicalMethodResult = this; } SetCachedCanonValue(kind, canonicalMethodResult); } return(canonicalMethodResult); }
/// <summary> /// Returns the result of canonicalizing this method over the given kind of Canon /// </summary> public override MethodDesc GetCanonMethodTarget(CanonicalFormKind kind) { InstantiatedMethod canonicalMethodResult = GetCachedCanonValue(kind); if (canonicalMethodResult == null) { bool instantiationChanged; Instantiation canonInstantiation = Context.ConvertInstantiationToCanonForm(Instantiation, kind, out instantiationChanged); MethodDesc openMethodOnCanonicalizedType = _methodDef.GetCanonMethodTarget(kind); if (instantiationChanged || (openMethodOnCanonicalizedType != _methodDef)) { canonicalMethodResult = Context.GetInstantiatedMethod(openMethodOnCanonicalizedType, canonInstantiation); } else { canonicalMethodResult = this; } SetCachedCanonValue(kind, canonicalMethodResult); } return(canonicalMethodResult); }
private InstantiatedMethod TryGetGenericMethodTemplate_Internal(InstantiatedMethod concreteMethod, CanonicalFormKind kind, out IntPtr nativeLayoutInfoModule, out uint nativeLayoutInfoToken) { nativeLayoutInfoModule = default(IntPtr); nativeLayoutInfoToken = 0; var canonForm = concreteMethod.GetCanonMethodTarget(kind); var hashCode = canonForm.GetHashCode(); var loadedModulesCount = RuntimeAugments.GetLoadedModules(null); var loadedModuleHandles = new IntPtr[loadedModulesCount]; var loadedModules = RuntimeAugments.GetLoadedModules(loadedModuleHandles); Debug.Assert(loadedModulesCount == loadedModules); foreach (var moduleHandle in loadedModuleHandles) { NativeReader nativeLayoutReader = TypeLoaderEnvironment.Instance.GetNativeLayoutInfoReader(moduleHandle); if (nativeLayoutReader == null) continue; ExternalReferencesTable externalFixupsTable; NativeHashtable genericMethodTemplatesHashtable = LoadHashtable(moduleHandle, ReflectionMapBlob.GenericMethodsTemplateMap, out externalFixupsTable); if (genericMethodTemplatesHashtable.IsNull) continue; var context = new NativeLayoutInfoLoadContext { _typeSystemContext = concreteMethod.Context, _typeArgumentHandles = concreteMethod.OwningType.Instantiation, _methodArgumentHandles = concreteMethod.Instantiation, _moduleHandle = moduleHandle }; var enumerator = genericMethodTemplatesHashtable.Lookup(hashCode); NativeParser entryParser; while (!(entryParser = enumerator.GetNext()).IsNull) { var methodSignatureParser = new NativeParser(nativeLayoutReader, externalFixupsTable.GetRvaFromIndex(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 = moduleHandle; nativeLayoutInfoToken = (uint)externalFixupsTable.GetRvaFromIndex(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 && candidateTemplate != candidateTemplate.GetCanonMethodTarget(kind)) || (kind == CanonicalFormKind.Universal && candidateTemplate == candidateTemplate.GetCanonMethodTarget(kind))); return candidateTemplate; } } } TypeLoaderLogger.WriteLine("ERROR: Cannot find a suitable template for generic method " + concreteMethod.ToString()); return null; }
// // Returns the template method for a generic method instantation // public InstantiatedMethod TryGetGenericMethodTemplate(InstantiatedMethod concreteMethod, out IntPtr 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 if (result == null) result = TryGetGenericMethodTemplate_Internal(concreteMethod, CanonicalFormKind.Universal, out nativeLayoutInfoModule, out nativeLayoutInfoToken); return result; }
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); Instance.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()); }