diff options
author | Sylvain Henry <sylvain@haskus.fr> | 2021-01-26 20:29:48 +0100 |
---|---|---|
committer | Marge Bot <ben+marge-bot@smart-cactus.org> | 2021-01-29 04:05:27 -0500 |
commit | ae8379abb8aa1defc86dc60bece70546d42af177 (patch) | |
tree | 7bf89867b75104631822fb1ab68dd4b7253b4875 /compiler | |
parent | 75accd548d245eda3096a1fa92a0f246a396b81f (diff) | |
download | haskell-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).
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/GHC/Data/FastString.hs | 11 |
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 |