Commit 2987b041 authored by Tao He's avatar Tao He Committed by Ben Gamari

Improve X86CodeGen's pprASCII.

The original implementation generates a list of SDoc then concatenates
them using `hcat`. For memory optimization, we can transform the given
literal string into escaped string the construct SDoc directly.

This optimization will decreate the memory allocation when there's big
literal strings in haskell code, see Trac #14741.
Signed-off-by: Tao He's avatarHE, Tao <sighingnow@gmail.com>

Reviewers: bgamari, mpickering, simonpj

Reviewed By: simonpj

Subscribers: simonpj, rwbarton, thomie, carter

GHC Trac Issues: #14741

Differential Revision: https://phabricator.haskell.org/D4384
parent 4c364402
......@@ -175,23 +175,44 @@ pprLabel lbl = pprGloblDecl lbl
$$ pprTypeAndSizeDecl lbl
$$ (ppr lbl <> char ':')
{-
Note [Pretty print ASCII when AsmCodeGen]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Previously, when generating assembly code, we created SDoc with
`(ptext . sLit)` for every bytes in literal bytestring, then
combine them using `hcat`.
When handling literal bytestrings with millions of bytes,
millions of SDoc would be created and to combine, leading to
high memory usage.
Now we escape the given bytestring to string directly and construct
SDoc only once. This improvement could dramatically decrease the
memory allocation from 4.7GB to 1.3GB when embedding a 3MB literal
string in source code. See Trac #14741 for profiling results.
-}
pprASCII :: [Word8] -> SDoc
pprASCII str
= hcat (map (do1 . fromIntegral) str)
-- Transform this given literal bytestring to escaped string and construct
-- the literal SDoc directly.
-- See Trac #14741
-- and Note [Pretty print ASCII when AsmCodeGen]
= ptext $ sLit $ foldr (\w s -> (do1 . fromIntegral) w ++ s) "" str
where
do1 :: Int -> SDoc
do1 w | '\t' <- chr w = ptext (sLit "\\t")
do1 w | '\n' <- chr w = ptext (sLit "\\n")
do1 w | '"' <- chr w = ptext (sLit "\\\"")
do1 w | '\\' <- chr w = ptext (sLit "\\\\")
do1 w | isPrint (chr w) = char (chr w)
do1 w | otherwise = char '\\' <> octal w
octal :: Int -> SDoc
octal w = int ((w `div` 64) `mod` 8)
<> int ((w `div` 8) `mod` 8)
<> int (w `mod` 8)
do1 :: Int -> String
do1 w | '\t' <- chr w = "\\t"
| '\n' <- chr w = "\\n"
| '"' <- chr w = "\\\""
| '\\' <- chr w = "\\\\"
| isPrint (chr w) = [chr w]
| otherwise = '\\' : octal w
octal :: Int -> String
octal w = [ chr (ord '0' + (w `div` 64) `mod` 8)
, chr (ord '0' + (w `div` 8) `mod` 8)
, chr (ord '0' + w `mod` 8)
]
pprAlign :: Int -> SDoc
pprAlign bytes
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment