summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSylvain Henry <sylvain@haskus.fr>2021-01-26 20:29:48 +0100
committerMarge Bot <ben+marge-bot@smart-cactus.org>2021-01-29 04:05:27 -0500
commitae8379abb8aa1defc86dc60bece70546d42af177 (patch)
tree7bf89867b75104631822fb1ab68dd4b7253b4875
parent75accd548d245eda3096a1fa92a0f246a396b81f (diff)
downloadhaskell-ae8379abb8aa1defc86dc60bece70546d42af177.tar.gz
Ppr: compute length of string literals at compile time (#19266)
SDoc string literals created for example with `text "xyz"` are converted into `PtrString` (`Addr#` + size in bytes) with a rewrite rule to avoid allocating a String. Before this patch, the size in bytes was still computed at runtime. For every literal, we obtained the following pseudo STG: x :: Addr# x = "xzy"# s :: PtrString s = \u [] case ffi:strlen [x realWorld#] of (# _, sz #) -> PtrString [x sz] But since GHC 9.0, we can use `cstringLength#` instead to get: x :: Addr# x = "xzy"# s :: PtrString s = PtrString! [x 3#] Literals become statically known constructor applications. Allocations seem to decrease a little in perf tests (between -0.1% and -0.7% on CI).
-rw-r--r--compiler/GHC/Data/FastString.hs11
1 files changed, 10 insertions, 1 deletions
diff --git a/compiler/GHC/Data/FastString.hs b/compiler/GHC/Data/FastString.hs
index 0f6a26f75e..90d1c61594 100644
--- a/compiler/GHC/Data/FastString.hs
+++ b/compiler/GHC/Data/FastString.hs
@@ -6,6 +6,7 @@
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE UnboxedTuples #-}
+{-# LANGUAGE UnliftedFFITypes #-}
{-# OPTIONS_GHC -O2 -funbox-strict-fields #-}
-- We always optimise this, otherwise performance of a non-optimised
@@ -425,6 +426,7 @@ lower-level `sharedCAF` mechanism that relies on Globals.c.
-}
mkFastString# :: Addr# -> FastString
+{-# INLINE mkFastString# #-}
mkFastString# a# = mkFastStringBytes ptr (ptrStrLength ptr)
where ptr = Ptr a#
@@ -653,6 +655,7 @@ data PtrString = PtrString !(Ptr Word8) !Int
-- | Wrap an unboxed address into a 'PtrString'.
mkPtrString# :: Addr# -> PtrString
+{-# INLINE mkPtrString# #-}
mkPtrString# a# = PtrString (Ptr a#) (ptrStrLength (Ptr a#))
-- | Encode a 'String' into a newly allocated 'PtrString' using Latin-1
@@ -688,8 +691,14 @@ lengthPS (PtrString _ n) = n
-- -----------------------------------------------------------------------------
-- under the carpet
+#if !MIN_VERSION_GLASGOW_HASKELL(9,0,0,0)
foreign import ccall unsafe "strlen"
- ptrStrLength :: Ptr Word8 -> Int
+ cstringLength# :: Addr# -> Int#
+#endif
+
+ptrStrLength :: Ptr Word8 -> Int
+{-# INLINE ptrStrLength #-}
+ptrStrLength (Ptr a) = I# (cstringLength# a)
{-# NOINLINE sLit #-}
sLit :: String -> PtrString