Skip to content
GitLab
Projects Groups Topics Snippets
  • /
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
  • Register
  • Sign in
  • GHC GHC
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributor statistics
    • Graph
    • Compare revisions
    • Locked files
  • Issues 5.6k
    • Issues 5.6k
    • List
    • Boards
    • Service Desk
    • Milestones
    • Iterations
  • Merge requests 663
    • Merge requests 663
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Artifacts
    • Schedules
    • Test cases
  • Deployments
    • Deployments
    • Releases
  • Packages and registries
    • Packages and registries
    • Model experiments
  • Analytics
    • Analytics
    • CI/CD
    • Code review
    • Insights
    • Issue
    • Repository
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • Glasgow Haskell CompilerGlasgow Haskell Compiler
  • GHCGHC
  • Issues
  • #14900

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:

  1. Did the user explicitly ask for the ByteArray to be pinned?
  2. Is the ByteArray pinned?

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
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information
Assignee
Assign to
Time tracking