Skip to content

Enlarging SmallMutableArray#s more efficiently

resizeSmallMutableArray# is currently implemented like this:

resizeSmallMutableArray#
  :: SmallMutableArray# s a -- ^ Array to resize
  -> Int# -- ^ New size of array
  -> a
     -- ^ Newly created slots initialized to this element.
     -- Only used when array is grown.
  -> State# s
  -> (# State# s, SmallMutableArray# s a #)
resizeSmallMutableArray# arr0 szNew a s0 =
  case getSizeofSmallMutableArray# arr0 s0 of
    (# s1, szOld #) -> if isTrue# (szNew <# szOld)
      then case shrinkSmallMutableArray# arr0 szNew s1 of
        s2 -> (# s2, arr0 #)
      else if isTrue# (szNew ># szOld)
        then case newSmallArray# szNew a s1 of
          (# s2, arr1 #) -> case copySmallMutableArray# arr0 0# arr1 0# szOld s2 of
            s3 -> (# s3, arr1 #)
        else (# s1, arr0 #)

Notably, in order to enlarge the array, a new array is allocated and initialized with a filler element (a), and then the contents from the old one are copied over.

I have two questions about this:

  1. Why isn't the initialization with the filler element skipped for length of the original array? Or are these write operations optimized away somehow?

  2. Why is there no attempt to use the slop at the end of the array that results from a previous use of shrinkSmallMutableArray#? This should make it unnecessary to allocate a fresh array in some cases, no?

To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information