nomeata / ghc-heap-view

Extract the heap representation of Haskell values and thunks
BSD 3-Clause "New" or "Revised" License
50 stars 19 forks source link

Strange behaviour with ghc-7.8.3 #1

Closed kosmikus closed 9 years ago

kosmikus commented 9 years ago

Thanks a lot for the release. I may be doing something stupid, but I get unexpected results using ghc-7.8.3.

Here is an example interaction using ghc-heap-view-0.5.1 and ghc-7.6.3:

$ ghci
GHCi, version 7.6.3: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude> let x = [1,2,3]
Prelude> :printHeap x
Loading package array-0.4.0.1 ... linking ... done.
Loading package deepseq-1.3.0.1 ... linking ... done.
Loading package containers-0.5.0.0 ... linking ... done.
Loading package transformers-0.3.0.0 ... linking ... done.
Loading package bytestring-0.10.0.2 ... linking ... done.
Loading package binary-0.5.1.1 ... linking ... done.
Loading package filepath-1.3.0.1 ... linking ... done.
Loading package old-locale-1.0.0.5 ... linking ... done.
Loading package time-1.4.0.1 ... linking ... done.
Loading package unix-2.6.0.1 ... linking ... done.
Loading package directory-1.2.0.1 ... linking ... done.
Loading package old-time-1.1.0.1 ... linking ... done.
Loading package pretty-1.1.1.0 ... linking ... done.
Loading package process-1.1.0.2 ... linking ... done.
Loading package Cabal-1.16.0 ... linking ... done.
Loading package bin-package-db-0.0.0.0 ... linking ... done.
Loading package hoopl-3.9.0.0 ... linking ... done.
Loading package hpc-0.6.0.0 ... linking ... done.
Loading package template-haskell ... linking ... done.
Loading package ghc-7.6.3 ... linking ... done.
Loading package ghc-heap-view-0.5.1 ... linking ... done.
[S# 1,S# 2,S# 3]
Prelude> let y = tail x
Prelude> :printHeap y
(_bco [S# 1,S# 2,S# 3] _fun)()
Prelude> head y
2
Prelude> :printHeap y
_bh [S# 2,S# 3]
Prelude> y
[2,3]
Prelude> :printHeap y
[S# 2,S# 3]
Prelude> 

The equivalent interaction using ghc-7.8.3 and the new ghc-heap-view looks rather less helpful:

$ ghci
GHCi, version 7.8.3: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude> let x = [1,2,3]
Prelude> :printHeap x
Loading package array-0.5.0.0 ... linking ... done.
Loading package deepseq-1.3.0.2 ... linking ... done.
Loading package bytestring-0.10.4.0 ... linking ... done.
Loading package containers-0.5.5.1 ... linking ... done.
Loading package binary-0.7.1.0 ... linking ... done.
Loading package transformers-0.3.0.0 ... linking ... done.
Loading package filepath-1.3.0.2 ... linking ... done.
Loading package old-locale-1.0.0.6 ... linking ... done.
Loading package time-1.4.2 ... linking ... done.
Loading package unix-2.7.0.1 ... linking ... done.
Loading package directory-1.2.1.0 ... linking ... done.
Loading package pretty-1.1.1.1 ... linking ... done.
Loading package process-1.2.0.0 ... linking ... done.
Loading package Cabal-1.18.1.3 ... linking ... done.
Loading package bin-package-db-0.0.0.0 ... linking ... done.
Loading package hoopl-3.10.0.1 ... linking ... done.
Loading package hpc-0.6.0.1 ... linking ... done.
Loading package template-haskell ... linking ... done.
Loading package ghc-7.8.3 ... linking ... done.
Loading package ghc-heap-view-0.5.2 ... linking ... done.
let f1 = _fun
in _bco()()
Prelude> let y = tail x
Prelude> :printHeap y
let f1 = _fun
in _bco()()
Prelude> head y
2
Prelude> :printHeap y
let f1 = _fun
in _bco()()
Prelude> y
[2,3]
Prelude> :printHeap y
let f1 = _fun
in _bco()()
Prelude> 
nomeata commented 9 years ago

I can reproduce it here... no idea yet what broke.

nomeata commented 9 years ago

It seems that passing x in GHCi no longer passes that value directly, but wraps it in some bytecode. If I put it in a box, force its evaluation and then print it, it works:

Prelude GHC.HeapView> let lb = asBox l
Prelude GHC.HeapView> getBoxedClosureData lb
APClosure {info = StgInfoTable {ptrs = 0, nptrs = 0, tipe = AP, srtlen = 0}, arity = 800703961, n_args = 0, fun = 0x00007fe32de5ac58, payload = []}
Prelude GHC.HeapView> case lb of Box a -> a `seq` ()
()
Prelude GHC.HeapView> getBoxedClosureData lb
BlackholeClosure {info = StgInfoTable {ptrs = 1, nptrs = 0, tipe = BLACKHOLE, srtlen = 0}, indirectee = 0x00007fe32e074db0}
Prelude GHC.HeapView> System.Mem.performGC
Prelude GHC.HeapView> getBoxedClosureData lb
ConsClosure {info = StgInfoTable {ptrs = 2, nptrs = 0, tipe = CONSTR_2_0, srtlen = 1}, ptrArgs = [0x00007fe32d98b810,0x00007fe32d98b7f8], dataArgs = [], pkg = "ghc-prim", modl = "GHC.Types", name = ":"}

but only so far:

Prelude GHC.HeapView> :printHeap lb
let f1 = _fun
    x1 = D:Num _fun _fun _fun _fun _fun _fun _fun
in Box [(_bco f1) x1,(_bco f1) x1,(_bco f1) x1]

which finally shows the problem: Polymorphism!

Prelude GHC.HeapView> let l = [1,2,3] :: [Int]
Prelude GHC.HeapView> :printHeap l
[I# 1,I# 2,I# 3]

Can you confirm that your problems go away once you add a type signature?

nomeata commented 9 years ago

There was also a bug in the byte code parser; fixed that. New version uploaded.

ma82 commented 9 years ago

Hello!

This does not deserve an issue of its own, I guess. I encountered a similar problem with the example code reported in the package description for version 0.5.4: I had OverloadedStrings turned on and it took me a while to understand why I couldn't see any change after triggering evaluations. Maybe a type signature for value could help there?

By the way: great software, thanks! :-)