/// <summary> /// For a shared (canonical) instance method on a generic valuetype, gets a method that can be used to call the /// method given a boxed version of the generic valuetype as 'this' pointer. /// </summary> public MethodDesc GetSpecialUnboxingThunk(MethodDesc targetMethod, ModuleDesc ownerModuleOfThunk) { Debug.Assert(targetMethod.IsSharedByGenericInstantiations); Debug.Assert(!targetMethod.Signature.IsStatic); Debug.Assert(!targetMethod.HasInstantiation); TypeDesc owningType = targetMethod.OwningType; Debug.Assert(owningType.IsValueType); var owningTypeDefinition = (MetadataType)owningType.GetTypeDefinition(); // Get a reference type that has the same layout as the boxed valuetype. var typeKey = new BoxedValuetypeHashtableKey(owningTypeDefinition, ownerModuleOfThunk); BoxedValueType boxedTypeDefinition = _boxedValuetypeHashtable.GetOrCreateValue(typeKey); // Get a method on the reference type with the same signature as the target method (but different // calling convention, since 'this' will be a reference type). var targetMethodDefinition = targetMethod.GetTypicalMethodDefinition(); var methodKey = new UnboxingThunkHashtableKey(targetMethodDefinition, boxedTypeDefinition); GenericUnboxingThunk thunkDefinition = _unboxingThunkHashtable.GetOrCreateValue(methodKey); // Find the thunk on the instantiated version of the reference type. Debug.Assert(owningType != owningTypeDefinition); InstantiatedType boxedType = boxedTypeDefinition.MakeInstantiatedType(owningType.Instantiation); MethodDesc thunk = GetMethodForInstantiatedType(thunkDefinition, boxedType); Debug.Assert(!thunk.HasInstantiation); return(thunk); }
public MethodDesc GetUnboxingThunk(MethodDesc targetMethod, ModuleDesc ownerModuleOfThunk) { TypeDesc owningType = targetMethod.OwningType; Debug.Assert(owningType.IsValueType); var owningTypeDefinition = (MetadataType)owningType.GetTypeDefinition(); // Get a reference type that has the same layout as the boxed valuetype. var typeKey = new BoxedValuetypeHashtableKey(owningTypeDefinition, ownerModuleOfThunk); BoxedValueType boxedTypeDefinition = _boxedValuetypeHashtable.GetOrCreateValue(typeKey); // Get a method on the reference type with the same signature as the target method (but different // calling convention, since 'this' will be a reference type). var targetMethodDefinition = targetMethod.GetTypicalMethodDefinition(); var methodKey = new UnboxingThunkHashtableKey(targetMethodDefinition, boxedTypeDefinition); UnboxingThunk thunkDefinition = _nonGenericUnboxingThunkHashtable.GetOrCreateValue(methodKey); // Find the thunk on the instantiated version of the reference type. if (owningType != owningTypeDefinition) { InstantiatedType boxedType = boxedTypeDefinition.MakeInstantiatedType(owningType.Instantiation); MethodDesc thunk = GetMethodForInstantiatedType(thunkDefinition, boxedType); //TODO: this might be triggered by a struct that implements an interface with a generic method Debug.Assert(!thunk.HasInstantiation); return(thunk); } else { //TODO: this might be triggered by a struct that implements an interface with a generic method Debug.Assert(!thunkDefinition.HasInstantiation); return(thunkDefinition); } }