[project @ 2001-09-18 08:32:11 by simonmar]
[ghc-hetmet.git] / ghc / lib / std / PrelIO.hsc
index ab06b78..67f909b 100644 (file)
@@ -3,7 +3,7 @@
 #undef DEBUG_DUMP
 
 -- -----------------------------------------------------------------------------
--- $Id: PrelIO.hsc,v 1.12 2001/09/14 14:51:06 simonmar Exp $
+-- $Id: PrelIO.hsc,v 1.16 2001/09/18 08:32:11 simonmar Exp $
 --
 -- (c) The University of Glasgow, 1992-2001
 --
 -- but as it happens they also do everything required by library
 -- module IO.
 
-module PrelIO where
+module PrelIO ( 
+   putChar, putStr, putStrLn, print, getChar, getLine, getContents,
+   interact, readFile, writeFile, appendFile, readLn, readIO, hReady,
+   hWaitForInput, hGetChar, hGetLine, hGetContents, hPutChar, hPutStr,
+   hPutStrLn, hPrint,
+   commitBuffer',      -- hack, see below
+   hGetcBuffered,      -- needed by ghc/compiler/utils/StringBuffer.lhs
+ ) where
 
 #include "HsStd.h"
 #include "PrelHandle_hsc.h"
@@ -491,7 +498,7 @@ writeLines hdl Buffer{ bufBuf=raw, bufSize=len } s =
        -- check n == len first, to ensure that shoveString is strict in n.
    shoveString n cs | n == len = do
        new_buf <- commitBuffer hdl raw len n True{-needs flush-} False
-       writeBlocks hdl new_buf cs
+       writeLines hdl new_buf cs
    shoveString n [] = do
        commitBuffer hdl raw len n False{-no flush-} True{-release-}
        return ()
@@ -500,7 +507,7 @@ writeLines hdl Buffer{ bufBuf=raw, bufSize=len } s =
        if (c == '\n') 
           then do 
                new_buf <- commitBuffer hdl raw len n' True{-needs flush-} False
-               writeBlocks hdl new_buf cs
+               writeLines hdl new_buf cs
           else 
                shoveString n' cs
   in
@@ -548,13 +555,27 @@ commitBuffer
        :: 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
@@ -608,13 +629,15 @@ commitBuffer hdl raw sz count flush release = do
                             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