private unsafe static IntPtr GVMLookupForSlotWorker(RuntimeTypeHandle type, RuntimeTypeHandle declaringType, RuntimeTypeHandle[] genericArguments, MethodNameAndSignature methodNameAndSignature) { bool slotChanged = false; IntPtr resolution = IntPtr.Zero; // Otherwise, walk parent hierarchy attempting to resolve EETypePtr eetype = type.ToEETypePtr(); IntPtr functionPointer = IntPtr.Zero; IntPtr genericDictionary = IntPtr.Zero; while (!eetype.IsNull) { RuntimeTypeHandle handle = new RuntimeTypeHandle(eetype); string methodName = methodNameAndSignature.Name; IntPtr methodSignature = methodNameAndSignature.Signature; if (RuntimeAugments.Callbacks.TryGetGenericVirtualTargetForTypeAndSlot(handle, ref declaringType, ref genericArguments, ref methodName, ref methodSignature, out functionPointer, out genericDictionary, out slotChanged)) { methodNameAndSignature = new MethodNameAndSignature(methodName, methodSignature); if (!slotChanged) { resolution = FunctionPointerOps.GetGenericMethodFunctionPointer(functionPointer, genericDictionary); } break; } eetype = eetype.BaseType; } // If the current slot to examine has changed, restart the lookup. // This happens when there is an interface call. if (slotChanged) { return(GVMLookupForSlotWorker(type, declaringType, genericArguments, methodNameAndSignature)); } if (resolution == IntPtr.Zero) { Environment.FailFast("GVM resolution failure"); } return(resolution); }
private static unsafe IntPtr GVMLookupForSlotWorker(RuntimeTypeHandle type, RuntimeTypeHandle declaringType, RuntimeTypeHandle[] genericArguments, MethodNameAndSignature methodNameAndSignature) { bool slotChanged = false; IntPtr resolution = IntPtr.Zero; IntPtr functionPointer = IntPtr.Zero; IntPtr genericDictionary = IntPtr.Zero; bool lookForDefaultImplementations = false; again: // Walk parent hierarchy attempting to resolve EETypePtr eeType = type.ToEETypePtr(); while (!eeType.IsNull) { RuntimeTypeHandle handle = new RuntimeTypeHandle(eeType); string methodName = methodNameAndSignature.Name; RuntimeSignature methodSignature = methodNameAndSignature.Signature; if (RuntimeAugments.TypeLoaderCallbacks.TryGetGenericVirtualTargetForTypeAndSlot(handle, ref declaringType, genericArguments, ref methodName, ref methodSignature, lookForDefaultImplementations, out functionPointer, out genericDictionary, out slotChanged)) { methodNameAndSignature = new MethodNameAndSignature(methodName, methodSignature); if (!slotChanged) { resolution = FunctionPointerOps.GetGenericMethodFunctionPointer(functionPointer, genericDictionary); } break; } eeType = eeType.BaseType; } // If the current slot to examine has changed, restart the lookup. // This happens when there is an interface call. if (slotChanged) { return(GVMLookupForSlotWorker(type, declaringType, genericArguments, methodNameAndSignature)); } if (resolution == IntPtr.Zero && !lookForDefaultImplementations && declaringType.ToEETypePtr().IsInterface) { lookForDefaultImplementations = true; goto again; } if (resolution == IntPtr.Zero) { var sb = new System.Text.StringBuilder(); sb.AppendLine("Generic virtual method pointer lookup failure."); sb.AppendLine(); sb.AppendLine("Declaring type: " + declaringType.LastResortToString); sb.AppendLine("Target type: " + type.LastResortToString); sb.AppendLine("Method name: " + methodNameAndSignature.Name); sb.AppendLine("Instantiation:"); for (int i = 0; i < genericArguments.Length; i++) { sb.AppendLine(" Argument " + i.LowLevelToString() + ": " + genericArguments[i].LastResortToString); } Environment.FailFast(sb.ToString()); } return(resolution); }