@@ -239,6 +239,7 @@ import Streamly.Internal.Data.Unboxed
239
239
, pokeWith
240
240
, sizeOf
241
241
, touch
242
+ , sizeOfMutableByteArray
242
243
)
243
244
import GHC.Base
244
245
( IO (.. )
@@ -269,6 +270,8 @@ import qualified Prelude
269
270
import Prelude hiding
270
271
(length , foldr , read , unlines , splitAt , reverse , truncate )
271
272
273
+ import System.IO.Unsafe
274
+
272
275
#include "DocTestDataMutArray.hs"
273
276
274
277
-------------------------------------------------------------------------------
@@ -343,7 +346,6 @@ data MutArray a =
343
346
, arrEnd :: {-# UNPACK #-} ! Int -- ^ index into arrContents
344
347
-- Represents the first invalid index of
345
348
-- the array.
346
- , arrBound :: {-# UNPACK #-} ! Int -- ^ first invalid index of arrContents.
347
349
}
348
350
349
351
-------------------------------------------------------------------------------
@@ -398,15 +400,14 @@ newArrayWith alloc alignSize count = do
398
400
{ arrContents = contents
399
401
, arrStart = 0
400
402
, arrEnd = 0
401
- , arrBound = size
402
403
}
403
404
404
405
nil ::
405
406
#ifdef DEVBUILD
406
407
Unbox a =>
407
408
#endif
408
409
MutArray a
409
- nil = MutArray Unboxed. nil 0 0 0
410
+ nil = MutArray Unboxed. nil 0 0
410
411
411
412
412
413
-- | Allocates a pinned empty array that can hold 'count' items. The memory of
@@ -426,7 +427,6 @@ newPinnedBytes bytes = do
426
427
{ arrContents = contents
427
428
, arrStart = 0
428
429
, arrEnd = 0
429
- , arrBound = bytes
430
430
}
431
431
432
432
-- | Like 'newArrayWith' but using an allocator is a pinned memory allocator and
@@ -725,6 +725,7 @@ roundDownTo elemSize size = size - (size `mod` elemSize)
725
725
{-# NOINLINE reallocExplicit #-}
726
726
reallocExplicit :: Int -> Int -> MutArray a -> IO (MutArray a )
727
727
reallocExplicit elemSize newCapacityInBytes MutArray {.. } = do
728
+ arrBound <- sizeOfMutableByteArray arrContents
728
729
assertM(arrEnd <= arrBound)
729
730
730
731
-- Allocate new array
@@ -749,7 +750,6 @@ reallocExplicit elemSize newCapacityInBytes MutArray{..} = do
749
750
{ arrStart = 0
750
751
, arrContents = contents
751
752
, arrEnd = newLenInBytes
752
- , arrBound = newCapInBytes
753
753
}
754
754
755
755
-- | @realloc newCapacity array@ reallocates the array to the specified
@@ -839,6 +839,7 @@ resizeExp nElems arr@MutArray{..} = do
839
839
{-# INLINE rightSize #-}
840
840
rightSize :: forall m a . (MonadIO m , Unbox a ) => MutArray a -> m (MutArray a )
841
841
rightSize arr@ MutArray {.. } = do
842
+ arrBound <- liftIO $ sizeOfMutableByteArray arrContents
842
843
assert (arrEnd <= arrBound) (return () )
843
844
let start = arrStart
844
845
len = arrEnd - start
@@ -871,6 +872,7 @@ rightSize arr@MutArray{..} = do
871
872
{-# INLINE snocNewEnd #-}
872
873
snocNewEnd :: (MonadIO m , Unbox a ) => Int -> MutArray a -> a -> m (MutArray a )
873
874
snocNewEnd newEnd arr@ MutArray {.. } x = liftIO $ do
875
+ arrBound <- liftIO $ sizeOfMutableByteArray arrContents
874
876
assert (newEnd <= arrBound) (return () )
875
877
pokeWith arrContents arrEnd x
876
878
return $ arr {arrEnd = newEnd}
@@ -894,6 +896,7 @@ snocMay :: forall m a. (MonadIO m, Unbox a) =>
894
896
MutArray a -> a -> m (Maybe (MutArray a ))
895
897
snocMay arr@ MutArray {.. } x = liftIO $ do
896
898
let newEnd = INDEX_NEXT (arrEnd,a)
899
+ arrBound <- sizeOfMutableByteArray arrContents
897
900
if newEnd <= arrBound
898
901
then Just <$> snocNewEnd newEnd arr x
899
902
else return Nothing
@@ -930,7 +933,8 @@ snocWith :: forall m a. (MonadIO m, Unbox a) =>
930
933
-> m (MutArray a )
931
934
snocWith allocSize arr x = liftIO $ do
932
935
let newEnd = INDEX_NEXT (arrEnd arr,a)
933
- if newEnd <= arrBound arr
936
+ arrBound <- sizeOfMutableByteArray (arrContents arr)
937
+ if newEnd <= arrBound
934
938
then snocNewEnd newEnd arr x
935
939
else snocWithRealloc allocSize arr x
936
940
@@ -1026,15 +1030,15 @@ getIndicesD liftio (D.Stream stepi sti) = Unfold step inject
1026
1030
1027
1031
where
1028
1032
1029
- inject (MutArray contents start end _ ) =
1033
+ inject (MutArray contents start end) =
1030
1034
return $ GetIndicesState contents start end sti
1031
1035
1032
1036
{-# INLINE_LATE step #-}
1033
1037
step (GetIndicesState contents start end st) = do
1034
1038
r <- stepi defState st
1035
1039
case r of
1036
1040
D. Yield i s -> do
1037
- x <- liftio $ getIndex i (MutArray contents start end undefined )
1041
+ x <- liftio $ getIndex i (MutArray contents start end)
1038
1042
return $ D. Yield x (GetIndicesState contents start end s)
1039
1043
D. Skip s -> return $ D. Skip (GetIndicesState contents start end s)
1040
1044
D. Stop -> return D. Stop
@@ -1062,14 +1066,14 @@ getSliceUnsafe :: forall a. Unbox a
1062
1066
-> Int -- ^ length of the slice
1063
1067
-> MutArray a
1064
1068
-> MutArray a
1065
- getSliceUnsafe index len (MutArray contents start e _ ) =
1069
+ getSliceUnsafe index len (MutArray contents start e) =
1066
1070
let fp1 = INDEX_OF (start,index,a)
1067
1071
end = fp1 + (len * SIZE_OF (a))
1068
1072
in assert
1069
1073
(index >= 0 && len >= 0 && end <= e)
1070
1074
-- Note: In a slice we always use bound = end so that the slice
1071
1075
-- user cannot overwrite elements beyond the end of the slice.
1072
- (MutArray contents fp1 end end )
1076
+ (MutArray contents fp1 end)
1073
1077
1074
1078
-- | /O(1)/ Slice an array in constant time. Throws an error if the slice
1075
1079
-- extends out of the array bounds.
@@ -1081,13 +1085,13 @@ getSlice :: forall a. Unbox a =>
1081
1085
-> Int -- ^ length of the slice
1082
1086
-> MutArray a
1083
1087
-> MutArray a
1084
- getSlice index len (MutArray contents start e _ ) =
1088
+ getSlice index len (MutArray contents start e) =
1085
1089
let fp1 = INDEX_OF (start,index,a)
1086
1090
end = fp1 + (len * SIZE_OF (a))
1087
1091
in if index >= 0 && len >= 0 && end <= e
1088
1092
-- Note: In a slice we always use bound = end so that the slice user
1089
1093
-- cannot overwrite elements beyond the end of the slice.
1090
- then MutArray contents fp1 end end
1094
+ then MutArray contents fp1 end
1091
1095
else error
1092
1096
$ " getSlice: invalid slice, index "
1093
1097
++ show index ++ " length " ++ show len
@@ -1138,8 +1142,8 @@ partitionBy f arr@MutArray{..} = liftIO $ do
1138
1142
then return (arr, arr)
1139
1143
else do
1140
1144
ptr <- go arrStart (INDEX_PREV (arrEnd,a))
1141
- let pl = MutArray arrContents arrStart ptr ptr
1142
- pr = MutArray arrContents ptr arrEnd arrEnd
1145
+ let pl = MutArray arrContents arrStart ptr
1146
+ pr = MutArray arrContents ptr arrEnd
1143
1147
return (pl, pr)
1144
1148
1145
1149
where
@@ -1259,14 +1263,19 @@ length arr =
1259
1263
blen = byteLength arr
1260
1264
in assert (blen `mod` elemSize == 0 ) (blen `div` elemSize)
1261
1265
1266
+ {-# INLINE getArrSizeUnsafe #-}
1267
+ getArrSizeUnsafe :: MutableByteArray -> Int
1268
+ getArrSizeUnsafe = unsafePerformIO . sizeOfMutableByteArray
1269
+
1262
1270
-- | Get the total capacity of an array. An array may have space reserved
1263
1271
-- beyond the current used length of the array.
1264
1272
--
1265
1273
-- /Pre-release/
1266
1274
{-# INLINE byteCapacity #-}
1267
1275
byteCapacity :: MutArray a -> Int
1268
1276
byteCapacity MutArray {.. } =
1269
- let len = arrBound - arrStart
1277
+ let arrBound = getArrSizeUnsafe arrContents
1278
+ len = arrBound - arrStart
1270
1279
in assert (len >= 0 ) len
1271
1280
1272
1281
-- | The remaining capacity in the array for appending more elements without
@@ -1276,7 +1285,8 @@ byteCapacity MutArray{..} =
1276
1285
{-# INLINE bytesFree #-}
1277
1286
bytesFree :: MutArray a -> Int
1278
1287
bytesFree MutArray {.. } =
1279
- let n = arrBound - arrEnd
1288
+ let arrBound = getArrSizeUnsafe arrContents
1289
+ n = arrBound - arrEnd
1280
1290
in assert (n >= 0 ) n
1281
1291
1282
1292
-------------------------------------------------------------------------------
@@ -1315,7 +1325,8 @@ chunksOf n (D.Stream step state) =
1315
1325
error $ " Streamly.Internal.Data.MutArray.Mut.Type.chunksOf: "
1316
1326
++ " the size of arrays [" ++ show n
1317
1327
++ " ] must be a natural number"
1318
- (MutArray contents start end bound :: MutArray a ) <- liftIO $ newPinned n
1328
+ (MutArray contents start end :: MutArray a ) <- liftIO $ newPinned n
1329
+ bound <- liftIO $ sizeOfMutableByteArray contents
1319
1330
return $ D. Skip (GroupBuffer st contents start end bound)
1320
1331
1321
1332
step' gst (GroupBuffer st contents start end bound) = do
@@ -1329,15 +1340,15 @@ chunksOf n (D.Stream step state) =
1329
1340
then D. Skip
1330
1341
(GroupYield
1331
1342
contents start end1 bound (GroupStart s))
1332
- else D. Skip (GroupBuffer s contents start end1 bound)
1343
+ else D. Skip (GroupBuffer s contents start end1 bound)
1333
1344
D. Skip s ->
1334
1345
return $ D. Skip (GroupBuffer s contents start end bound)
1335
1346
D. Stop ->
1336
1347
return
1337
1348
$ D. Skip (GroupYield contents start end bound GroupFinish )
1338
1349
1339
- step' _ (GroupYield contents start end bound next) =
1340
- return $ D. Yield (MutArray contents start end bound ) next
1350
+ step' _ (GroupYield contents start end _bound next) =
1351
+ return $ D. Yield (MutArray contents start end) next
1341
1352
1342
1353
step' _ GroupFinish = return D. Stop
1343
1354
@@ -1428,15 +1439,15 @@ data ArrayUnsafe a = ArrayUnsafe
1428
1439
{- # UNPACK #-} !Int -- index 2
1429
1440
1430
1441
toArrayUnsafe :: MutArray a -> ArrayUnsafe a
1431
- toArrayUnsafe (MutArray contents start end _ ) = ArrayUnsafe contents start end
1442
+ toArrayUnsafe (MutArray contents start end) = ArrayUnsafe contents start end
1432
1443
1433
1444
fromArrayUnsafe ::
1434
1445
#ifdef DEVBUILD
1435
1446
Unbox a =>
1436
1447
#endif
1437
1448
ArrayUnsafe a -> MutArray a
1438
1449
fromArrayUnsafe (ArrayUnsafe contents start end) =
1439
- MutArray contents start end end
1450
+ MutArray contents start end
1440
1451
1441
1452
{-# INLINE_NORMAL producerWith #-}
1442
1453
producerWith ::
@@ -1477,7 +1488,7 @@ readerRevWith ::
1477
1488
readerRevWith liftio = Unfold step inject
1478
1489
where
1479
1490
1480
- inject (MutArray contents start end _ ) =
1491
+ inject (MutArray contents start end) =
1481
1492
let p = INDEX_PREV (end,a)
1482
1493
in return $ ArrayUnsafe contents start p
1483
1494
@@ -1668,7 +1679,8 @@ writeAppendNUnsafe n action =
1668
1679
1669
1680
initial = do
1670
1681
assert (n >= 0 ) (return () )
1671
- arr@ (MutArray _ _ end bound) <- action
1682
+ arr@ (MutArray _ _ end) <- action
1683
+ bound <- liftIO $ sizeOfMutableByteArray (arrContents arr)
1672
1684
let free = bound - end
1673
1685
needed = n * SIZE_OF (a)
1674
1686
-- XXX We can also reallocate if the array has too much free space,
@@ -1789,8 +1801,9 @@ writeRevNWithUnsafe alloc n = fromArrayUnsafe <$> FL.foldlM' step initial
1789
1801
1790
1802
where
1791
1803
1792
- toArrayUnsafeRev (MutArray contents _ _ bound) =
1793
- ArrayUnsafe contents bound bound
1804
+ toArrayUnsafeRev arr@ (MutArray contents _ _) =
1805
+ let bound = getArrSizeUnsafe (arrContents arr)
1806
+ in ArrayUnsafe contents bound bound
1794
1807
1795
1808
initial = toArrayUnsafeRev <$> alloc (max n 0 )
1796
1809
@@ -1887,8 +1900,8 @@ writeWith elemCount =
1887
1900
when (elemCount < 0 ) $ error " writeWith: elemCount is negative"
1888
1901
liftIO $ newPinned elemCount
1889
1902
1890
- step arr@ (MutArray _ start end bound ) x
1891
- | INDEX_NEXT (end,a) > bound = do
1903
+ step arr@ (MutArray _ start end) x
1904
+ | INDEX_NEXT (end,a) > getArrSizeUnsafe (arrContents arr) = do
1892
1905
let oldSize = end - start
1893
1906
newSize = max (oldSize * 2 ) 1
1894
1907
arr1 <- liftIO $ reallocExplicit (SIZE_OF (a)) newSize arr
@@ -2004,7 +2017,8 @@ fromListRev xs = fromListRevN (Prelude.length xs) xs
2004
2017
{-# INLINE putSliceUnsafe #-}
2005
2018
putSliceUnsafe :: MonadIO m => MutArray a -> Int -> MutArray a -> Int -> Int -> m ()
2006
2019
putSliceUnsafe src srcStartBytes dst dstStartBytes lenBytes = liftIO $ do
2007
- assertM(lenBytes <= arrBound dst - dstStartBytes)
2020
+ arrBound <- sizeOfMutableByteArray (arrContents dst)
2021
+ assertM(lenBytes <= arrBound - dstStartBytes)
2008
2022
assertM(lenBytes <= arrEnd src - srcStartBytes)
2009
2023
let ! (I # srcStartBytes# ) = srcStartBytes
2010
2024
! (I # dstStartBytes# ) = dstStartBytes
@@ -2029,7 +2043,7 @@ spliceCopy arr1 arr2 = liftIO $ do
2029
2043
len2 = arrEnd arr2 - start2
2030
2044
newArrContents <- liftIO $ Unboxed. newPinnedBytes (len1 + len2)
2031
2045
let len = len1 + len2
2032
- newArr = MutArray newArrContents 0 len len
2046
+ newArr = MutArray newArrContents 0 len
2033
2047
putSliceUnsafe arr1 start1 newArr 0 len1
2034
2048
putSliceUnsafe arr2 start2 newArr len1 len2
2035
2049
return newArr
@@ -2045,7 +2059,8 @@ spliceUnsafe dst src =
2045
2059
let startSrc = arrStart src
2046
2060
srcLen = arrEnd src - startSrc
2047
2061
endDst = arrEnd dst
2048
- assertM(endDst + srcLen <= arrBound dst)
2062
+ arrBound <- sizeOfMutableByteArray (arrContents dst)
2063
+ assertM(endDst + srcLen <= arrBound)
2049
2064
putSliceUnsafe src startSrc dst endDst srcLen
2050
2065
return $ dst {arrEnd = endDst + srcLen}
2051
2066
@@ -2060,11 +2075,12 @@ spliceUnsafe dst src =
2060
2075
{-# INLINE spliceWith #-}
2061
2076
spliceWith :: forall m a . (MonadIO m , Unbox a ) =>
2062
2077
(Int -> Int -> Int ) -> MutArray a -> MutArray a -> m (MutArray a )
2063
- spliceWith sizer dst@ (MutArray _ start end bound ) src = do
2078
+ spliceWith sizer dst@ (MutArray _ start end) src = do
2064
2079
{-
2065
2080
let f = writeAppendWith (`sizer` byteLength src) (return dst)
2066
2081
in D.fold f (toStreamD src)
2067
2082
-}
2083
+ bound <- liftIO $ sizeOfMutableByteArray (arrContents dst)
2068
2084
assert (end <= bound) (return () )
2069
2085
let srcBytes = arrEnd src - arrStart src
2070
2086
@@ -2131,13 +2147,11 @@ breakOn sep arr@MutArray{..} = asPtrUnsafe arr $ \p -> liftIO $ do
2131
2147
{ arrContents = arrContents
2132
2148
, arrStart = arrStart
2133
2149
, arrEnd = arrStart + sepIndex -- exclude the separator
2134
- , arrBound = arrStart + sepIndex
2135
2150
}
2136
2151
, Just $ MutArray
2137
2152
{ arrContents = arrContents
2138
2153
, arrStart = arrStart + (sepIndex + 1 )
2139
2154
, arrEnd = arrEnd
2140
- , arrBound = arrBound
2141
2155
}
2142
2156
)
2143
2157
@@ -2158,13 +2172,11 @@ splitAt i arr@MutArray{..} =
2158
2172
{ arrContents = arrContents
2159
2173
, arrStart = arrStart
2160
2174
, arrEnd = p
2161
- , arrBound = p
2162
2175
}
2163
2176
, MutArray
2164
2177
{ arrContents = arrContents
2165
2178
, arrStart = p
2166
2179
, arrEnd = arrEnd
2167
- , arrBound = arrBound
2168
2180
}
2169
2181
)
2170
2182
@@ -2184,8 +2196,8 @@ castUnsafe ::
2184
2196
Unbox b =>
2185
2197
#endif
2186
2198
MutArray a -> MutArray b
2187
- castUnsafe (MutArray contents start end bound ) =
2188
- MutArray contents start end bound
2199
+ castUnsafe (MutArray contents start end) =
2200
+ MutArray contents start end
2189
2201
2190
2202
-- | Cast an @MutArray a@ into an @MutArray Word8@.
2191
2203
--
@@ -2295,7 +2307,7 @@ strip :: forall a m. (Unbox a, MonadIO m) =>
2295
2307
strip eq arr@ MutArray {.. } = liftIO $ do
2296
2308
st <- getStart arrStart
2297
2309
end <- getLast arrEnd st
2298
- return arr {arrStart = st, arrEnd = end, arrBound = end }
2310
+ return arr {arrStart = st, arrEnd = end}
2299
2311
2300
2312
where
2301
2313
0 commit comments