summaryrefslogtreecommitdiff
path: root/compiler/utils/FastString.hs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/utils/FastString.hs')
-rw-r--r--compiler/utils/FastString.hs35
1 files changed, 17 insertions, 18 deletions
diff --git a/compiler/utils/FastString.hs b/compiler/utils/FastString.hs
index f16b32779f..6ca3043668 100644
--- a/compiler/utils/FastString.hs
+++ b/compiler/utils/FastString.hs
@@ -18,7 +18,7 @@
--
-- ['LitString']
--
--- * Just a wrapper for the @Addr#@ of a C string (@Ptr CChar@).
+-- * Pointer and size of a Latin-1 encoded string.
-- * Practically no operations.
-- * Outputing them is fast.
-- * Generated by 'sLit'.
@@ -81,7 +81,7 @@ module FastString
hasZEncoding,
-- * LitStrings
- LitString,
+ LitString (..),
-- ** Construction
sLit,
@@ -130,7 +130,7 @@ import Foreign
import GHC.Conc.Sync (sharedCAF)
#endif
-import GHC.Base ( unpackCString# )
+import GHC.Base ( unpackCString#, unpackNBytes# )
#define hASH_TBL_SIZE 4091
#define hASH_TBL_SIZE_UNBOXED 4091#
@@ -227,7 +227,7 @@ cmpFS f1@(FastString u1 _ _ _) f2@(FastString u2 _ _ _) =
if u1 == u2 then EQ else
compare (fastStringToByteString f1) (fastStringToByteString f2)
-foreign import ccall unsafe "ghc_memcmp"
+foreign import ccall unsafe "memcmp"
memcmp :: Ptr a -> Ptr b -> Int -> IO Int
-- -----------------------------------------------------------------------------
@@ -568,15 +568,12 @@ hPutFS handle fs = BS.hPut handle $ fastStringToByteString fs
-- -----------------------------------------------------------------------------
-- LitStrings, here for convenience only.
--- | A 'LitString' is a pointer to some null-terminated array of bytes.
-type LitString = Ptr Word8
---Why do we recalculate length every time it's requested?
---If it's commonly needed, we should perhaps have
---data LitString = LitString {-#UNPACK#-}!Addr# {-#UNPACK#-}!Int#
+-- | A 'LitString' is a pointer to some array of Latin-1 encoded chars.
+data LitString = LitString !(Ptr Word8) !Int
-- | Wrap an unboxed address into a 'LitString'.
mkLitString# :: Addr# -> LitString
-mkLitString# a# = Ptr a#
+mkLitString# a# = LitString (Ptr a#) (ptrStrLength (Ptr a#))
-- | Encode a 'String' into a newly allocated 'LitString' using Latin-1
-- encoding. The original string must not contain non-Latin-1 characters
@@ -584,32 +581,34 @@ mkLitString# a# = Ptr a#
{-# INLINE mkLitString #-}
mkLitString :: String -> LitString
mkLitString s =
+ -- we don't use `unsafeDupablePerformIO` here to avoid potential memory leaks
+ -- and because someone might be using `eqAddr#` to check for string equality.
unsafePerformIO (do
- p <- mallocBytes (length s + 1)
+ let len = length s
+ p <- mallocBytes len
let
loop :: Int -> String -> IO ()
- loop !n [] = pokeByteOff p n (0 :: Word8)
+ loop !_ [] = return ()
loop n (c:cs) = do
pokeByteOff p n (fromIntegral (ord c) :: Word8)
loop (1+n) cs
loop 0 s
- return p
+ return (LitString p len)
)
-- | Decode a 'LitString' back into a 'String' using Latin-1 encoding.
-- This does not free the memory associated with 'LitString'.
unpackLitString :: LitString -> String
-unpackLitString (Ptr p) = unpackCString# p
+unpackLitString (LitString (Ptr p#) (I# n#)) = unpackNBytes# p# n#
--- | Compute the length of a 'LitString', which must necessarily be
--- null-terminated.
+-- | Return the length of a 'LitString'
lengthLS :: LitString -> Int
-lengthLS = ptrStrLength
+lengthLS (LitString _ n) = n
-- -----------------------------------------------------------------------------
-- under the carpet
-foreign import ccall unsafe "ghc_strlen"
+foreign import ccall unsafe "strlen"
ptrStrLength :: Ptr Word8 -> Int
{-# NOINLINE sLit #-}