Skip to content

Commit eedcf5e

Browse files
committed
make the memset encoding which uses Prim type class memset round trip trick more explicit and obvious.
1 parent 96bbd13 commit eedcf5e

File tree

1 file changed

+32
-11
lines changed

1 file changed

+32
-11
lines changed

Data/Vector/Storable/Mutable.hs

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -74,12 +74,14 @@ import GHC.Prim (byteArrayContents#, unsafeCoerce#)
7474
import GHC.ForeignPtr
7575
#endif
7676

77+
import GHC.Base ( Int(..) )
78+
7779
import Foreign.Ptr
7880
import Foreign.Marshal.Array ( advancePtr, copyArray, moveArray )
7981

8082
import Control.Monad.Primitive
81-
import Data.Primitive.Addr
8283
import Data.Primitive.Types (Prim)
84+
import qualified Data.Primitive.Types as DPT
8385

8486
import GHC.Word (Word8, Word16, Word32, Word64)
8587
import GHC.Ptr (Ptr(..))
@@ -163,13 +165,11 @@ instance Storable a => G.MVector MVector a where
163165

164166
storableZero :: forall a m. (Storable a, PrimMonad m) => MVector (PrimState m) a -> m ()
165167
{-# INLINE storableZero #-}
166-
storableZero (MVector n fp) = unsafePrimToPrim . withForeignPtr fp $ \(Ptr p) -> do
167-
let q = Addr p
168-
setAddr q byteSize (0 :: Word8)
168+
storableZero (MVector n fp) = unsafePrimToPrim . withForeignPtr fp $ \ptr-> do
169+
memsetPrimPtr_vector (castPtr ptr) byteSize (0 :: Word8)
169170
where
170171
x :: a
171172
x = undefined
172-
173173
byteSize :: Int
174174
byteSize = n * sizeOf x
175175

@@ -195,13 +195,34 @@ storableSet (MVector n fp) x
195195
do_set 1
196196

197197
storableSetAsPrim
198-
:: (Storable a, Prim b) => Int -> ForeignPtr a -> a -> b -> IO ()
198+
:: forall a b . (Storable a, Prim b) => Int -> ForeignPtr a -> a -> b -> IO ()
199199
{-# INLINE [0] storableSetAsPrim #-}
200-
storableSetAsPrim n fp x y = withForeignPtr fp $ \(Ptr p) -> do
201-
poke (Ptr p) x
202-
let q = Addr p
203-
w <- readOffAddr q 0
204-
setAddr (q `plusAddr` sizeOf x) (n-1) (w `asTypeOf` y)
200+
storableSetAsPrim n fp x y = withForeignPtr fp $ \ ptr -> do
201+
poke ptr x
202+
-- we dont equate storable and prim reps, so we need to write to a slot
203+
-- in storable
204+
-- then read it back as a prim
205+
w<- peakPrimPtr_vector ((castPtr ptr) :: Ptr b) 0
206+
memsetPrimPtr_vector ((castPtr ptr) `plusPtr` sizeOf x ) (n-1) w
207+
208+
209+
210+
{-
211+
AFTER primitive 0.7 is pretty old, move to using setPtr. which is really
212+
a confusing misnomer for whats often called memset (intialize )
213+
-}
214+
-- Fill a memory block with the given value. The length is in
215+
-- elements of type @a@ rather than in bytes.
216+
memsetPrimPtr_vector :: forall a c m. (Prim c, PrimMonad m) => Ptr a -> Int -> c -> m ()
217+
memsetPrimPtr_vector (Ptr addr#) (I# n#) x = primitive_ (DPT.setOffAddr# addr# 0# n# x)
218+
{-# INLINE memsetPrimPtr_vector #-}
219+
220+
221+
-- Read a value from a memory position given by an address and an offset.
222+
-- The offset is in elements of type @a@ rather than in bytes.
223+
peakPrimPtr_vector :: (Prim a, PrimMonad m) => Ptr a -> Int -> m a
224+
peakPrimPtr_vector (Ptr addr#) (I# i#) = primitive (DPT.readOffAddr# addr# i#)
225+
{-# INLINE peakPrimPtr_vector #-}
205226

206227
{-# INLINE mallocVector #-}
207228
mallocVector :: Storable a => Int -> IO (ForeignPtr a)

0 commit comments

Comments
 (0)