Example #1
0
            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));
                }
            }
Example #2
0
            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);
            }