#undef DEBUG_DUMP
-- -----------------------------------------------------------------------------
--- $Id: PrelIO.hsc,v 1.13 2001/09/17 14:58:09 simonmar Exp $
+-- $Id: PrelIO.hsc,v 1.16 2001/09/18 08:32:11 simonmar Exp $
--
-- (c) The University of Glasgow, 1992-2001
--
putChar, putStr, putStrLn, print, getChar, getLine, getContents,
interact, readFile, writeFile, appendFile, readLn, readIO, hReady,
hWaitForInput, hGetChar, hGetLine, hGetContents, hPutChar, hPutStr,
- hPutStrLn, hPrint
+ hPutStrLn, hPrint,
+ commitBuffer', -- hack, see below
+ hGetcBuffered, -- needed by ghc/compiler/utils/StringBuffer.lhs
) where
#include "HsStd.h"
:: Handle -- handle to commit to
-> RawBuffer -> Int -- address and size (in bytes) of buffer
-> Int -- number of bytes of data in buffer
- -> Bool -- flush the handle afterward?
+ -> Bool -- True <=> flush the handle afterward
-> Bool -- release the buffer?
-> IO Buffer
-commitBuffer hdl raw sz count flush release = do
- wantWritableHandle "commitAndReleaseBuffer" hdl $
- \ handle_@Handle__{ haFD=fd, haBuffer=ref, haBuffers=spare_buf_ref } -> do
+commitBuffer hdl raw sz@(I## _) count@(I## _) flush release = do
+ wantWritableHandle "commitAndReleaseBuffer" hdl $
+ commitBuffer' hdl raw sz count flush release
+
+-- Explicitly lambda-lift this function to subvert GHC's full laziness
+-- optimisations, which otherwise tends to float out subexpressions
+-- past the \handle, which is really a pessimisation in this case because
+-- that lambda is a one-shot lambda.
+--
+-- Don't forget to export the function, to stop it being inlined too
+-- (this appears to be better than NOINLINE, because the strictness
+-- analyser still gets to worker-wrapper it).
+--
+-- This hack is a fairly big win for hPutStr performance. --SDM 18/9/2001
+--
+commitBuffer' hdl raw sz@(I## _) count@(I## _) flush release
+ handle_@Handle__{ haFD=fd, haBuffer=ref, haBuffers=spare_buf_ref } = do
#ifdef DEBUG_DUMP
puts ("commitBuffer: sz=" ++ show sz ++ ", count=" ++ show count
else allocateBuffer size WriteBuffer
-- release the buffer if necessary
- if release && bufSize buf_ret == size
- then do
+ case buf_ret of
+ Buffer{ bufSize=buf_ret_sz, bufBuf=buf_ret_raw } -> do
+ if release && buf_ret_sz == size
+ then do
spare_bufs <- readIORef spare_buf_ref
writeIORef spare_buf_ref
- (BufferListCons (bufBuf buf_ret) spare_bufs)
+ (BufferListCons buf_ret_raw spare_bufs)
return buf_ret
- else
+ else
return buf_ret