{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE BinaryLiterals #-}
{-# LANGUAGE RankNTypes #-}
module GHC.Debug.Client.BlockCache(BlockCache, BlockCacheRequest(..)
, handleBlockReq, emptyBlockCache, bcSize, addBlocks) where
import GHC.Debug.Types.Ptr
import GHC.Debug.Types
import qualified Data.HashMap.Strict as HM
import GHC.Word
import Data.Hashable
import Data.IORef
import Data.Bits
import Data.List (sort)
import Data.Binary
import Control.Tracer
newtype BlockCache = BlockCache (HM.HashMap Word64 RawBlock)
instance Binary BlockCache where
get :: Get BlockCache
get = HashMap Word64 RawBlock -> BlockCache
BlockCache forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall k v. (Eq k, Hashable k) => [(k, v)] -> HashMap k v
HM.fromList forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall t. Binary t => Get t
get
put :: BlockCache -> Put
put (BlockCache HashMap Word64 RawBlock
hm) = forall t. Binary t => t -> Put
put (forall k v. HashMap k v -> [(k, v)]
HM.toList HashMap Word64 RawBlock
hm)
emptyBlockCache :: BlockCache
emptyBlockCache :: BlockCache
emptyBlockCache = HashMap Word64 RawBlock -> BlockCache
BlockCache forall k v. HashMap k v
HM.empty
addBlock :: RawBlock -> BlockCache -> BlockCache
addBlock :: RawBlock -> BlockCache -> BlockCache
addBlock rb :: RawBlock
rb@(RawBlock (BlockPtr Word64
bp) Word16
_ ByteString
_) (BlockCache HashMap Word64 RawBlock
bc) =
HashMap Word64 RawBlock -> BlockCache
BlockCache (forall k v.
(Eq k, Hashable k) =>
k -> v -> HashMap k v -> HashMap k v
HM.insert Word64
bp RawBlock
rb HashMap Word64 RawBlock
bc)
addBlocks :: [RawBlock] -> BlockCache -> BlockCache
addBlocks :: [RawBlock] -> BlockCache -> BlockCache
addBlocks [RawBlock]
bc BlockCache
bs = forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
Prelude.foldr RawBlock -> BlockCache -> BlockCache
addBlock BlockCache
bs [RawBlock]
bc
lookupClosure :: ClosurePtr -> BlockCache -> Maybe RawBlock
lookupClosure :: ClosurePtr -> BlockCache -> Maybe RawBlock
lookupClosure (ClosurePtr Word64
cp) (BlockCache HashMap Word64 RawBlock
b) =
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> Maybe v
HM.lookup (Word64
cp forall a. Bits a => a -> a -> a
.&. forall a. Bits a => a -> a
complement Word64
blockMask) HashMap Word64 RawBlock
b
bcSize :: BlockCache -> Int
bcSize :: BlockCache -> Int
bcSize (BlockCache HashMap Word64 RawBlock
b) = forall k v. HashMap k v -> Int
HM.size HashMap Word64 RawBlock
b
_bcKeys :: BlockCache -> [ClosurePtr]
_bcKeys :: BlockCache -> [ClosurePtr]
_bcKeys (BlockCache HashMap Word64 RawBlock
b) = forall a. Ord a => [a] -> [a]
sort forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map Word64 -> ClosurePtr
mkClosurePtr (forall k v. HashMap k v -> [k]
HM.keys HashMap Word64 RawBlock
b)
data BlockCacheRequest a where
LookupClosure :: ClosurePtr -> BlockCacheRequest RawClosure
PopulateBlockCache :: BlockCacheRequest [RawBlock]
deriving instance Show (BlockCacheRequest a)
deriving instance Eq (BlockCacheRequest a)
instance Hashable (BlockCacheRequest a) where
hashWithSalt :: Int -> BlockCacheRequest a -> Int
hashWithSalt Int
s (LookupClosure ClosurePtr
cpt) = Int
s forall a. Hashable a => Int -> a -> Int
`hashWithSalt` (Int
1 :: Int) forall a. Hashable a => Int -> a -> Int
`hashWithSalt` ClosurePtr
cpt
hashWithSalt Int
s BlockCacheRequest a
PopulateBlockCache = Int
s forall a. Hashable a => Int -> a -> Int
`hashWithSalt` (Int
2 :: Int)
handleBlockReq :: Tracer IO String -> (forall a . Request a -> IO a) -> IORef BlockCache -> BlockCacheRequest resp -> IO resp
handleBlockReq :: forall resp.
Tracer IO String
-> (forall a. Request a -> IO a)
-> IORef BlockCache
-> BlockCacheRequest resp
-> IO resp
handleBlockReq Tracer IO String
_ forall a. Request a -> IO a
do_req IORef BlockCache
ref (LookupClosure ClosurePtr
cp) = do
BlockCache
bc <- forall a. IORef a -> IO a
readIORef IORef BlockCache
ref
let mrb :: Maybe RawBlock
mrb = ClosurePtr -> BlockCache -> Maybe RawBlock
lookupClosure ClosurePtr
cp BlockCache
bc
RawBlock
rb <- case Maybe RawBlock
mrb of
Maybe RawBlock
Nothing -> do
RawBlock
rb <- forall a. Request a -> IO a
do_req (ClosurePtr -> Request RawBlock
RequestBlock ClosurePtr
cp)
forall a b. IORef a -> (a -> (a, b)) -> IO b
atomicModifyIORef' IORef BlockCache
ref (\BlockCache
bc' -> (RawBlock -> BlockCache -> BlockCache
addBlock RawBlock
rb BlockCache
bc', ()))
return RawBlock
rb
Just RawBlock
rb -> do
forall (m :: * -> *) a. Monad m => a -> m a
return RawBlock
rb
return (ClosurePtr -> RawBlock -> RawClosure
extractFromBlock ClosurePtr
cp RawBlock
rb)
handleBlockReq Tracer IO String
tracer forall a. Request a -> IO a
do_req IORef BlockCache
ref BlockCacheRequest resp
PopulateBlockCache = do
[RawBlock]
blocks <- forall a. Request a -> IO a
do_req Request [RawBlock]
RequestAllBlocks
forall (m :: * -> *) a. Monad m => Tracer m a -> a -> m ()
traceWith Tracer IO String
tracer forall a b. (a -> b) -> a -> b
$ String
"Populating block cache with " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show (forall (t :: * -> *) a. Foldable t => t a -> Int
length [RawBlock]
blocks) forall a. [a] -> [a] -> [a]
++ String
" blocks"
forall a b. IORef a -> (a -> (a, b)) -> IO b
atomicModifyIORef' IORef BlockCache
ref ((,()) forall b c a. (b -> c) -> (a -> b) -> a -> c
. [RawBlock] -> BlockCache -> BlockCache
addBlocks [RawBlock]
blocks)
return [RawBlock]
blocks