1 {-# LANGUAGE ScopedTypeVariables #-}
3 ({- dont export generic versions for high performance ;-) -}) where
7 import Data.Foldable hiding (mapM_)
10 import Foreign.Marshal.Alloc
11 import Foreign.Marshal.Array
12 import Foreign.Storable
17 payload :: a -> IO IntPtr
19 marked :: a -> IO Bool
23 instance RefObj (Ptr a) where
24 payload = return . ptrToIntPtr
25 refs = unpackRefs . castPtr
35 unpackRefs :: Ptr Int32 -> IO [Ptr b]
36 unpackRefs ptr = do --dereference number of objs; mark field skipped via fieldsOffset
37 numberOfObjs <- peekByteOff ptr numberOfObjsOff :: IO Int32
38 mapM (peekElemOff (ptr `plusPtr` fieldsOff)) [0..fromIntegral $ numberOfObjs-1]
40 markedRef :: Ptr a -> IO Bool
41 markedRef ptr = liftM ((/=0) . fromIntegral) (peekByteOff ptr markedOff :: IO Int32)
43 markRef :: Ptr a -> IO ()
44 markRef ptr = pokeByteOff ptr markedOff (1::Int32)
46 markTree :: RefObj a => a -> IO ()
47 markTree root = marked root >>= (`when` continue) . not
48 where continue = mark root >> refs root >>= mapM_ markTree
51 emptyObj id = do mem <- mallocBytes 0xC
52 pokeArray mem [id,0,0::Int32]
55 twoRefs = do mem <- mallocBytes 0x14
56 -- idOfObj; numberofObj; marked waste memory Int32
57 pokeArray mem [0::Int32,2,0]
60 pokeByteOff mem 0xC obj1
61 pokeByteOff mem (0xC+0x4) obj2