/// <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)); } }
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); }
private static PInvokeDelegateThunk AllocateThunk(Delegate del) { if (s_thunkPoolHeap == null) { // TODO: Free s_thunkPoolHeap if the thread lose the race Interlocked.CompareExchange( ref s_thunkPoolHeap, RuntimeAugments.CreateThunksHeap(RuntimeImports.GetInteropCommonStubAddress()), null ); Debug.Assert(s_thunkPoolHeap != null); } var delegateThunk = new PInvokeDelegateThunk(del); McgPInvokeDelegateData pinvokeDelegateData; if (!RuntimeAugments.InteropCallbacks.TryGetMarshallerDataForDelegate(del.GetTypeHandle(), out pinvokeDelegateData)) { Environment.FailFast("Couldn't find marshalling stubs for delegate."); } // // 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, delegateThunk.Thunk, delegateThunk.ContextData, pTarget); return(delegateThunk); }
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 PInvokeDelegateThunk AllocateThunk(Delegate del) { if (s_thunkPoolHeap == null) { // TODO: Free s_thunkPoolHeap if the thread lose the race Interlocked.CompareExchange( ref s_thunkPoolHeap, RuntimeAugments.CreateThunksHeap(RuntimeImports.GetInteropCommonStubAddress()), null ); Debug.Assert(s_thunkPoolHeap != null); } var delegateThunk = new PInvokeDelegateThunk(del); // // For open static delegates set target to ReverseOpenStaticDelegateStub which calls the static function pointer directly // bool openStaticDelegate = del.GetRawFunctionPointerForOpenStaticDelegate() != IntPtr.Zero; IntPtr pTarget = RuntimeInteropData.GetDelegateMarshallingStub(del.GetTypeHandle(), openStaticDelegate); Debug.Assert(pTarget != IntPtr.Zero); RuntimeAugments.SetThunkData(s_thunkPoolHeap, delegateThunk.Thunk, delegateThunk.ContextData, pTarget); return(delegateThunk); }
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 GetOrAllocateThunk(Delegate del) { ConditionalWeakTable <Delegate, PInvokeDelegateThunk> pinvokeDelegates = GetPInvokeDelegates(); PInvokeDelegateThunk delegateThunk; // if the delegate already exists in the table return the allocated thunk for it if (pinvokeDelegates.TryGetValue(del, out delegateThunk)) { return(delegateThunk.Thunk); } if (s_thunkPoolHeap == null) { s_thunkPoolHeap = RuntimeAugments.CreateThunksHeap(RuntimeImports.GetInteropCommonStubAddress()); Debug.Assert(s_thunkPoolHeap != null); } delegateThunk = new PInvokeDelegateThunk(del); McgPInvokeDelegateData pinvokeDelegateData; if (!RuntimeAugments.InteropCallbacks.TryGetMarshallerDataForDelegate(del.GetTypeHandle(), out pinvokeDelegateData)) { Environment.FailFast("Couldn't find marshalling stubs for delegate."); } // // 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, delegateThunk.Thunk, delegateThunk.ContextData, pTarget); // Add the delegate to the dictionary if it doesn't already exists delegateThunk = pinvokeDelegates.GetOrAdd(del, delegateThunk); return(delegateThunk.Thunk); }
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); }