mirror of
https://github.com/composewell/streamly.git
synced 2024-09-11 11:37:22 +03:00
Use Proxy type in the sizeOf method of Unbox
This commit is contained in:
parent
5884b1ee09
commit
96a7c99708
@ -122,6 +122,7 @@ import Control.Exception (assert)
|
||||
import Control.Monad (when)
|
||||
import Control.Monad.IO.Class (MonadIO(..))
|
||||
import Data.Functor.Identity (Identity)
|
||||
import Data.Proxy (Proxy(..))
|
||||
import Data.Word (Word8)
|
||||
import Foreign.C.String (CString)
|
||||
import Foreign.Ptr (castPtr)
|
||||
|
@ -8,22 +8,23 @@
|
||||
--
|
||||
-- XXX Check the core to see if max can be statically eliminated. llvm can
|
||||
-- eliminate the comparison, but not sure if GHC NCG can.
|
||||
#define SIZE_OF(a) max 1 (sizeOf (undefined :: a))
|
||||
#define SIZE_OF(a) max 1 (sizeOf (Proxy :: Proxy a))
|
||||
#define STORABLE_SIZE_OF(a) max 1 (sizeOf (undefined :: a))
|
||||
|
||||
-- Move the pointer to ith element of specified type. Type is specified as the
|
||||
-- type variable in the signature of the function where this macro is used.
|
||||
#define PTR_NEXT(ptr,a) ptr `plusPtr` SIZE_OF(a)
|
||||
#define PTR_PREV(ptr,a) ptr `plusPtr` negate (SIZE_OF(a))
|
||||
#define PTR_NEXT(ptr,a) ptr `plusPtr` STORABLE_SIZE_OF(a)
|
||||
#define PTR_PREV(ptr,a) ptr `plusPtr` negate (STORABLE_SIZE_OF(a))
|
||||
|
||||
#define PTR_INDEX(ptr,i,a) ptr `plusPtr` (SIZE_OF(a) * i)
|
||||
#define PTR_RINDEX(ptr,i,a) ptr `plusPtr` negate (SIZE_OF(a) * (i + 1))
|
||||
#define PTR_INDEX(ptr,i,a) ptr `plusPtr` (STORABLE_SIZE_OF(a) * i)
|
||||
#define PTR_RINDEX(ptr,i,a) ptr `plusPtr` negate (STORABLE_SIZE_OF(a) * (i + 1))
|
||||
|
||||
-- XXX If we know that the array is guaranteed to have size multiples of the
|
||||
-- element size then we can use a simpler check saying "ptr < end". Since we
|
||||
-- always allocate in multiples of elem we can use the simpler check and assert
|
||||
-- the rigorous check.
|
||||
#define PTR_VALID(ptr,end,a) ptr `plusPtr` SIZE_OF(a) <= end
|
||||
#define PTR_INVALID(ptr,end,a) ptr `plusPtr` SIZE_OF(a) > end
|
||||
#define PTR_VALID(ptr,end,a) ptr `plusPtr` STORABLE_SIZE_OF(a) <= end
|
||||
#define PTR_INVALID(ptr,end,a) ptr `plusPtr` STORABLE_SIZE_OF(a) > end
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- Macros to access array indices
|
||||
|
@ -30,6 +30,7 @@ where
|
||||
import Control.Monad.IO.Class (MonadIO(..))
|
||||
import Control.Monad (when)
|
||||
import Data.Bifunctor (first)
|
||||
import Data.Proxy (Proxy(..))
|
||||
import Streamly.Internal.Data.Unboxed (Unbox, sizeOf)
|
||||
import Streamly.Internal.Data.Array.Mut.Type (Array(..))
|
||||
import Streamly.Internal.Data.Fold.Type (Fold(..))
|
||||
|
@ -81,6 +81,7 @@ import Control.Exception (assert)
|
||||
import Control.Monad (replicateM)
|
||||
import Control.Monad.IO.Class (MonadIO(..))
|
||||
import Data.Functor.Identity (Identity(..))
|
||||
import Data.Proxy (Proxy(..))
|
||||
import Data.Word (Word8)
|
||||
import GHC.Base (build)
|
||||
import GHC.Exts (IsList, IsString(..))
|
||||
|
@ -309,6 +309,7 @@ import Data.Bifunctor (first)
|
||||
import Data.Bits (shiftL, shiftR, (.|.), (.&.))
|
||||
import Data.Either (isLeft, isRight, fromLeft, fromRight)
|
||||
import Data.Int (Int64)
|
||||
import Data.Proxy (Proxy(..))
|
||||
import Data.Word (Word32)
|
||||
import Foreign.Storable (Storable, peek)
|
||||
import Streamly.Internal.Data.Maybe.Strict (Maybe'(..), toMaybe)
|
||||
@ -1707,7 +1708,7 @@ takeEndBySeq patArr (Fold fstep finitial fextract) =
|
||||
| patLen == 1 -> do
|
||||
pat <- liftIO $ Array.unsafeIndexIO 0 patArr
|
||||
return $ Partial $ SplitOnSeqSingle acc pat
|
||||
| SIZE_OF(a) * patLen <= sizeOf (undefined :: Word) ->
|
||||
| SIZE_OF(a) * patLen <= sizeOf (Proxy :: Proxy Word) ->
|
||||
return $ Partial $ SplitOnSeqWord acc 0 0
|
||||
| otherwise -> do
|
||||
(rb, rhead) <- liftIO $ Ring.new patLen
|
||||
@ -1844,7 +1845,7 @@ takeEndBySeq_ patArr (Fold fstep finitial fextract) =
|
||||
pat <- liftIO $ Array.unsafeIndexIO 0 patArr
|
||||
return $ Partial $ SplitOnSeqSingle acc pat
|
||||
-- XXX Need to add tests for this case
|
||||
| SIZE_OF(a) * patLen <= sizeOf (undefined :: Word) ->
|
||||
| SIZE_OF(a) * patLen <= sizeOf (Proxy :: Proxy Word) ->
|
||||
return $ Partial $ SplitOnSeqWord acc 0 0
|
||||
| otherwise -> do
|
||||
(rb, rhead) <- liftIO $ Ring.new patLen
|
||||
|
@ -60,6 +60,7 @@ import Control.Applicative (liftA2)
|
||||
import Control.Exception (assert)
|
||||
import Control.Monad.IO.Class (MonadIO(..))
|
||||
import Data.Bifunctor (first)
|
||||
import Data.Proxy (Proxy(..))
|
||||
import Streamly.Internal.Data.Unboxed (peekWith, sizeOf, Unbox)
|
||||
import GHC.Types (SPEC(..))
|
||||
import Streamly.Internal.Data.Array.Mut.Type (touch)
|
||||
|
@ -38,6 +38,7 @@ where
|
||||
|
||||
#include "inline.hs"
|
||||
|
||||
import Data.Proxy (Proxy(..))
|
||||
import Control.Monad.IO.Class (MonadIO(..))
|
||||
import Streamly.Internal.Data.Unboxed
|
||||
( MutableByteArray(..)
|
||||
@ -59,7 +60,7 @@ newtype IORef a = IORef MutableByteArray
|
||||
{-# INLINE newIORef #-}
|
||||
newIORef :: forall a. Unbox a => a -> IO (IORef a)
|
||||
newIORef x = do
|
||||
var <- newUnpinnedBytes (sizeOf (undefined :: a))
|
||||
var <- newUnpinnedBytes (sizeOf (Proxy :: Proxy a))
|
||||
pokeWith var 0 x
|
||||
return $ IORef var
|
||||
|
||||
|
@ -37,6 +37,7 @@ where
|
||||
#include "inline.hs"
|
||||
|
||||
import Control.Monad.IO.Class (MonadIO(..))
|
||||
import Data.Proxy (Proxy(..))
|
||||
import GHC.Types (SPEC(..))
|
||||
import Streamly.Internal.Data.Array.Type (Array(..))
|
||||
import Streamly.Internal.Data.Parser.Chunked.Type (ChunkParser (..))
|
||||
|
@ -166,7 +166,7 @@ moveBy by Ring {..} ringHead = ringStartPtr `plusPtr` advanceFromHead
|
||||
|
||||
where
|
||||
|
||||
elemSize = SIZE_OF(a)
|
||||
elemSize = STORABLE_SIZE_OF(a)
|
||||
ringStartPtr = unsafeForeignPtrToPtr ringStart
|
||||
lenInBytes = ringBound `minusPtr` ringStartPtr
|
||||
offInBytes = ringHead `minusPtr` ringStartPtr
|
||||
@ -384,7 +384,7 @@ asBytes = castUnsafe
|
||||
cast :: forall a b. Storable b => Ring a -> Maybe (Ring b)
|
||||
cast arr =
|
||||
let len = byteLength arr
|
||||
r = len `mod` SIZE_OF(b)
|
||||
r = len `mod` STORABLE_SIZE_OF(b)
|
||||
in if r /= 0
|
||||
then Nothing
|
||||
else Just $ castUnsafe arr
|
||||
|
@ -53,6 +53,7 @@ where
|
||||
import Data.Bifunctor (second)
|
||||
import Control.Exception (assert)
|
||||
import Control.Monad.IO.Class (MonadIO(..))
|
||||
import Data.Proxy (Proxy(..))
|
||||
import Data.Word (Word8)
|
||||
import Streamly.Internal.Data.Unboxed (Unbox, peekWith, sizeOf)
|
||||
import Fusion.Plugin.Types (Fuse(..))
|
||||
|
@ -153,6 +153,7 @@ import Control.Exception (assert)
|
||||
import Control.Monad.IO.Class (MonadIO(..))
|
||||
import Data.Bits (shiftR, shiftL, (.|.), (.&.))
|
||||
import Data.Functor.Identity ( Identity )
|
||||
import Data.Proxy (Proxy(..))
|
||||
import Data.Word (Word32)
|
||||
import Foreign.Storable (Storable, peek)
|
||||
import Fusion.Plugin.Types (Fuse(..))
|
||||
@ -1961,7 +1962,7 @@ splitOnSeq patArr (Fold fstep initial done) (Stream step state) =
|
||||
pat <- liftIO $ A.unsafeIndexIO 0 patArr
|
||||
return $ Skip $ SplitOnSeqSingle acc state pat
|
||||
else if SIZE_OF(a) * patLen
|
||||
<= sizeOf (undefined :: Word)
|
||||
<= sizeOf (Proxy :: Proxy Word)
|
||||
then return $ Skip $ SplitOnSeqWordInit acc state
|
||||
else do
|
||||
(rb, rhead) <- liftIO $ RB.new patLen
|
||||
@ -2294,7 +2295,7 @@ splitOnSuffixSeq withSep patArr (Fold fstep initial done) (Stream step state) =
|
||||
pat <- liftIO $ A.unsafeIndexIO 0 patArr
|
||||
skip $ SplitOnSuffixSeqSingleInit fs state pat
|
||||
else if SIZE_OF(a) * patLen
|
||||
<= sizeOf (undefined :: Word)
|
||||
<= sizeOf (Proxy :: Proxy Word)
|
||||
then skip $ SplitOnSuffixSeqWordInit fs state
|
||||
else do
|
||||
(rb, rhead) <- liftIO $ RB.new patLen
|
||||
|
@ -178,7 +178,6 @@ unpin arr@(MutableByteArray marr#) =
|
||||
-- The Unbox type class
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
-- XXX Use Proxy type in sizeOf method.
|
||||
-- XXX generate error if the size is < 1
|
||||
|
||||
-- In theory we could convert a type to and from a byte stream and use that
|
||||
@ -257,10 +256,10 @@ unpin arr@(MutableByteArray marr#) =
|
||||
--
|
||||
class Unbox a where
|
||||
-- | Get the size.
|
||||
sizeOf :: a -> Int
|
||||
sizeOf :: Proxy a -> Int
|
||||
|
||||
default sizeOf :: (SizeOfRep (Rep a)) => a -> Int
|
||||
sizeOf _ = genericSizeOf (Proxy :: Proxy a)
|
||||
default sizeOf :: (SizeOfRep (Rep a)) => Proxy a -> Int
|
||||
sizeOf = genericSizeOf
|
||||
|
||||
-- | Read an element of type "a" from a MutableByteArray given the byte
|
||||
-- index.
|
||||
@ -449,7 +448,7 @@ instance Unbox IoSubSystem where
|
||||
pokeByteIndex i arr a = pokeByteIndex i arr (fromEnum a)
|
||||
|
||||
{-# INLINE sizeOf #-}
|
||||
sizeOf = sizeOf . fromEnum
|
||||
sizeOf _ = sizeOf (Proxy :: Proxy Int)
|
||||
#endif
|
||||
|
||||
instance Unbox Bool where
|
||||
@ -511,7 +510,7 @@ readUnsafe = Peeker (Builder step)
|
||||
{-# INLINE step #-}
|
||||
step :: forall a. Unbox a => BoundedPtr -> IO (BoundedPtr, a)
|
||||
step (BoundedPtr arr pos end) = do
|
||||
let next = pos + sizeOf (undefined :: a)
|
||||
let next = pos + sizeOf (Proxy :: Proxy a)
|
||||
r <- peekByteIndex pos arr
|
||||
return (BoundedPtr arr next end, r)
|
||||
|
||||
@ -524,7 +523,7 @@ read = Peeker (Builder step)
|
||||
{-# INLINE step #-}
|
||||
step :: forall a. Unbox a => BoundedPtr -> IO (BoundedPtr, a)
|
||||
step (BoundedPtr arr pos end) = do
|
||||
let next = pos + sizeOf (undefined :: a)
|
||||
let next = pos + sizeOf (Proxy :: Proxy a)
|
||||
when (next > end) $ error "peekObject reading beyond limit"
|
||||
r <- peekByteIndex pos arr
|
||||
return (BoundedPtr arr next end, r)
|
||||
@ -557,16 +556,16 @@ runPeeker (Peeker (Builder f)) ptr = fmap snd (f ptr)
|
||||
|
||||
-- Does not check writing beyond bound.
|
||||
{-# INLINE pokeBoundedPtrUnsafe #-}
|
||||
pokeBoundedPtrUnsafe :: Unbox a => a -> BoundedPtr -> IO BoundedPtr
|
||||
pokeBoundedPtrUnsafe :: forall a. Unbox a => a -> BoundedPtr -> IO BoundedPtr
|
||||
pokeBoundedPtrUnsafe a (BoundedPtr arr pos end) = do
|
||||
let next = pos + sizeOf a
|
||||
let next = pos + sizeOf (Proxy :: Proxy a)
|
||||
pokeByteIndex pos arr a
|
||||
return (BoundedPtr arr next end)
|
||||
|
||||
{-# INLINE pokeBoundedPtr #-}
|
||||
pokeBoundedPtr :: Unbox a => a -> BoundedPtr -> IO BoundedPtr
|
||||
pokeBoundedPtr :: forall a. Unbox a => a -> BoundedPtr -> IO BoundedPtr
|
||||
pokeBoundedPtr a (BoundedPtr arr pos end) = do
|
||||
let next = pos + sizeOf a
|
||||
let next = pos + sizeOf (Proxy :: Proxy a)
|
||||
when (next > end) $ error "pokeBoundedPtr writing beyond limit"
|
||||
pokeByteIndex pos arr a
|
||||
return (BoundedPtr arr next end)
|
||||
@ -615,7 +614,7 @@ instance SizeOfRep f => SizeOfRep (M1 i c f) where
|
||||
-- Primitive type "a".
|
||||
instance Unbox a => SizeOfRep (K1 i a) where
|
||||
{-# INLINE sizeOfRep #-}
|
||||
sizeOfRep _ = sizeOf (undefined :: a)
|
||||
sizeOfRep _ = sizeOf (Proxy :: Proxy a)
|
||||
|
||||
-- Void: data type without constructors. Values of this type cannot exist,
|
||||
-- therefore the size is undefined. We should never be serializing structures
|
||||
@ -671,7 +670,7 @@ instance (MaxArity256 (SumArity (f :+: g)), SizeOfRepSum f, SizeOfRepSum g) =>
|
||||
{-# INLINE sizeOfRep #-}
|
||||
sizeOfRep _ =
|
||||
-- One byte for the constructor id and then the constructor value.
|
||||
sizeOf (undefined :: Word8) +
|
||||
sizeOf (Proxy :: Proxy Word8) +
|
||||
max (sizeOfRepSum (undefined :: f x))
|
||||
(sizeOfRepSum (undefined :: g x))
|
||||
|
||||
|
@ -8,22 +8,23 @@
|
||||
--
|
||||
-- XXX Check the core to see if max can be statically eliminated. llvm can
|
||||
-- eliminate the comparison, but not sure if GHC NCG can.
|
||||
#define SIZE_OF(a) max 1 (sizeOf (undefined :: a))
|
||||
#define SIZE_OF(a) max 1 (sizeOf (Proxy :: Proxy a))
|
||||
#define STORABLE_SIZE_OF(a) max 1 (sizeOf (undefined :: a))
|
||||
|
||||
-- Move the pointer to ith element of specified type. Type is specified as the
|
||||
-- type variable in the signature of the function where this macro is used.
|
||||
#define PTR_NEXT(ptr,a) ptr `plusPtr` SIZE_OF(a)
|
||||
#define PTR_PREV(ptr,a) ptr `plusPtr` negate (SIZE_OF(a))
|
||||
#define PTR_NEXT(ptr,a) ptr `plusPtr` STORABLE_SIZE_OF(a)
|
||||
#define PTR_PREV(ptr,a) ptr `plusPtr` negate (STORABLE_SIZE_OF(a))
|
||||
|
||||
#define PTR_INDEX(ptr,i,a) ptr `plusPtr` (SIZE_OF(a) * i)
|
||||
#define PTR_RINDEX(ptr,i,a) ptr `plusPtr` negate (SIZE_OF(a) * (i + 1))
|
||||
#define PTR_INDEX(ptr,i,a) ptr `plusPtr` (STORABLE_SIZE_OF(a) * i)
|
||||
#define PTR_RINDEX(ptr,i,a) ptr `plusPtr` negate (STORABLE_SIZE_OF(a) * (i + 1))
|
||||
|
||||
-- XXX If we know that the array is guaranteed to have size multiples of the
|
||||
-- element size then we can use a simpler check saying "ptr < end". Since we
|
||||
-- always allocate in multiples of elem we can use the simpler check and assert
|
||||
-- the rigorous check.
|
||||
#define PTR_VALID(ptr,end,a) ptr `plusPtr` SIZE_OF(a) <= end
|
||||
#define PTR_INVALID(ptr,end,a) ptr `plusPtr` SIZE_OF(a) > end
|
||||
#define PTR_VALID(ptr,end,a) ptr `plusPtr` STORABLE_SIZE_OF(a) <= end
|
||||
#define PTR_INVALID(ptr,end,a) ptr `plusPtr` STORABLE_SIZE_OF(a) > end
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- Macros to access array indices
|
||||
|
@ -10,6 +10,7 @@ module Streamly.Test.Data.Array (main) where
|
||||
|
||||
import Data.Char (isLower)
|
||||
import Data.List (sort)
|
||||
import Data.Proxy (Proxy(..))
|
||||
import Data.Word(Word8)
|
||||
import Foreign.Storable (peek)
|
||||
import GHC.Ptr (plusPtr)
|
||||
@ -196,7 +197,7 @@ testAsPtrUnsafeMA = do
|
||||
|
||||
where
|
||||
|
||||
sizeOfInt = sizeOf (undefined :: Int)
|
||||
sizeOfInt = sizeOf (Proxy :: Proxy Int)
|
||||
|
||||
-- We need to be careful here. We assume Unboxed and Storable are compatible
|
||||
-- with each other. For Int, they are compatible.
|
||||
@ -210,7 +211,7 @@ testAsPtrUnsafeMA = do
|
||||
reallocMA :: Property
|
||||
reallocMA =
|
||||
let len = 10000
|
||||
bSize = len * sizeOf (undefined :: Char)
|
||||
bSize = len * sizeOf (Proxy :: Proxy Char)
|
||||
in forAll (vectorOf len (arbitrary :: Gen Char)) $ \vec ->
|
||||
forAll (chooseInt (bSize - 2000, bSize + 2000)) $ \newBLen -> do
|
||||
arr <- MA.fromList vec
|
||||
|
@ -8,7 +8,7 @@ maxTestCount = 10
|
||||
#endif
|
||||
|
||||
allocOverhead :: Int
|
||||
allocOverhead = 2 * sizeOf (undefined :: Int)
|
||||
allocOverhead = 16
|
||||
|
||||
-- XXX this should be in sync with the defaultChunkSize in Array code, or we
|
||||
-- should expose that and use that. For fast testing we could reduce the
|
||||
|
@ -1,6 +1,4 @@
|
||||
|
||||
import Streamly.Internal.Data.Unboxed (sizeOf)
|
||||
|
||||
import Test.Hspec.QuickCheck
|
||||
import Test.QuickCheck (Property, forAll, Gen, vectorOf, arbitrary, choose)
|
||||
import Test.QuickCheck.Monadic (monadicIO, assert, run)
|
||||
|
@ -48,7 +48,7 @@ test v1 v2 = monadicIO $ do
|
||||
|
||||
checkSizeOf :: forall a. Unbox a => Proxy a -> Int -> Property
|
||||
checkSizeOf _ size = monadicIO $
|
||||
assert (sizeOf (undefined :: a) == size)
|
||||
assert (sizeOf (Proxy :: Proxy a) == size)
|
||||
|
||||
moduleName :: String
|
||||
moduleName = "Data.Unbox"
|
||||
|
@ -9,6 +9,7 @@
|
||||
module Streamly.Test.FileSystem.Handle (main) where
|
||||
|
||||
import Data.Functor.Identity (runIdentity)
|
||||
import Data.Proxy (Proxy(..))
|
||||
import Data.Word (Word8)
|
||||
import Streamly.Internal.Data.Unboxed (sizeOf)
|
||||
import Streamly.Internal.Data.Stream (Stream)
|
||||
@ -36,7 +37,7 @@ import Test.Hspec as H
|
||||
import Test.Hspec.QuickCheck
|
||||
|
||||
allocOverhead :: Int
|
||||
allocOverhead = 2 * sizeOf (undefined :: Int)
|
||||
allocOverhead = 2 * sizeOf (Proxy :: Proxy Int)
|
||||
|
||||
defaultChunkSize :: Int
|
||||
defaultChunkSize = 32 * k - allocOverhead
|
||||
|
Loading…
Reference in New Issue
Block a user