| 177 | | == The D in Dynamic Breakpoints == |
| 178 | | When we instrument the code we insert a flavor of regular breakpoints which know about their site number. So when one of these is hit, ghci finds out whether that site is enabled and acts accordingly. |
| 179 | | GHCi thus stores a boolean matrix of enabled breakpoint sites. This scheme is realized in [http://darcs.haskell.org/SoC/ghc.debugger/compiler/main/Breakpoints.hs Breakpoints.hs]: |
| 180 | | {{{ |
| 181 | | data BkptTable a = BkptTable { |
| 182 | | breakpoints :: Map.Map a (UArray Int Bool) -- *An array of breaks, indexed by site number |
| 183 | | , sites :: Map.Map a [[(SiteNumber, Int)]] -- *A list of lines, each line can have zero or more sites, which are annotated with a column number |
| 184 | | } |
| 185 | | }}} |
| 186 | | |
| 187 | | Since this structure needs to be accessed every time a breakpoint is hit and is modified extremely few times in comparison, the goal is to have as fast access time as possible. Most of the overhead is due to this structure. |
| 188 | | It's too bad that I haven't explored alternative designs. (Using bits instead of Bools in the matrix? discard the matrix thing and use an IORef in every breakpoint? some clever trick using the FFI?). |
| 189 | | |
| 242 | | handleBreakpoint :: forall b. Session -> [(Id,HValue)] -> BkptLocation a -> String -> b -> IO b |
| 243 | | , isAutoBkptEnabled :: Session -> BkptLocation a -> IO Bool |
| | 234 | -- | What to do once an enabled breakpoint is found |
| | 235 | handleBreakpoint :: forall b. Session |
| | 236 | -> [(Id,HValue)] -- * Local bindings and their id's |
| | 237 | -> BkptLocation a -- * Module and Site # |
| | 238 | -> String -- * A SrcLoc string msg |
| | 239 | -> b -- * The arg. to the breakpoint fun |
| | 240 | -> IO b |
| | 241 | -- | Implementors should return True if the breakpoint is enabled |
| | 242 | , isAutoBkptEnabled :: Session |
| | 243 | -> BkptLocation a -- * Module and Site # |
| | 244 | -> IO Bool |
| 246 | | '' to be finished'' |
| 247 | | |
| | 247 | |
| | 248 | The Ghci debugger is a client of this API as described below. |
| | 249 | |
| | 250 | == The D in Dynamic Breakpoints == |
| | 251 | |
| | 252 | In order to implement the 'isAutoBkptEnabled' record, when a breakpoint is hit GHCi must find out whether that site is enabled or not. GHCi thus stores a boolean matrix of enabled breakpoint sites. This scheme is realized in [http://darcs.haskell.org/SoC/ghc.debugger/compiler/main/Breakpoints.hs Breakpoints.hs]: |
| | 253 | {{{ |
| | 254 | data BkptTable a = BkptTable { |
| | 255 | breakpoints :: Map.Map a (UArray Int Bool) -- *An array of breaks, indexed by site number |
| | 256 | , sites :: Map.Map a [[(SiteNumber, Int)]] -- *A list of lines, each line can have zero or more sites, which are annotated with a column number |
| | 257 | } |
| | 258 | }}} |
| | 259 | |
| | 260 | Since this structure needs to be accessed every time a breakpoint is hit and is modified extremely few times in comparison, the goal is to have as fast access time as possible. All of the overhead in our debugger is going to be caused by this operation. |
| | 261 | |
| | 262 | It's too bad that I haven't explored alternative designs. (Using bits instead of Bools in the matrix? discard the matrix thing and use an IORef in every breakpoint? some clever trick using the FFI?). |