[commit: packages/bytestring] ghc-head: Fix the rewrite rule that optimizes packing of string literals (794c345)
git at git.haskell.org
git at git.haskell.org
Thu Aug 29 10:19:00 CEST 2013
Repository : ssh://git@git.haskell.org/bytestring
On branch : ghc-head
Link : http://git.haskell.org/?p=packages/bytestring.git;a=commit;h=794c3459f8b6469bdc5c0a08f101696bf277ae65
>---------------------------------------------------------------
commit 794c3459f8b6469bdc5c0a08f101696bf277ae65
Author: Patrick Palka <patrick at parcs.ath.cx>
Date: Fri Mar 1 18:20:05 2013 -0500
Fix the rewrite rule that optimizes packing of string literals
This patch addresses two issues:
1) The particular rule was guarded under the wrong CPP conditional
#if !defined(__GLASGOW_HASKELL__)
...
#endif
so GHC never even knew about it!
2) The rule didn't apply to ByteStrings that were implicitly packed
via OverloadedStrings.
So now the RULE is properly guarded and applied earlier (or later,
depending how you look at it). Specifically, the rule changed from
forall s.
pack (unpackCString# s) = inlinePerfomIO (unsafePackAddress s)
-- defined in Data.ByteString.Char8
to
forall s.
packChars (unpackCString# s) = inlinePerfomIO (unsafePackAddress s)
-- defined in Data.ByteString.Internal
To achieve this, the definition of 'unsafePackAddress' had to be
moved from the .Unsafe module to the .Internal module.
>---------------------------------------------------------------
794c3459f8b6469bdc5c0a08f101696bf277ae65
Data/ByteString/Char8.hs | 11 +----------
Data/ByteString/Internal.hs | 27 ++++++++++++++++++++++++++-
Data/ByteString/Unsafe.hs | 8 +-------
3 files changed, 28 insertions(+), 18 deletions(-)
diff --git a/Data/ByteString/Char8.hs b/Data/ByteString/Char8.hs
index 6bad28e..9e710d9 100644
--- a/Data/ByteString/Char8.hs
+++ b/Data/ByteString/Char8.hs
@@ -284,16 +284,7 @@ singleton = B.singleton . c2w
-- bottleneck.
pack :: String -> ByteString
pack = packChars
-
-#if !defined(__GLASGOW_HASKELL__)
-{-# INLINE [1] pack #-}
-
-{-# RULES
-"ByteString pack/packAddress" forall s .
- pack (unpackCString# s) = inlinePerformIO (B.unsafePackAddress s)
- #-}
-
-#endif
+{-# INLINE pack #-}
-- | /O(n)/ Converts a 'ByteString' to a 'String'.
unpack :: ByteString -> [Char]
diff --git a/Data/ByteString/Internal.hs b/Data/ByteString/Internal.hs
index ed8e459..c48c693 100644
--- a/Data/ByteString/Internal.hs
+++ b/Data/ByteString/Internal.hs
@@ -32,6 +32,7 @@ module Data.ByteString.Internal (
packChars, packUptoLenChars, unsafePackLenChars,
unpackBytes, unpackAppendBytesLazy, unpackAppendBytesStrict,
unpackChars, unpackAppendCharsLazy, unpackAppendCharsStrict,
+ unsafePackAddr,
-- * Low level imperative construction
create, -- :: Int -> (Ptr Word8 -> IO ()) -> IO ByteString
@@ -112,6 +113,8 @@ import Data.Generics (Data(..), mkNorepType)
#ifdef __GLASGOW_HASKELL__
import GHC.Base (realWorld#,unsafeChr)
+import GHC.CString (unpackCString#)
+import GHC.Prim (Addr#)
#if __GLASGOW_HASKELL__ >= 611
import GHC.IO (IO(IO))
#else
@@ -128,7 +131,8 @@ import System.IO.Unsafe (unsafePerformIO)
#endif
#ifdef __GLASGOW_HASKELL__
-import GHC.ForeignPtr (mallocPlainForeignPtrBytes)
+import GHC.ForeignPtr (newForeignPtr_, mallocPlainForeignPtrBytes)
+import GHC.Ptr (Ptr(..), castPtr)
#else
import Foreign.ForeignPtr (mallocForeignPtrBytes)
#endif
@@ -226,6 +230,15 @@ packBytes ws = unsafePackLenBytes (List.length ws) ws
packChars :: [Char] -> ByteString
packChars cs = unsafePackLenChars (List.length cs) cs
+#if defined(__GLASGOW_HASKELL__)
+{-# INLINE [0] packChars #-}
+
+{-# RULES
+"ByteString packChars/packAddress" forall s .
+ packChars (unpackCString# s) = inlinePerformIO (unsafePackAddr s)
+ #-}
+#endif
+
unsafePackLenBytes :: Int -> [Word8] -> ByteString
unsafePackLenBytes len xs0 =
unsafeCreate len $ \p -> go p xs0
@@ -240,6 +253,18 @@ unsafePackLenChars len cs0 =
go !_ [] = return ()
go !p (c:cs) = poke p (c2w c) >> go (p `plusPtr` 1) cs
+#if defined(__GLASGOW_HASKELL__)
+unsafePackAddr :: Addr# -> IO ByteString
+unsafePackAddr addr# = do
+ p <- newForeignPtr_ (castPtr cstr)
+ l <- c_strlen cstr
+ return $ PS p 0 (fromIntegral l)
+ where
+ cstr :: CString
+ cstr = Ptr addr#
+{-# INLINE unsafePackAddr #-}
+#endif
+
packUptoLenBytes :: Int -> [Word8] -> (ByteString, [Word8])
packUptoLenBytes len xs0 =
unsafeCreateUptoN' len $ \p -> go p len xs0
diff --git a/Data/ByteString/Unsafe.hs b/Data/ByteString/Unsafe.hs
index 242e366..6f8f7de 100644
--- a/Data/ByteString/Unsafe.hs
+++ b/Data/ByteString/Unsafe.hs
@@ -172,13 +172,7 @@ unsafeDrop n (PS x s l) = assert (0 <= n && n <= l) $ PS x (s+n) (l-n)
-- the string (strlen will fail).
--
unsafePackAddress :: Addr# -> IO ByteString
-unsafePackAddress addr# = do
- p <- newForeignPtr_ (castPtr cstr)
- l <- c_strlen cstr
- return $ PS p 0 (fromIntegral l)
- where
- cstr :: CString
- cstr = Ptr addr#
+unsafePackAddress = unsafePackAddr
{-# INLINE unsafePackAddress #-}
-- | /O(1)/ 'unsafePackAddressLen' provides constant-time construction of
More information about the ghc-commits
mailing list