/// <summary> /// Create a new value from a key. Must be threadsafe. Value may or may not be added /// to collection. Return value must not be null. /// </summary> protected override unsafe MethodEntrypointPtr CreateValueFromKey(MethodEntrypointLookup key) { lock (this) { IntPtr thunk = IntPtr.Zero; if (s_thunkPoolHeap == null) { s_thunkPoolHeap = RuntimeAugments.CreateThunksHeap(s_entryPointStub); MethodEntrypointPtr.SetThunkPool(s_thunkPoolHeap); Debug.Assert(s_thunkPoolHeap != null); } thunk = RuntimeAugments.AllocateThunk(s_thunkPoolHeap); Debug.Assert(thunk != IntPtr.Zero); MethodEntrypointData *methodEntrypointData = (MethodEntrypointData *)MemoryHelpers.AllocateMemory(sizeof(MethodEntrypointData)); *methodEntrypointData = new MethodEntrypointData(key.MethodHandle, thunk); RuntimeAugments.SetThunkData(s_thunkPoolHeap, thunk, IntPtr.Zero, new IntPtr(methodEntrypointData)); SerializedDebugData.RegisterTailCallThunk(thunk); return(new MethodEntrypointPtr(methodEntrypointData)); } }
public IntPtr ContextData; // ThunkContextData pointer which will be stored in the context slot of the thunk public PInvokeDelegateThunk(Delegate del) { Thunk = RuntimeAugments.AllocateThunk(s_thunkPoolHeap); Debug.Assert(Thunk != IntPtr.Zero); if (Thunk == IntPtr.Zero) { // We've either run out of memory, or failed to allocate a new thunk due to some other bug. Now we should fail fast Environment.FailFast("Insufficient number of thunks."); } else { // // Allocate unmanaged memory for GCHandle of delegate and function pointer of open static delegate // We will store this pointer on the context slot of thunk data // ContextData = AllocHGlobal(2 * IntPtr.Size); unsafe { ThunkContextData *thunkData = (ThunkContextData *)ContextData; // allocate a weak GChandle for the delegate thunkData->Handle = GCHandle.Alloc(del, GCHandleType.Weak); // if it is an open static delegate get the function pointer thunkData->FunctionPtr = del.GetRawFunctionPointerForOpenStaticDelegate(); } } }
private static IntPtr GetThunkThatDereferencesThisPointerAndTailCallsTarget(IntPtr target) { IntPtr result = IntPtr.Zero; lock (s_deferenceAndCallThunks) { if (!s_deferenceAndCallThunks.TryGetValue(target, out result)) { if (s_DerefThisAndCall_ThunkPoolHeap == null) { s_DerefThisAndCall_ThunkPoolHeap = RuntimeAugments.CreateThunksHeap(s_constrainedCallSupport_DerefThisAndCall_CommonCallingStub); Debug.Assert(s_DerefThisAndCall_ThunkPoolHeap != null); } IntPtr thunk = RuntimeAugments.AllocateThunk(s_DerefThisAndCall_ThunkPoolHeap); Debug.Assert(thunk != IntPtr.Zero); RuntimeAugments.SetThunkData(s_DerefThisAndCall_ThunkPoolHeap, thunk, target, IntPtr.Zero); result = thunk; s_deferenceAndCallThunks.Add(target, result); } SerializedDebugData.RegisterTailCallThunk(result); } return(result); }
public static unsafe IntPtr GetDirectConstrainedCallPtr(RuntimeTypeHandle constraintType, RuntimeTypeHandle constrainedMethodType, int constrainedMethodSlot) { if (s_DirectConstrainedCall_ThunkPoolHeap == null) { lock (s_DirectConstrainedCall_ThunkPoolHeapLock) { if (s_DirectConstrainedCall_ThunkPoolHeap == null) { s_DirectConstrainedCall_ThunkPoolHeap = RuntimeAugments.CreateThunksHeap(s_constrainedCallSupport_DirectConstrainedCall_CommonCallingStub); Debug.Assert(s_DirectConstrainedCall_ThunkPoolHeap != null); } } } IntPtr thunk = RuntimeAugments.AllocateThunk(s_DirectConstrainedCall_ThunkPoolHeap); Debug.Assert(thunk != IntPtr.Zero); IntPtr constrainedCallDesc = Get(constraintType, constrainedMethodType, constrainedMethodSlot, true); RuntimeAugments.SetThunkData(s_DirectConstrainedCall_ThunkPoolHeap, thunk, constrainedCallDesc, s_resolveDirectConstrainedCallFuncPtr); SerializedDebugData.RegisterTailCallThunk(thunk); return(thunk); }
private static IntPtr AllocateThunk(Delegate del) { //TODO: cache del->thunk here if (s_thunkPoolHeap == null) { s_thunkPoolHeap = RuntimeAugments.CreateThunksHeap(RuntimeImports.GetInteropCommonStubAddress()); Debug.Assert(s_thunkPoolHeap != null); } IntPtr pThunk = RuntimeAugments.AllocateThunk(s_thunkPoolHeap); Debug.Assert(pThunk != IntPtr.Zero); if (pThunk == IntPtr.Zero) { // We've either run out of memory, or failed to allocate a new thunk due to some other bug. Now we should fail fast Environment.FailFast("Insufficient number of thunks."); return(IntPtr.Zero); } else { McgPInvokeDelegateData pinvokeDelegateData; if (!RuntimeAugments.InteropCallbacks.TryGetMarshallerDataForDelegate(del.GetTypeHandle(), out pinvokeDelegateData)) { Environment.FailFast("Couldn't find marshalling stubs for delegate."); } IntPtr pContext; unsafe { // // Allocate unmanaged memory for GCHandle of delegate and function pointer of open static delegate // We will store this pointer on the context slot of thunk data // pContext = (IntPtr)CoTaskMemAllocAndZeroMemory((System.IntPtr)(2 * (IntPtr.Size))); ThunkContextData *thunkData = (ThunkContextData *)pContext; (*thunkData).Handle = GCHandle.Alloc(del, GCHandleType.Weak); (*thunkData).FunctionPtr = del.GetRawFunctionPointerForOpenStaticDelegate(); } // // For open static delegates set target to ReverseOpenStaticDelegateStub which calls the static function pointer directly // IntPtr pTarget = del.GetRawFunctionPointerForOpenStaticDelegate() == IntPtr.Zero ? pinvokeDelegateData.ReverseStub : pinvokeDelegateData.ReverseOpenStaticDelegateStub; RuntimeAugments.SetThunkData(s_thunkPoolHeap, pThunk, pContext, pTarget); return(pThunk); } }
private static IntPtr CreateDynamicThunk(int slotIndex) { if (s_lazyVtableThunksPoolHeap == null) { s_lazyVtableThunksPoolHeap = RuntimeAugments.CreateThunksHeap(VTableResolver_GetCommonCallingStub()); Debug.Assert(s_lazyVtableThunksPoolHeap != null); } IntPtr thunk = RuntimeAugments.AllocateThunk(s_lazyVtableThunksPoolHeap); if (thunk == IntPtr.Zero) { Environment.FailFast("Not enough thunks for calling convention converter"); } int eetypeVtableOffset = SlotIndexToEETypeVTableOffset(slotIndex); RuntimeAugments.SetThunkData(s_lazyVtableThunksPoolHeap, thunk, new IntPtr(eetypeVtableOffset), thunk); return(thunk); }