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; } }
private bool IsThunkInHeap(IntPtr thunkAddress) { nuint thunkAddressValue = (nuint)(nint)ClearThumbBit(thunkAddress); AllocatedBlock currentBlock = _allocatedBlocks; while (currentBlock != null) { if (thunkAddressValue >= (nuint)(nint)currentBlock._blockBaseAddress && thunkAddressValue < (nuint)(nint)currentBlock._blockBaseAddress + (nuint)(Constants.NumThunksPerBlock * Constants.ThunkCodeSize)) { return(true); } currentBlock = currentBlock._nextBlock; } return(false); }
private bool IsThunkInHeap(IntPtr thunkAddress) { nuint thunkAddressValue = (nuint)ClearThumbBit(thunkAddress); AllocatedBlock currentBlock = _allocatedBlocks; while (currentBlock != null) { if (thunkAddressValue >= (nuint)currentBlock._blockBaseAddress && thunkAddressValue < (nuint)currentBlock._blockBaseAddress + (nuint)(InternalCalls.RhpGetNumThunksPerBlock() * InternalCalls.RhpGetThunkSize())) { return(true); } currentBlock = currentBlock._nextBlock; } 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 (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); }
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)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; } }
// 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 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)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; }