internal DispatchCellInfo ConvertDispatchCellInfo(IntPtr module, DispatchCellInfo cellInfo) { using (LockHolder.Hold(_typeLoaderLock)) { return ConvertDispatchCellInfo_Inner( module, cellInfo); } }
internal DispatchCellInfo ConvertDispatchCellInfo(NativeFormatModuleInfo module, DispatchCellInfo cellInfo) { using (LockHolder.Hold(_typeLoaderLock)) { return ConvertDispatchCellInfo_Inner( module, cellInfo); } }
/// <summary> /// Attempt to convert the dispatch cell to a metadata token to a more efficient vtable dispatch or interface/slot dispatch. /// Failure to convert is not a correctness issue. We also support performing a dispatch based on metadata token alone. /// </summary> private static DispatchCellInfo ConvertDispatchCellInfo_Inner(NativeFormatModuleInfo module, DispatchCellInfo cellInfo) { Debug.Assert(cellInfo.CellType == DispatchCellType.MetadataToken); TypeSystemContext context = TypeSystemContextFactory.Create(); MethodDesc targetMethod = context.ResolveMetadataUnit(module).GetMethod(cellInfo.MetadataToken.AsHandle(), null); Debug.Assert(!targetMethod.HasInstantiation); // At this time we do not support generic virtuals through the dispatch mechanism Debug.Assert(targetMethod.IsVirtual); if (targetMethod.OwningType.IsInterface) { if (!LazyVTableResolver.TryGetInterfaceSlotNumberFromMethod(targetMethod, out cellInfo.InterfaceSlot)) { // Unable to resolve interface method. Fail, by not mutating cellInfo return(cellInfo); } if (!targetMethod.OwningType.RetrieveRuntimeTypeHandleIfPossible()) { new TypeBuilder().BuildType(targetMethod.OwningType); } cellInfo.CellType = DispatchCellType.InterfaceAndSlot; cellInfo.InterfaceType = targetMethod.OwningType.RuntimeTypeHandle.ToIntPtr(); cellInfo.MetadataToken = 0; } else { // Virtual function case, attempt to resolve to a VTable slot offset. // If the offset is less than 4096 update the cellInfo #if DEBUG // The path of resolving a metadata token at dispatch time is relatively rare in practice. // Force it to occur in debug builds with much more regularity if ((s_ConvertDispatchCellInfoCounter % 16) == 0) { s_ConvertDispatchCellInfoCounter++; TypeSystemContextFactory.Recycle(context); return(cellInfo); } s_ConvertDispatchCellInfoCounter++; #endif int slotIndexOfMethod = LazyVTableResolver.VirtualMethodToSlotIndex(targetMethod); int vtableOffset = -1; if (slotIndexOfMethod >= 0) { vtableOffset = LazyVTableResolver.SlotIndexToEETypeVTableOffset(slotIndexOfMethod); } if ((vtableOffset < 4096) && (vtableOffset != -1)) { cellInfo.CellType = DispatchCellType.VTableOffset; cellInfo.VTableOffset = checked ((uint)vtableOffset); cellInfo.MetadataToken = 0; } // Otherwise, do nothing, and resolve with a metadata dispatch later } TypeSystemContextFactory.Recycle(context); return(cellInfo); }