public bool CanInstantiationsShareCode(RuntimeTypeHandle[] genericArgHandles1, RuntimeTypeHandle[] genericArgHandles2, CanonicalFormKind kind) { if (genericArgHandles1.Length != genericArgHandles2.Length) return false; bool match = true; TypeSystemContext context = TypeSystemContextFactory.Create(); for (int i = 0; i < genericArgHandles1.Length; i++) { TypeDesc genericArg1 = context.ResolveRuntimeTypeHandle(genericArgHandles1[i]); TypeDesc genericArg2 = context.ResolveRuntimeTypeHandle(genericArgHandles2[i]); if (context.ConvertToCanon(genericArg1, kind) != context.ConvertToCanon(genericArg2, kind)) { match = false; break; } } TypeSystemContextFactory.Recycle(context); return match; }
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); }
/// <summary> /// This thunk is used to lazily resolve Finalizer calls /// </summary> /// <param name="obj">Object to be finalized</param> private static void FinalizeThunk(object obj) { RuntimeTypeHandle rthType = RuntimeAugments.GetRuntimeTypeHandleFromObjectReference(obj); TypeSystemContext context = TypeSystemContextFactory.Create(); TypeDesc type = context.ResolveRuntimeTypeHandle(rthType); MethodDesc finalizer = type.GetFinalizer(); IntPtr fnPtrFinalizer; if (!TryGetVTableCallableAddress(finalizer, out fnPtrFinalizer)) { Environment.FailFast("Method address lookup failed for: " + finalizer.ToString()); } TypeSystemContextFactory.Recycle(context); unsafe { rthType.ToEETypePtr()->FinalizerCode = fnPtrFinalizer; } // Call the finalizer directly. No need to play tricks with tail calling, as this is rare enough, it shouldn't happen much // Here we take advantage of the detail that the calling convention abi for a static function // that returns no values, and takes a single object parameter matches that of a // instance function that takes no parameters Intrinsics.Call(fnPtrFinalizer, obj); }
/// <summary> /// Attempt a virtual dispatch on a given instanceType based on the method found via a metadata token /// </summary> private static bool TryDispatchMethodOnTarget_Inner(NativeFormatModuleInfo module, int metadataToken, RuntimeTypeHandle targetInstanceType, out IntPtr methodAddress) { #if SUPPORTS_NATIVE_METADATA_TYPE_LOADING TypeSystemContext context = TypeSystemContextFactory.Create(); NativeFormatMetadataUnit metadataUnit = context.ResolveMetadataUnit(module); MethodDesc targetMethod = metadataUnit.GetMethod(metadataToken.AsHandle(), null); TypeDesc instanceType = context.ResolveRuntimeTypeHandle(targetInstanceType); MethodDesc realTargetMethod = targetMethod; // For non-interface methods we support the target method not being the exact target. (This allows // a canonical method to be passed in and work for any generic type instantiation.) if (!targetMethod.OwningType.IsInterface) { realTargetMethod = instanceType.FindMethodOnTypeWithMatchingTypicalMethod(targetMethod); } bool success = LazyVTableResolver.TryDispatchMethodOnTarget(instanceType, realTargetMethod, out methodAddress); TypeSystemContextFactory.Recycle(context); return(success); #else methodAddress = IntPtr.Zero; return(false); #endif }
public bool TryComputeHasInstantiationDeterminedSize(RuntimeTypeHandle typeHandle, TypeSystemContext context, out bool hasInstantiationDeterminedSize) { Debug.Assert(RuntimeAugments.IsGenericType(typeHandle) || RuntimeAugments.IsGenericTypeDefinition(typeHandle)); DefType type = (DefType)context.ResolveRuntimeTypeHandle(typeHandle); return TryComputeHasInstantiationDeterminedSize(type, out hasInstantiationDeterminedSize); }
internal TypeDesc GetExternalType(uint index) { InitializeExternalReferencesLookup(); RuntimeTypeHandle rtth = _externalReferencesLookup.GetRuntimeTypeHandleFromIndex(index); return(_typeSystemContext.ResolveRuntimeTypeHandle(rtth)); }
/// <summary> /// Resolve a dispatch on an interface EEType/slot index pair to a function pointer /// </summary> private bool TryResolveTypeSlotDispatch_Inner(IntPtr targetTypeAsIntPtr, IntPtr interfaceTypeAsIntPtr, ushort slot, out IntPtr methodAddress) { methodAddress = IntPtr.Zero; #if SUPPORTS_NATIVE_METADATA_TYPE_LOADING TypeSystemContext context = TypeSystemContextFactory.Create(); TypeDesc targetType; TypeDesc interfaceType; unsafe { targetType = context.ResolveRuntimeTypeHandle(((EEType *)targetTypeAsIntPtr.ToPointer())->ToRuntimeTypeHandle()); interfaceType = context.ResolveRuntimeTypeHandle(((EEType *)interfaceTypeAsIntPtr.ToPointer())->ToRuntimeTypeHandle()); } if (!(interfaceType.GetTypeDefinition() is MetadataType)) { // If the interface open type is not a metadata type, this must be an interface not known in the metadata world. // Use the redhawk resolver for this directly. TypeDesc pregeneratedType = LazyVTableResolver.GetMostDerivedPregeneratedOrTemplateLoadedType(targetType); pregeneratedType.RetrieveRuntimeTypeHandleIfPossible(); interfaceType.RetrieveRuntimeTypeHandleIfPossible(); methodAddress = RuntimeAugments.ResolveDispatchOnType(pregeneratedType.RuntimeTypeHandle, interfaceType.RuntimeTypeHandle, slot); } else { MethodDesc interfaceMethod; if (!LazyVTableResolver.TryGetMethodFromInterfaceSlot(interfaceType, slot, out interfaceMethod)) { return(false); } if (!LazyVTableResolver.TryDispatchMethodOnTarget(targetType, interfaceMethod, out methodAddress)) { return(false); } } TypeSystemContextFactory.Recycle(context); return(true); #else return(false); #endif }
public int GetCanonicalHashCode(RuntimeTypeHandle typeHandle, CanonicalFormKind kind) { TypeSystemContext context = TypeSystemContextFactory.Create(); TypeDesc type = context.ResolveRuntimeTypeHandle(typeHandle); int hashCode = type.ConvertToCanonForm(kind).GetHashCode(); TypeSystemContextFactory.Recycle(context); return hashCode; }
internal override bool MatchGenericTypeEntry(GenericTypeEntry entry) { TypeSystemContext context = _typeToLookup.Context; DefType parsedTypeDefinition = (DefType)context.ResolveRuntimeTypeHandle(entry._genericTypeDefinitionHandle); Instantiation parsedArgs = context.ResolveRuntimeTypeHandles(entry._genericTypeArgumentHandles); DefType parsedGenericType = context.ResolveGenericInstantiation(parsedTypeDefinition, parsedArgs); return(parsedGenericType == _typeToLookup); }
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); }
public static MethodDesc ToMethodDesc(this RuntimeMethodHandle rmh, TypeSystemContext typeSystemContext) { RuntimeTypeHandle declaringTypeHandle; MethodNameAndSignature nameAndSignature; RuntimeTypeHandle[] genericMethodArgs; if (!TypeLoaderEnvironment.Instance.TryGetRuntimeMethodHandleComponents(rmh, out declaringTypeHandle, out nameAndSignature, out genericMethodArgs)) { return(null); } QMethodDefinition methodHandle; if (!TypeLoaderEnvironment.Instance.TryGetMetadataForTypeMethodNameAndSignature(declaringTypeHandle, nameAndSignature, out methodHandle)) { return(null); } TypeDesc declaringType = typeSystemContext.ResolveRuntimeTypeHandle(declaringTypeHandle); TypeDesc declaringTypeDefinition = declaringType.GetTypeDefinition(); MethodDesc typicalMethod = null; if (methodHandle.IsNativeFormatMetadataBased) { var nativeFormatType = (NativeFormatType)declaringTypeDefinition; typicalMethod = nativeFormatType.MetadataUnit.GetMethod(methodHandle.NativeFormatHandle, nativeFormatType); } else if (methodHandle.IsEcmaFormatMetadataBased) { var ecmaFormatType = (EcmaType)declaringTypeDefinition; typicalMethod = ecmaFormatType.EcmaModule.GetMethod(methodHandle.EcmaFormatHandle); } Debug.Assert(typicalMethod != null); MethodDesc methodOnInstantiatedType = typicalMethod; if (declaringType != declaringTypeDefinition) { methodOnInstantiatedType = typeSystemContext.GetMethodForInstantiatedType(typicalMethod, (InstantiatedType)declaringType); } MethodDesc instantiatedMethod = methodOnInstantiatedType; if (genericMethodArgs != null) { Debug.Assert(genericMethodArgs.Length > 0); Instantiation genericMethodInstantiation = typeSystemContext.ResolveRuntimeTypeHandles(genericMethodArgs); typeSystemContext.GetInstantiatedMethod(methodOnInstantiatedType, genericMethodInstantiation); } return(instantiatedMethod); }
private bool ResolveInterfaceGenericVirtualMethodSlot(RuntimeTypeHandle targetTypeHandle, ref RuntimeTypeHandle declaringType, ref MethodNameAndSignature methodNameAndSignature) { 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(ResolveInterfaceGenericVirtualMethodSlot_Static(targetTypeHandle, ref declaringType, ref methodNameAndSignature)); } else { #if SUPPORTS_NATIVE_METADATA_TYPE_LOADING TypeSystemContext context = TypeSystemContextFactory.Create(); DefType targetType = (DefType)context.ResolveRuntimeTypeHandle(targetTypeHandle); // Method being called... MethodDesc targetVirtualMethod = ResolveTypeHandleAndMethodNameAndSigToVirtualMethodDesc(context, declaringType, methodNameAndSignature); 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(ResolveInterfaceGenericVirtualMethodSlot_Static(targetTypeHandle, ref declaringType, ref methodNameAndSignature)); } TypeDesc instanceDefTypeToExamine; MethodDesc newlyFoundVirtualMethod = LazyVTableResolver.ResolveInterfaceMethodToVirtualMethod(targetType, out instanceDefTypeToExamine, targetVirtualMethod); targetVirtualMethod = newlyFoundVirtualMethod; // The pregenerated base type must be the one that implements the interface method // Call into Redhawk to deal with this. if ((newlyFoundVirtualMethod == null) && (instanceDefTypeToExamine != null)) { TypeSystemContextFactory.Recycle(context); // If we can't find the method in the type system, the overload must be defined in the static environment. Search there instead. return(ResolveInterfaceGenericVirtualMethodSlot_Static(instanceDefTypeToExamine.GetRuntimeTypeHandle(), ref declaringType, ref methodNameAndSignature)); } declaringType = targetVirtualMethod.OwningType.GetRuntimeTypeHandle(); methodNameAndSignature = targetVirtualMethod.NameAndSignature; TypeSystemContextFactory.Recycle(context); return(true); #else Environment.FailFast("GVM Resolution for non template or pregenerated type"); return(false); #endif } }
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); }
public MethodDesc ResolveTypeHandleAndMethodNameAndSigToVirtualMethodDesc(TypeSystemContext context, RuntimeTypeHandle declaringTypeHandle, MethodNameAndSignature methodNameAndSignature) { TypeDesc declaringType = context.ResolveRuntimeTypeHandle(declaringTypeHandle); MethodDesc targetVirtualMethod = null; foreach (MethodDesc m in declaringType.GetAllMethods()) { if (!m.IsVirtual) { continue; } if (m.NameAndSignature.Equals(methodNameAndSignature)) { targetVirtualMethod = m; } } return(targetVirtualMethod); }
/// <summary> /// Try to figure out field access information based on type metadata for native format types. /// </summary> /// <param name="metadataReader">Metadata reader for the declaring type</param> /// <param name="declaringTypeHandle">Declaring type for the method</param> /// <param name="fieldHandle">Field handle</param> /// <param name="canonFormKind">Canonical form to use</param> /// <param name="fieldAccessMetadata">Output - metadata information for field accessor construction</param> /// <returns>true when found, false otherwise</returns> private static bool TryGetFieldAccessMetadataFromNativeFormatMetadata( MetadataReader metadataReader, RuntimeTypeHandle declaringTypeHandle, FieldHandle fieldHandle, TypeSystemContext context, ref FieldAccessMetadata fieldAccessMetadata) { Field field = metadataReader.GetField(fieldHandle); string fieldName = metadataReader.GetString(field.Name); TypeDesc declaringType = context.ResolveRuntimeTypeHandle(declaringTypeHandle); #if SUPPORTS_NATIVE_METADATA_TYPE_LOADING if (declaringType is MetadataType) { return(TryGetFieldAccessMetadataForNativeFormatType(declaringType, fieldName, ref fieldAccessMetadata)); } #endif return(false); }
/// <summary> /// This function is called from the lazy vtable resolver thunks via the UniversalTransitionThunk to compute /// the correct resolution of a virtual dispatch. /// </summary> /// <param name="callerTransitionBlockParam">pointer to the arguments of the called function</param> /// <param name="eeTypePointerOffsetAsIntPtr">eeTypePointerOffsetAsIntPtr is the offset from the start of the EEType to the vtable slot</param> /// <returns>function pointer of correct override of virtual function</returns> unsafe private static IntPtr VTableResolveThunk(IntPtr callerTransitionBlockParam, IntPtr eeTypePointerOffsetAsIntPtr) { int eeTypePointerOffset = (int)eeTypePointerOffsetAsIntPtr; int vtableSlotIndex = EETypeVTableOffsetToSlotIndex(eeTypePointerOffset); Debug.Assert(eeTypePointerOffset == SlotIndexToEETypeVTableOffset(vtableSlotIndex)); // Assert that the round trip through the slot calculations is good EEType **thisPointer = *((EEType ***)(((byte *)callerTransitionBlockParam) + ArgIterator.GetThisOffset())); EEType * eeType = *thisPointer; RuntimeTypeHandle rth = eeType->ToRuntimeTypeHandle(); TypeSystemContext context = TypeSystemContextFactory.Create(); TypeDesc type = context.ResolveRuntimeTypeHandle(rth); IntPtr functionPointer = ResolveVirtualVTableFunction(type, vtableSlotIndex); eeType->GetVTableStartAddress()[vtableSlotIndex] = functionPointer; TypeSystemContextFactory.Recycle(context); return(functionPointer); }
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 } }
// 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); }