private unsafe ThunksHeap(IntPtr commonStubAddress) { _commonStubAddress = commonStubAddress; _allocatedBlocks = new AllocatedBlock(); InternalCalls.RhpAcquireThunkPoolLock(); IntPtr thunkStubsBlock = ThunkBlocks.GetNewThunksBlock(); InternalCalls.RhpReleaseThunkPoolLock(); if (thunkStubsBlock != IntPtr.Zero) { IntPtr thunkDataBlock = InternalCalls.RhpGetThunkDataBlockAddress(thunkStubsBlock); // Address of the first thunk data cell should be at the begining of the thunks data block (page-aligned) Debug.Assert(((nuint)(nint)thunkDataBlock % Constants.PageSize) == 0); // Update the last pointer value in the thunks data section with the value of the common stub address *(IntPtr *)(thunkDataBlock + (int)(Constants.PageSize - IntPtr.Size)) = commonStubAddress; Debug.Assert(*(IntPtr *)(thunkDataBlock + (int)(Constants.PageSize - IntPtr.Size)) == commonStubAddress); // Set the head and end of the linked list _nextAvailableThunkPtr = thunkDataBlock; _lastThunkPtr = _nextAvailableThunkPtr + Constants.ThunkDataSize * (Constants.NumThunksPerBlock - 1); _allocatedBlocks._blockBaseAddress = thunkStubsBlock; } }
private unsafe ThunksHeap(IntPtr commonStubAddress) { _commonStubAddress = commonStubAddress; _allocatedBlocks = new AllocatedBlock(); InternalCalls.RhpAcquireThunkPoolLock(); IntPtr thunksBlock = ThunkBlocks.GetNewThunksBlock(); InternalCalls.RhpReleaseThunkPoolLock(); if (thunksBlock != IntPtr.Zero) { // Update the last pointer value in the thunks data section with the value of the common stub address *((IntPtr *)(thunksBlock + (int)(Constants.PageSize * 2 - IntPtr.Size))) = commonStubAddress; Debug.Assert(*((IntPtr *)(thunksBlock + (int)(Constants.PageSize * 2 - IntPtr.Size))) != IntPtr.Zero); // Set the head and end of the linked list _nextAvailableThunkPtr = thunksBlock + (int)Constants.PageSize; _lastThunkPtr = _nextAvailableThunkPtr + 2 * IntPtr.Size * (InternalCalls.RhpGetNumThunksPerBlock() - 1); _allocatedBlocks._blockBaseAddress = thunksBlock; } }
// TODO: Feature // public static ThunksHeap DestroyThunksHeap(ThunksHeap heapToDestroy) // { // } // // Note: Expected to be called under lock // private unsafe bool ExpandHeap() { AllocatedBlock newBlockInfo; try { newBlockInfo = new AllocatedBlock(); } catch (Exception) { return(false); } IntPtr thunkStubsBlock = ThunkBlocks.GetNewThunksBlock(); if (thunkStubsBlock != IntPtr.Zero) { IntPtr thunkDataBlock = InternalCalls.RhpGetThunkDataBlockAddress(thunkStubsBlock); // Address of the first thunk data cell should be at the begining of the thunks data block (page-aligned) Debug.Assert(((nuint)(nint)thunkDataBlock % Constants.PageSize) == 0); // Update the last pointer value in the thunks data section with the value of the common stub address *(IntPtr *)(thunkDataBlock + (int)(Constants.PageSize - IntPtr.Size)) = _commonStubAddress; Debug.Assert(*(IntPtr *)(thunkDataBlock + (int)(Constants.PageSize - IntPtr.Size)) == _commonStubAddress); // Link the last entry in the old list to the first entry in the new list *((IntPtr *)_lastThunkPtr) = thunkDataBlock; // Update the pointer to the last entry in the list _lastThunkPtr = *((IntPtr *)_lastThunkPtr) + Constants.ThunkDataSize * (Constants.NumThunksPerBlock - 1); newBlockInfo._blockBaseAddress = thunkStubsBlock; newBlockInfo._nextBlock = _allocatedBlocks; _allocatedBlocks = newBlockInfo; return(true); } return(false); }
// TODO: Feature // public static ThunksHeap DestroyThunksHeap(ThunksHeap heapToDestroy) // { // } // // Note: Expected to be called under lock // private unsafe bool ExpandHeap() { AllocatedBlock newBlockInfo; try { newBlockInfo = new AllocatedBlock(); } catch { return(false); } IntPtr newBlockAddress = ThunkBlocks.GetNewThunksBlock(); if (newBlockAddress != IntPtr.Zero) { // Update the last pointer value in the thunks data section with the value of the common stub address *((IntPtr *)(newBlockAddress + (int)(Constants.PageSize * 2 - IntPtr.Size))) = _commonStubAddress; Debug.Assert(*((IntPtr *)(newBlockAddress + (int)(Constants.PageSize * 2 - IntPtr.Size))) != IntPtr.Zero); // Link the last entry in the old list to the first entry in the new list *((IntPtr *)_lastThunkPtr) = newBlockAddress + (int)Constants.PageSize; // Update the pointer to the last entry in the list _lastThunkPtr = newBlockAddress + (int)Constants.PageSize + 2 * IntPtr.Size * (InternalCalls.RhpGetNumThunksPerBlock() - 1); newBlockInfo._blockBaseAddress = newBlockAddress; newBlockInfo._nextBlock = _allocatedBlocks; _allocatedBlocks = newBlockInfo; return(true); } return(false); }