public static unsafe bool Compare(IntPtr functionPointerA, IntPtr functionPointerB) { if (!IsGenericMethodPointer(functionPointerA)) { IntPtr codeTargetA = RuntimeAugments.GetCodeTarget(functionPointerA); IntPtr codeTargetB = RuntimeAugments.GetCodeTarget(functionPointerB); return(codeTargetA == codeTargetB); } else { if (!IsGenericMethodPointer(functionPointerB)) { return(false); } GenericMethodDescriptor *pointerDefA = ConvertToGenericDescriptor(functionPointerA); GenericMethodDescriptor *pointerDefB = ConvertToGenericDescriptor(functionPointerB); if (pointerDefA->InstantiationArgument != pointerDefB->InstantiationArgument) { return(false); } IntPtr codeTargetA = RuntimeAugments.GetCodeTarget(pointerDefA->MethodFunctionPointer); IntPtr codeTargetB = RuntimeAugments.GetCodeTarget(pointerDefB->MethodFunctionPointer); return(codeTargetA == codeTargetB); } }
protected virtual object DynamicInvokeImpl(object[] args) { if (IsDynamicDelegate()) { // DynamicDelegate case object result = ((Func <object[], object>)m_helperObject)(args); DebugAnnotations.PreviousCallContainsDebuggerStepInCode(); return(result); } else { IntPtr invokeThunk = this.GetThunk(DelegateInvokeThunk); #if PROJECTN object result = InvokeUtils.CallDynamicInvokeMethod(this.m_firstParameter, this.m_functionPointer, this, invokeThunk, IntPtr.Zero, this, args, binderBundle: null, wrapInTargetInvocationException: true); #else IntPtr genericDictionary = IntPtr.Zero; if (FunctionPointerOps.IsGenericMethodPointer(invokeThunk)) { unsafe { GenericMethodDescriptor *descriptor = FunctionPointerOps.ConvertToGenericDescriptor(invokeThunk); genericDictionary = descriptor->InstantiationArgument; invokeThunk = descriptor->MethodFunctionPointer; } } object result = InvokeUtils.CallDynamicInvokeMethod(this.m_firstParameter, this.m_functionPointer, null, invokeThunk, genericDictionary, this, args, binderBundle: null, wrapInTargetInvocationException: true, invokeMethodHelperIsThisCall: false); #endif DebugAnnotations.PreviousCallContainsDebuggerStepInCode(); return(result); } }
public static unsafe IntPtr GetGenericMethodFunctionPointer(IntPtr canonFunctionPointer, IntPtr instantiationArgument) { if (instantiationArgument == IntPtr.Zero) { return(canonFunctionPointer); } lock (s_genericFunctionPointerDictionary) { GenericMethodDescriptorInfo key; key.MethodFunctionPointer = canonFunctionPointer; key.InstantiationArgument = instantiationArgument; uint index = 0; if (!s_genericFunctionPointerDictionary.TryGetValue(key, out index)) { // Capture new index value index = s_genericFunctionPointerNextIndex; int newChunkIndex = (int)(index / c_genericDictionaryChunkSize); uint newSubChunkIndex = index % c_genericDictionaryChunkSize; // Generate new chunk if existing chunks are insufficient if (s_genericFunctionPointerCollection.Count <= newChunkIndex) { System.Diagnostics.Debug.Assert(newSubChunkIndex == 0); // New generic descriptors are allocated on the native heap and not tracked in the GC. UIntPtr allocationSize = new UIntPtr((uint)(c_genericDictionaryChunkSize * sizeof(RuntimeGeneratedGenericMethodDescriptor))); IntPtr pNewMem = Interop.MemAlloc(allocationSize); s_genericFunctionPointerCollection.Add(pNewMem); } RuntimeGeneratedGenericMethodDescriptor *newDescriptor = &((RuntimeGeneratedGenericMethodDescriptor *)s_genericFunctionPointerCollection[newChunkIndex])[newSubChunkIndex]; newDescriptor->Set(canonFunctionPointer, instantiationArgument); s_genericFunctionPointerDictionary.LookupOrAdd(key, index); // Now that we can no longer have failed, update the next index. s_genericFunctionPointerNextIndex++; } // Lookup within list int chunkIndex = (int)(index / c_genericDictionaryChunkSize); uint subChunkIndex = index % c_genericDictionaryChunkSize; RuntimeGeneratedGenericMethodDescriptor *genericRuntimeFunctionPointer = &((RuntimeGeneratedGenericMethodDescriptor *)s_genericFunctionPointerCollection[chunkIndex])[subChunkIndex]; GenericMethodDescriptor *genericFunctionPointer = &genericRuntimeFunctionPointer->Descriptor; System.Diagnostics.Debug.Assert(canonFunctionPointer == genericFunctionPointer->MethodFunctionPointer); System.Diagnostics.Debug.Assert(instantiationArgument == genericFunctionPointer->InstantiationArgument); return((IntPtr)((byte *)genericFunctionPointer + FatFunctionPointerOffset)); } }
public static IntPtr ConvertUnboxingFunctionPointerToUnderlyingNonUnboxingPointer(IntPtr unboxingFunctionPointer, RuntimeTypeHandle declaringType) { if (FunctionPointerOps.IsGenericMethodPointer(unboxingFunctionPointer)) { // Handle shared generic methods unsafe { GenericMethodDescriptor *functionPointerDescriptor = FunctionPointerOps.ConvertToGenericDescriptor(unboxingFunctionPointer); IntPtr nonUnboxingTarget = RuntimeAugments.GetCodeTarget(functionPointerDescriptor->MethodFunctionPointer); Debug.Assert(nonUnboxingTarget != functionPointerDescriptor->MethodFunctionPointer); Debug.Assert(nonUnboxingTarget == RuntimeAugments.GetCodeTarget(nonUnboxingTarget)); return(FunctionPointerOps.GetGenericMethodFunctionPointer(nonUnboxingTarget, functionPointerDescriptor->InstantiationArgument)); } } // GetCodeTarget will look through simple unboxing stubs (ones that consist of adjusting the this pointer and then // jumping to the target. IntPtr exactTarget = RuntimeAugments.GetCodeTarget(unboxingFunctionPointer); if (RuntimeAugments.IsGenericType(declaringType)) { IntPtr fatFunctionPointerTarget; // This check looks for unboxing and instantiating stubs generated via the compiler backend if (TypeLoaderEnvironment.TryGetTargetOfUnboxingAndInstantiatingStub(exactTarget, out fatFunctionPointerTarget)) { // If this is an unboxing and instantiating stub, use separate table, find target, and create fat function pointer exactTarget = FunctionPointerOps.GetGenericMethodFunctionPointer(fatFunctionPointerTarget, declaringType.ToIntPtr()); } #if FEATURE_UNIVERSAL_GENERICS else { IntPtr newExactTarget; // This check looks for unboxing and instantiating stubs generated dynamically as thunks in the calling convention converter if (CallConverterThunk.TryGetNonUnboxingFunctionPointerFromUnboxingAndInstantiatingStub(exactTarget, declaringType, out newExactTarget)) { // CallingConventionConverter determined non-unboxing stub exactTarget = newExactTarget; } else { // Target method was a method on a generic, but it wasn't a shared generic, and thus none of the above // complex unboxing stub digging logic was necessary. Do nothing, and use exactTarget as discovered // from GetCodeTarget } } #endif } return(exactTarget); }
private bool UpdateCalleeFunctionPointer(IntPtr newFunctionPointer) { if (FunctionPointerOps.IsGenericMethodPointer(newFunctionPointer)) { GenericMethodDescriptor *genericTarget = FunctionPointerOps.ConvertToGenericDescriptor(newFunctionPointer); _instantiatingStubArgument = genericTarget->InstantiationArgument; _functionPointerToCall = genericTarget->MethodFunctionPointer; return(true); } else { _functionPointerToCall = newFunctionPointer; return(false); } }
private unsafe static IntPtr ResolveCallOnReferenceTypeCacheMiss(IntPtr context, IntPtr callDescIntPtr, object contextObject, out IntPtr auxResult) { auxResult = IntPtr.Zero; // Perform a normal GVM dispatch, then change the function pointer to dereference the this pointer. GenericConstrainedCallDesc *callDesc = (GenericConstrainedCallDesc *)callDescIntPtr; IntPtr target = RuntimeAugments.GVMLookupForSlot(contextObject.GetType().TypeHandle, callDesc->_constrainedMethod); if (FunctionPointerOps.IsGenericMethodPointer(target)) { GenericMethodDescriptor *genMethodDesc = FunctionPointerOps.ConvertToGenericDescriptor(target); IntPtr actualCodeTarget = GetThunkThatDereferencesThisPointerAndTailCallsTarget(genMethodDesc->MethodFunctionPointer); return(FunctionPointerOps.GetGenericMethodFunctionPointer(actualCodeTarget, genMethodDesc->InstantiationArgument)); } else { return(GetThunkThatDereferencesThisPointerAndTailCallsTarget(target)); } }
private unsafe static IntPtr ResolveCallOnValueType(IntPtr unused, IntPtr callDescIntPtr) #endif { GenericConstrainedCallDesc *callDesc = (GenericConstrainedCallDesc *)callDescIntPtr; IntPtr targetAsVirtualCall = RuntimeAugments.GVMLookupForSlot(callDesc->_constraintType, callDesc->_constrainedMethod); IntPtr exactTarget = IntPtr.Zero; if (FunctionPointerOps.IsGenericMethodPointer(targetAsVirtualCall)) { GenericMethodDescriptor *genMethodDesc = FunctionPointerOps.ConvertToGenericDescriptor(targetAsVirtualCall); IntPtr actualCodeTarget = RuntimeAugments.GetCodeTarget(genMethodDesc->MethodFunctionPointer); exactTarget = FunctionPointerOps.GetGenericMethodFunctionPointer(actualCodeTarget, genMethodDesc->InstantiationArgument); } else { IntPtr actualCodeTarget = RuntimeAugments.GetCodeTarget(targetAsVirtualCall); IntPtr callConverterThunk; if (CallConverterThunk.TryGetNonUnboxingFunctionPointerFromUnboxingAndInstantiatingStub(actualCodeTarget, callDesc->_constraintType, out callConverterThunk)) { actualCodeTarget = callConverterThunk; } exactTarget = actualCodeTarget; } // Ensure that all threads will have their function pointers completely published before updating callDesc. // as the ExactTarget is read from callDesc by binder generated code without a barrier, we need a barrier here // to ensure that the new function pointer data is valid on all threads Interlocked.MemoryBarrier(); // Its possible for multiple threads to race to set exact target. Check to see we always set the same value if (callDesc->_exactTarget != IntPtr.Zero) { Debug.Assert(callDesc->_exactTarget == exactTarget); } callDesc->_exactTarget = exactTarget; return(exactTarget); }
private string GetTargetMethodsDescriptionForDebugger() { if (m_functionPointer == GetThunk(MulticastThunk)) { // Multi-cast delegates return the Target of the last delegate in the list Delegate[] invocationList = (Delegate[])m_helperObject; int invocationCount = (int)m_extraFunctionPointerOrData; StringBuilder builder = new StringBuilder(); for (int c = 0; c < invocationCount; c++) { if (c != 0) { builder.Append(", "); } builder.Append(invocationList[c].GetTargetMethodsDescriptionForDebugger()); } return(builder.ToString()); } else { RuntimeTypeHandle typeOfFirstParameterIfInstanceDelegate; bool isOpenThunk; IntPtr functionPointer = GetFunctionPointer(out typeOfFirstParameterIfInstanceDelegate, out isOpenThunk); if (!FunctionPointerOps.IsGenericMethodPointer(functionPointer)) { return(DebuggerFunctionPointerFormattingHook(functionPointer, typeOfFirstParameterIfInstanceDelegate)); } else { unsafe { GenericMethodDescriptor *pointerDef = FunctionPointerOps.ConvertToGenericDescriptor(functionPointer); return(DebuggerFunctionPointerFormattingHook(pointerDef->InstantiationArgument, typeOfFirstParameterIfInstanceDelegate)); } } } }
public static unsafe bool Compare(IntPtr functionPointerA, IntPtr functionPointerB) { if (!IsGenericMethodPointer(functionPointerA)) { return(functionPointerA == functionPointerB); } else { if (!IsGenericMethodPointer(functionPointerB)) { return(false); } GenericMethodDescriptor *pointerDefA = ConvertToGenericDescriptor(functionPointerA); GenericMethodDescriptor *pointerDefB = ConvertToGenericDescriptor(functionPointerB); if (pointerDefA->InstantiationArgument != pointerDefB->InstantiationArgument) { return(false); } return(pointerDefA->MethodFunctionPointer == pointerDefB->MethodFunctionPointer); } }