Calling isByteArrayPinned# on compact ByteArray
The documentation explaining the relationship between pinnedness and compact regions is incomplete. From Data.Compact:
Pinned ByteArray# objects cannot be compacted. This is for a good reason: the memory is pinned so that it can be referenced by address (the address might be stored in a C data structure, for example), so we can't make a copy of it to store in the Compact.
This is half-way true since it only considers one a the ways in which the GHC runtime tracks the pinnedness of an object. From experimenting with compact regions, it seems like there are two different notions of pinnedness:
- Did the user explicitly ask for the
ByteArrayto be pinned? - Is the
ByteArraypinned?
If (1) is true, then (2) must always be true, but if (1) is false, then could be true or false. ByteArrays over 3KB are pinned, and ByteArrays under 3KB are not (or somewhere around that number).
With that background information in place, here's the scenario I've encountered:
{-# LANGUAGE MagicHash #-}
import Data.Primitive
import Data.Compact
import GHC.Int
import GHC.Prim
main :: IO ()
main = do
ByteArray arr1# <- fmap getCompact $ newByteArray 65000 >>= unsafeFreezeByteArray >>= compact
ByteArray arr2# <- newByteArray 65000 >>= unsafeFreezeByteArray
print (I# (isByteArrayPinned# arr1#))
print (I# (isByteArrayPinned# arr2#))
putStrLn "Finished"
When compiled and run, this gives:
0
1
Finished
We can see that the 65KiB ByteArray that was not compacted let's the user know that it is pinned. The compacted ByteArray claims to not be pinned, but this is not true. The docs in Data.Compact claim:
Data in a compact doesn't ever move, so compacting data is also a way to pin arbitrary data structures in memory.
I propose that the behavior of compact be modified to accurately convey the pinnedness of the ByteArrays that copies. This would mean that even small, previously unpinned, ByteArrays would also be designated as pinned. It's a small change, but it makes the information the runtime gives us more accurate. This is occasionally handy when dealing with the FFI.
Trac metadata
| Trac field | Value |
|---|---|
| Version | 8.2.2 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | ezyang, simonmar |
| Operating system | |
| Architecture |