<div dir="auto"><div>So I guess this is to avoid having to check the closure type on each mutation to see if the array needs to be added to the mutable list?<br><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, Aug 20, 2020, 6:12 PM Bertram Felgenhauer via Glasgow-haskell-users <<a href="mailto:glasgow-haskell-users@haskell.org">glasgow-haskell-users@haskell.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">David Feuer wrote:<br>
> I know that a frozen array doesn't have to be searched for elements in<br>
> a younger generation, but how does it differ from an unfrozen array<br>
> that hasn't been mutated since the last collection?<br>
<br>
Frozen arrays are not put on the mutable list once they're clean<br>
(meaning they have no references to younger generations). Thawed<br>
arrays are always on the mutable list.<br>
<br>
Cheers,<br>
<br>
Bertram<br>
<br>
<br>
You can crash a program by updating a clean frozen array in the old<br>
generation, then doing a minor GC, and then accessing the updated<br>
entry:<br>
<br>
import Data.Array<br>
import Data.Array.Base (unsafeFreezeIOArray, unsafeThawIOArray)<br>
import <a href="http://Data.Array.IO" rel="noreferrer noreferrer" target="_blank">Data.Array.IO</a><br>
import Data.Array.Unsafe<br>
import System.Mem<br>
import Control.Monad (forM_)<br>
<br>
main = do<br>
    arr <- newArray (0, 1024) 42 :: IO (IOArray Int Int)<br>
    -- `arr` points to a MUT_ARR_PTRS closure<br>
<br>
    arr' <- unsafeFreezeIOArray arr :: IO (Array Int Int)<br>
    -- unsafeFreezeIOArray changes the closure type to<br>
    -- MUT_ARR_PTRS_FROZEN_DIRTY<br>
<br>
    performMajorGC<br>
    -- the first major GC changes it to MUT_ARR_PTRS_FROZEN<br>
<br>
    performMajorGC<br>
    -- the second GC kicks it off the mutable list??<br>
<br>
    -- unsafeThaw would change the closure type to MUT_ARR_PTRS_DIRTY<br>
    -- *and* put the array on the mutable list.<br>
    -- _ <- unsafeThawIOArray arr'<br>
<br>
    -- in contrast, `writeArray` changes the closure type to<br>
    -- MUT_ARR_PTRS_DIRTY but does not touch the `mutable list`<br>
    forM_ [0..1023] $ \i -> do<br>
        writeArray arr i $ f i<br>
<br>
    print $ sum [1..1000000]<br>
    -- Evaluating the sum produces a lot of garbage, and the minor GCs<br>
    -- will not scan the array.<br>
<br>
    arr' <- unsafeFreezeIOArray arr :: IO (Array Int Int)<br>
    print $ arr' ! 0<br>
    print $ arr' ! 1<br>
    -- so these array entries have a good chance to point to utter garbage.<br>
<br>
{-# NOINLINE f #-}<br>
f x = x*x<br>
<br>
{-<br>
<br>
> ghc -O0 Crash.hs && ./Crash<br>
[1 of 1] Compiling Main             ( Crash.hs, Crash.o )<br>
Linking Crash ...<br>
Crash: internal error: evacuate: strange closure type 29041<br>
    (GHC version 8.6.5 for x86_64_unknown_linux)<br>
    Please report this as a GHC bug:  <a href="http://www.haskell.org/ghc/reportabug" rel="noreferrer noreferrer" target="_blank">http://www.haskell.org/ghc/reportabug</a><br>
Aborted (core dumped)<br>
<br>
> ghc -O1 Crash.hs && ./Crash<br>
[1 of 1] Compiling Main             ( Crash.hs, Crash.o )<br>
Linking Crash ...<br>
500000500000<br>
482299980870<br>
Segmentation fault (core dumped)<br>
<br>
> ghc -O2 Crash.hs && ./Crash<br>
[1 of 1] Compiling Main             ( Crash.hs, Crash.o ) [Optimisation flags changed]<br>
Linking Crash ...<br>
500000500000<br>
482299980870<br>
Segmentation fault (core dumped)<br>
<br>
-}<br>
_______________________________________________<br>
Glasgow-haskell-users mailing list<br>
<a href="mailto:Glasgow-haskell-users@haskell.org" target="_blank" rel="noreferrer">Glasgow-haskell-users@haskell.org</a><br>
<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/glasgow-haskell-users" rel="noreferrer noreferrer" target="_blank">http://mail.haskell.org/cgi-bin/mailman/listinfo/glasgow-haskell-users</a><br>
</blockquote></div></div></div>