Rodrigo Mesquita pushed to branch wip/romes/multi-threaded-debugger at Glasgow Haskell Compiler / GHC

Commits:

4 changed files:

Changes:

  • compiler/GHC.hs
    ... ... @@ -198,7 +198,7 @@ module GHC (
    198 198
             isStmt, hasImport, isImport, isDecl,
    
    199 199
     
    
    200 200
             -- ** The debugger
    
    201
    -        SingleStep(..),
    
    201
    +        SingleStep(..), ThreadBreaksIsolationMode(..),
    
    202 202
             Resume(..),
    
    203 203
             History(historyBreakpointId, historyEnclosingDecls),
    
    204 204
             GHC.getHistorySpan, getHistoryModule,
    

  • compiler/GHC/Runtime/Eval.hs
    ... ... @@ -13,7 +13,7 @@ module GHC.Runtime.Eval (
    13 13
             Resume(..), History(..),
    
    14 14
             execStmt, execStmt', ExecOptions(..), execOptions, ExecResult(..), resumeExec,
    
    15 15
             runDecls, runDeclsWithLocation, runParsedDecls,
    
    16
    -        parseImportDecl, SingleStep(..),
    
    16
    +        parseImportDecl, SingleStep(..), ThreadBreaksIsolationMode(..),
    
    17 17
             abandon, abandonAll,
    
    18 18
             getResumeContext,
    
    19 19
             getHistorySpan,
    
    ... ... @@ -184,8 +184,8 @@ execOptions = ExecOptions
    184 184
       , execSourceFile = "<interactive>"
    
    185 185
       , execLineNumber = 1
    
    186 186
       , execWrap = EvalThis -- just run the statement, don't wrap it in anything
    
    187
    -  , execIsolateBreaks = True
    
    188
    -    -- by default we just care about breakpoints hit in this "main" thread
    
    187
    +  , execIsolateMode = SingleThreadedBreaks
    
    188
    +    -- by default we just care about breakpoints hit in this eval thread
    
    189 189
       }
    
    190 190
     
    
    191 191
     -- | Run a statement in the current interactive context.
    
    ... ... @@ -211,7 +211,7 @@ execStmt input exec_opts@ExecOptions{..} = do
    211 211
     -- doing preprocessing on the AST before execution, e.g. in GHCi (see
    
    212 212
     -- GHCi.UI.runStmt).
    
    213 213
     execStmt' :: GhcMonad m => GhciLStmt GhcPs -> String -> ExecOptions -> m ExecResult
    
    214
    -execStmt' stmt stmt_text opts@ExecOptions{..} = do
    
    214
    +execStmt' stmt stmt_text ExecOptions{..} = do
    
    215 215
         hsc_env <- getSession
    
    216 216
         let interp = hscInterp hsc_env
    
    217 217
     
    
    ... ... @@ -232,8 +232,8 @@ execStmt' stmt stmt_text opts@ExecOptions{..} = do
    232 232
     
    
    233 233
             status <-
    
    234 234
               liftIO $ do
    
    235
    -            let eval_opts = initEvalOpts idflags' (enableGhcStepMode execSingleStep)
    
    236
    -                              { isolateThreadBreaks = execIsolateThreadBreaks }
    
    235
    +            let eval_opts = (initEvalOpts idflags' (enableGhcStepMode execSingleStep))
    
    236
    +                              { isolateThreadBreaks = enableIsolateThreadBreaks execIsolateMode }
    
    237 237
                 evalStmt interp eval_opts (execWrap hval)
    
    238 238
     
    
    239 239
             let ic = hsc_IC hsc_env
    
    ... ... @@ -241,7 +241,7 @@ execStmt' stmt stmt_text opts@ExecOptions{..} = do
    241 241
     
    
    242 242
                 size = ghciHistSize idflags'
    
    243 243
     
    
    244
    -        handleRunStatus opts stmt_text bindings ids
    
    244
    +        handleRunStatus execSingleStep execIsolateMode stmt_text bindings ids
    
    245 245
                             status (emptyHistory size)
    
    246 246
     
    
    247 247
     runDecls :: GhcMonad m => String -> m [Name]
    
    ... ... @@ -293,15 +293,15 @@ emptyHistory size = nilBL size
    293 293
     -- breakpoint if we don't care about that breakpoint (e.g. if using :steplocal
    
    294 294
     -- or :stepmodule, rather than :step, we only care about certain breakpoints).
    
    295 295
     handleRunStatus :: GhcMonad m
    
    296
    -                => ExecOptions
    
    296
    +                => SingleStep
    
    297
    +                -> ThreadBreaksIsolationMode
    
    297 298
                     -> String
    
    298 299
                     -> ResumeBindings
    
    299 300
                     -> [Id]
    
    300 301
                     -> EvalStatus_ [ForeignHValue] [HValueRef]
    
    301 302
                     -> BoundedList History
    
    302 303
                     -> m ExecResult
    
    303
    -handleRunStatus ExecOptions{execSingleStep = step, execIsolateThreadBreaks}
    
    304
    -                expr bindings final_ids status history0 = do
    
    304
    +handleRunStatus step isolateMode expr bindings final_ids status history0 = do
    
    305 305
       hsc_env <- getSession
    
    306 306
       let
    
    307 307
         interp = hscInterp hsc_env
    
    ... ... @@ -395,22 +395,25 @@ handleRunStatus ExecOptions{execSingleStep = step, execIsolateThreadBreaks}
    395 395
             return (ExecBreak names (Just ibi))
    
    396 396
           else do
    
    397 397
             -- resume with the same step type
    
    398
    -        let eval_opts = initEvalOpts dflags (enableGhcStepMode step)
    
    399
    -                          { isolateThreadBreaks = execIsolateThreadBreaks }
    
    398
    +        let eval_opts = (initEvalOpts dflags (enableGhcStepMode step))
    
    399
    +                          { isolateThreadBreaks = enableIsolateThreadBreaks isolateMode }
    
    400 400
             status <- liftIO $ GHCi.resumeStmt interp eval_opts resume_ctxt_fhv
    
    401 401
             history <- if not tracing then pure history0 else do
    
    402 402
               history1 <- liftIO $ mkHistory hug apStack_fhv ibi
    
    403 403
               let !history' = history1 `consBL` history0
    
    404 404
                     -- history is strict, otherwise our BoundedList is pointless.
    
    405 405
               return history'
    
    406
    -        handleRunStatus step expr bindings final_ids status history
    
    406
    +        handleRunStatus step isolateMode expr bindings final_ids status history
    
    407 407
      where
    
    408 408
       tracing | RunAndLogSteps <- step = True
    
    409 409
               | otherwise              = False
    
    410 410
     
    
    411
    -resumeExec :: GhcMonad m => SingleStep -> Maybe Int
    
    411
    +resumeExec :: GhcMonad m
    
    412
    +           => SingleStep
    
    413
    +           -> ThreadBreaksIsolationMode
    
    414
    +           -> Maybe Int
    
    412 415
                -> m ExecResult
    
    413
    -resumeExec step mbCnt
    
    416
    +resumeExec step isolateMode mbCnt
    
    414 417
      = do
    
    415 418
        hsc_env <- getSession
    
    416 419
        let ic = hsc_IC hsc_env
    
    ... ... @@ -455,7 +458,8 @@ resumeExec step mbCnt
    455 458
                       (Just brkpt, Just cnt) -> setupBreakpoint interp brkpt cnt
    
    456 459
                       _ -> return ()
    
    457 460
     
    
    458
    -                let eval_opts = initEvalOpts dflags (enableGhcStepMode step)
    
    461
    +                let eval_opts = (initEvalOpts dflags (enableGhcStepMode step))
    
    462
    +                                  { isolateThreadBreaks = enableIsolateThreadBreaks isolateMode }
    
    459 463
                     status <- liftIO $ GHCi.resumeStmt interp eval_opts fhv
    
    460 464
                     let prevHistoryLst = fromListBL 50 hist
    
    461 465
                         hug = hsc_HUG hsc_env
    
    ... ... @@ -466,7 +470,7 @@ resumeExec step mbCnt
    466 470
                                 hist1 <- liftIO (mkHistory hug apStack bi)
    
    467 471
                                 return $ hist1 `consBL` fromListBL 50 hist
    
    468 472
                              | otherwise -> pure prevHistoryLst
    
    469
    -                handleRunStatus step expr bindings final_ids status =<< hist'
    
    473
    +                handleRunStatus step isolateMode expr bindings final_ids status =<< hist'
    
    470 474
     
    
    471 475
     setupBreakpoint :: GhcMonad m => Interp -> InternalBreakpointId -> Int -> m ()   -- #19157
    
    472 476
     setupBreakpoint interp ibi cnt = do
    

  • compiler/GHC/Runtime/Eval/Types.hs
    ... ... @@ -10,6 +10,7 @@ module GHC.Runtime.Eval.Types (
    10 10
             Resume(..), ResumeBindings, IcGlobalRdrEnv(..),
    
    11 11
             History(..), ExecResult(..),
    
    12 12
             SingleStep(..), enableGhcStepMode, breakHere,
    
    13
    +        ThreadBreaksIsolationMode(..), enableIsolateThreadBreaks,
    
    13 14
             ExecOptions(..)
    
    14 15
             ) where
    
    15 16
     
    
    ... ... @@ -36,7 +37,8 @@ data ExecOptions
    36 37
          , execSourceFile :: String             -- ^ filename (for errors)
    
    37 38
          , execLineNumber :: Int                -- ^ line number (for errors)
    
    38 39
          , execWrap :: ForeignHValue -> EvalExpr ForeignHValue
    
    39
    -     , execIsolateThreadBreaks :: Bool      -- ^ just like @'isolateThreadBreaks'@
    
    40
    +     , execIsolateMode :: ThreadBreaksIsolationMode
    
    41
    +                                            -- ^ like @'isolateThreadBreaks'@
    
    40 42
          }
    
    41 43
     
    
    42 44
     -- | What kind of stepping are we doing?
    
    ... ... @@ -65,6 +67,17 @@ data SingleStep
    65 67
        | ModuleStep
    
    66 68
           { breakAt :: SrcSpan }
    
    67 69
     
    
    70
    +-- | Just like @'isolateThreadBreaks'@, determining whether the
    
    71
    +-- execution/resuming execution of an expression should stop whenever any
    
    72
    +-- non-isolated thread hits a breakpoint, or only when the thread executing
    
    73
    +-- that expression specifically stops.
    
    74
    +data ThreadBreaksIsolationMode
    
    75
    +  -- | Stop exclusively on the breakpoints in this thread
    
    76
    +  = SingleThreadedBreaks
    
    77
    +  -- | Stop whenever any thread that is not running in 'SingleThreadedBreaks'
    
    78
    +  -- isolation mode hits a breakpoint
    
    79
    +  | MultiThreadedBreaks
    
    80
    +
    
    68 81
     -- | Whether this 'SingleStep' mode requires instructing the interpreter to
    
    69 82
     -- step at every breakpoint or after every return (see @'EvalStep'@).
    
    70 83
     enableGhcStepMode :: SingleStep -> EvalStep
    
    ... ... @@ -73,6 +86,10 @@ enableGhcStepMode StepOut{} = EvalStepOut
    73 86
     -- for the remaining step modes we need to stop at every single breakpoint.
    
    74 87
     enableGhcStepMode _               = EvalStepSingle
    
    75 88
     
    
    89
    +enableIsolateThreadBreaks :: ThreadBreaksIsolationMode -> Bool
    
    90
    +enableIsolateThreadBreaks SingleThreadedBreaks = True
    
    91
    +enableIsolateThreadBreaks MultiThreadedBreaks  = False
    
    92
    +
    
    76 93
     -- | Given a 'SingleStep' mode, whether the breakpoint was explicitly active,
    
    77 94
     -- and the SrcSpan of a breakpoint we hit, return @True@ if we should stop at
    
    78 95
     -- this breakpoint.
    

  • ghc/GHCi/UI/Monad.hs
    ... ... @@ -412,7 +412,7 @@ resume step mbIgnoreCnt = do
    412 412
         withProgName (progname st) $
    
    413 413
         withArgs (args st) $
    
    414 414
           reflectGHCi x $ do
    
    415
    -        GHC.resumeExec step mbIgnoreCnt
    
    415
    +        GHC.resumeExec step GHC.SingleThreadedBreaks mbIgnoreCnt
    
    416 416
     
    
    417 417
     -- --------------------------------------------------------------------------
    
    418 418
     -- timing & statistics