Commit 4ad9ffd3 authored by Peter Trommler's avatar Peter Trommler 🥁

PPC NCG: Reduce memory consumption emitting string literals

parent a34ee615
......@@ -125,12 +125,9 @@ pprDatas :: CmmStatics -> SDoc
pprDatas (Statics lbl dats) = vcat (pprLabel lbl : map pprData dats)
pprData :: CmmStatic -> SDoc
pprData (CmmString str) = pprASCII str
pprData (CmmUninitialised bytes) = keyword <> int bytes
where keyword = sdocWithPlatform $ \platform ->
case platformOS platform of
OSAIX -> text ".space "
_ -> text ".skip "
pprData (CmmString str)
= text "\t.string" <+> doubleQuotes (pprASCII str)
pprData (CmmUninitialised bytes) = text ".space " <> int bytes
pprData (CmmStaticLit lit) = pprDataItem lit
pprGloblDecl :: CLabel -> SDoc
......@@ -151,15 +148,6 @@ pprLabel lbl = pprGloblDecl lbl
$$ pprTypeAndSizeDecl lbl
$$ (ppr lbl <> char ':')
pprASCII :: [Word8] -> SDoc
pprASCII str
= vcat (map do1 str) $$ do1 0
where
do1 :: Word8 -> SDoc
do1 w = text "\t.byte\t" <> int (fromIntegral w)
-- -----------------------------------------------------------------------------
-- pprInstr: print an 'Instr'
......
......@@ -11,6 +11,7 @@ module PprBase (
castDoubleToWord8Array,
floatToBytes,
doubleToBytes,
pprASCII,
pprSectionHeader
)
......@@ -32,6 +33,7 @@ import Data.Array.ST
import Control.Monad.ST
import Data.Word
import Data.Char
......@@ -82,6 +84,51 @@ doubleToBytes d
return (map fromIntegral [i0,i1,i2,i3,i4,i5,i6,i7])
)
-- ---------------------------------------------------------------------------
-- Printing ASCII strings.
--
-- Print as a string and escape non-printable characters.
-- This is similar to charToC in Utils.
pprASCII :: [Word8] -> SDoc
pprASCII 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]
= text $ foldr (\w s -> (do1 . fromIntegral) w ++ s) "" str
where
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)
]
{-
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.
-}
-- ----------------------------------------------------------------------------
-- Printing section headers.
--
......
......@@ -109,7 +109,11 @@ pprDatas :: CmmStatics -> SDoc
pprDatas (Statics lbl dats) = vcat (pprLabel lbl : map pprData dats)
pprData :: CmmStatic -> SDoc
pprData (CmmString str) = pprASCII str
pprData (CmmString str)
= vcat (map do1 str) $$ do1 0
where
do1 :: Word8 -> SDoc
do1 w = text "\t.byte\t" <> int (fromIntegral w)
pprData (CmmUninitialised bytes) = text ".skip " <> int bytes
pprData (CmmStaticLit lit) = pprDataItem lit
......@@ -130,15 +134,6 @@ pprLabel lbl = pprGloblDecl lbl
$$ pprTypeAndSizeDecl lbl
$$ (ppr lbl <> char ':')
pprASCII :: [Word8] -> SDoc
pprASCII str
= vcat (map do1 str) $$ do1 0
where
do1 :: Word8 -> SDoc
do1 w = text "\t.byte\t" <> int (fromIntegral w)
-- -----------------------------------------------------------------------------
-- pprInstr: print an 'Instr'
......
......@@ -48,8 +48,6 @@ import Outputable
import Data.Word
import Data.Char
import Data.Bits
-- -----------------------------------------------------------------------------
......@@ -243,45 +241,6 @@ pprLabel lbl = pprGloblDecl lbl
$$ pprTypeDecl 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
-- 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 -> 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
= sdocWithPlatform $ \platform ->
......
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