on master help sign in
warp : Move the MagicHash version of the readInt64 function to its own file.

This was needed to prevent a nasty interaction (incorrect code being generated) when the CPP and MagicHash pragmas were used in the same file.

commit16c646943c8de8307b22faaf5f979d61e95f8624 authorErik de Castro Lopo <erikd@mega-nerd.com> dateTue 24 Jan 2012, 17:31 (15 years ago) parent19c31e4
2 files changed+61−43
warp/Network/Wai/Handler/Warp.hs+3−43 warp/ReadInt.hs+58
warp/Network/Wai/Handler/Warp.hs+3−43
@@ -84,7 +84,6 @@ import Control.Exception
8484 , bracketOnError
8585 )
8686import Control.Concurrent (forkIO)
87−import qualified Data.Char as C
8887import Data.Maybe (fromMaybe, isJust)
8988
9089import Data.Typeable (Typeable)
@@ -114,9 +113,8 @@ import Control.Monad (forever, when)
114113import qualified Network.HTTP.Types as H
115114import qualified Data.CaseInsensitive as CI
116115import System.IO (hPutStrLn, stderr)
117−import Data.Int (Int64)
118−import GHC.Prim
119−import GHC.Types
116+import ReadInt (readInt64)
117+
120118
121119#if WINDOWS
122120import Control.Concurrent (threadDelay)
@@ -651,48 +649,10 @@ checkCR bs pos =
651649 else pos
652650{-# INLINE checkCR #-}
653651
654−-- This function is used to parse the Content-Length field of HTTP headers and
655−-- is a performance hot spot. It should only be replaced with something
656−-- significantly and provably faster.
657−-- It needs to be able work correctly on 32 bit CPUs for file sizes > 2G so we
658−-- use Int64 here and then make a generic 'readInt' that allows conversion to
659−-- Int and Integer.
660652readInt :: Integral a => ByteString -> a
661−readInt s = fromIntegral $ readInt64MH s
662− where
663− readInt64MH :: ByteString -> Int64
664− readInt64MH bs =
665− B.foldl' (\i c -> i * 10 + fromIntegral (mhDigitToInt c)) 0
666− $ B.takeWhile C.isDigit bs
653+readInt bs = fromIntegral $ readInt64 bs
667654{-# INLINE readInt #-}
668655
669−data Table = Table !Addr#
670−
671−mhDigitToInt :: Char -> Int
672−mhDigitToInt (C# i) = I# (word2Int# $ indexWord8OffAddr# addr (ord# i))
673− where
674− !(Table addr) = table
675− table :: Table
676− table = Table
677− "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
678− \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
679− \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
680− \\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x00\x00\x00\x00\x00\x00\
681− \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
682− \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
683− \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
684− \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
685− \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
686− \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
687− \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
688− \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
689− \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
690− \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
691− \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
692− \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"#
693−
694−
695−
696656
697657-- | Call the inner function with a timeout manager.
698658withManager :: Int -- ^ timeout in microseconds
warp/ReadInt.hsnew file+58
@@ -0,0 +1,58 @@
1+{-# LANGUAGE OverloadedStrings, MagicHash, BangPatterns #-}
2+
3+-- Copyright : Erik de Castro Lopo <erikd@mega-nerd.com>
4+-- License : BSD3
5+
6+module ReadInt (readInt64) where
7+
8+-- This function lives in its own file because the MagicHash pragma interacts
9+-- poorly with the CPP pragma.
10+
11+import Data.ByteString (ByteString)
12+import Data.Int (Int64)
13+import GHC.Prim
14+import GHC.Types
15+
16+import qualified Data.ByteString.Char8 as B
17+import qualified Data.Char as C
18+
19+-- This function is used to parse the Content-Length field of HTTP headers and
20+-- is a performance hot spot. It should only be replaced with something
21+-- significantly and provably faster.
22+--
23+-- It needs to be able work correctly on 32 bit CPUs for file sizes > 2G so we
24+-- use Int64 here and then make a generic 'readInt' that allows conversion to
25+-- Int and Integer.
26+
27+readInt64 :: ByteString -> Int64
28+readInt64 bs =
29+ B.foldl' (\i c -> i * 10 + fromIntegral (mhDigitToInt c)) 0
30+ $ B.takeWhile C.isDigit bs
31+{- NOINLINE readInt64MH #-}
32+
33+data Table = Table !Addr#
34+
35+{- NOINLINE mhDigitToInt #-}
36+mhDigitToInt :: Char -> Int
37+mhDigitToInt (C# i) = I# (word2Int# $ indexWord8OffAddr# addr (ord# i))
38+ where
39+ !(Table addr) = table
40+ table :: Table
41+ table = Table
42+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
43+ \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
44+ \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
45+ \\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x00\x00\x00\x00\x00\x00\
46+ \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
47+ \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
48+ \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
49+ \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
50+ \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
51+ \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
52+ \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
53+ \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
54+ \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
55+ \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
56+ \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
57+ \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"#
58+