Wen Kokke pushed to branch wip/wenkokke/trace-ipe at Glasgow Haskell Compiler / GHC

Commits:

16 changed files:

Changes:

  • changelog.d/ipe-event-class
    1
    +section: compiler
    
    2
    +synopsis: Add eventlog flag -lI to enable/disable IPE tracing
    
    3
    +issues: #27239
    
    4
    +mrs: !16004
    
    5
    +
    
    6
    +description: {
    
    7
    +    The RTS `-l` flag now accepts the new event class `I`,
    
    8
    +    which controls whether or not IPE events are emitted.
    
    9
    +}

  • docs/users_guide/runtime_control.rst
    ... ... @@ -1304,6 +1304,9 @@ When the program is linked with the :ghc-flag:`-eventlog` option
    1304 1304
         - ``u`` โ€” user events. These are events emitted from Haskell code using
    
    1305 1305
           functions such as ``Debug.Trace.traceEvent``. Enabled by default.
    
    1306 1306
     
    
    1307
    +    - ``I`` โ€” IPE events. These events describe source position information
    
    1308
    +      for info tables. See :ghc-flag:`-finfo-table-map`.
    
    1309
    +
    
    1307 1310
         You can disable specific classes, or enable/disable all classes at
    
    1308 1311
         once:
    
    1309 1312
     
    

  • libraries/ghc-internal/src/GHC/Internal/RTS/Flags.hsc
    ... ... @@ -211,6 +211,7 @@ data DebugFlags = DebugFlags
    211 211
         , squeeze        :: Bool -- ^ @z@ stack squeezing & lazy blackholing
    
    212 212
         , hpc            :: Bool -- ^ @c@ coverage
    
    213 213
         , sparks         :: Bool -- ^ @r@
    
    214
    +    , ipe            :: Bool -- ^ @I@
    
    214 215
         } deriving ( Show -- ^ @since base-4.8.0.0
    
    215 216
                    , Generic -- ^ @since base-4.15.0.0
    
    216 217
                    )
    
    ... ... @@ -359,6 +360,7 @@ data TraceFlags = TraceFlags
    359 360
         , sparksSampled  :: Bool -- ^ trace spark events by a sampled method
    
    360 361
         , sparksFull     :: Bool -- ^ trace spark events 100% accurately
    
    361 362
         , user           :: Bool -- ^ trace user events (emitted from Haskell code)
    
    363
    +    , traceIpe       :: Bool -- ^ trace IPE events
    
    362 364
         } deriving ( Show -- ^ @since base-4.8.0.0
    
    363 365
                    , Generic -- ^ @since base-4.15.0.0
    
    364 366
                    )
    
    ... ... @@ -588,6 +590,8 @@ getDebugFlags = do
    588 590
                        (#{peek DEBUG_FLAGS, hpc} ptr :: IO CBool))
    
    589 591
                  <*> (toBool <$>
    
    590 592
                        (#{peek DEBUG_FLAGS, sparks} ptr :: IO CBool))
    
    593
    +             <*> (toBool <$>
    
    594
    +                   (#{peek DEBUG_FLAGS, ipe} ptr :: IO CBool))
    
    591 595
     
    
    592 596
     getCCFlags :: IO CCFlags
    
    593 597
     getCCFlags = do
    
    ... ... @@ -647,6 +651,8 @@ getTraceFlags = do
    647 651
                        (#{peek TRACE_FLAGS, sparks_full} ptr :: IO CBool))
    
    648 652
                  <*> (toBool <$>
    
    649 653
                        (#{peek TRACE_FLAGS, user} ptr :: IO CBool))
    
    654
    +             <*> (toBool <$>
    
    655
    +                   (#{peek TRACE_FLAGS, ipe} ptr :: IO CBool))
    
    650 656
     #endif
    
    651 657
     
    
    652 658
     getTickyFlags :: IO TickyFlags
    

  • rts/IPE.c
    ... ... @@ -165,26 +165,46 @@ static void traceIPEFromHashTable(void *data STG_UNUSED, StgWord key STG_UNUSED,
    165 165
     }
    
    166 166
     
    
    167 167
     void dumpIPEToEventLog(void) {
    
    168
    -    // Dump pending entries
    
    169
    -    IpeBufferListNode *node = RELAXED_LOAD(&ipeBufferList);
    
    170
    -    while (node != NULL) {
    
    171
    -        if (ipe_node_valid(node)){
    
    172
    -          decompressIPEBufferListNodeIfCompressed(node);
    
    173
    -
    
    174
    -          for (uint32_t i = 0; i < node->count; i++) {
    
    175
    -              const InfoProvEnt ent = ipeBufferEntryToIpe(node, i);
    
    176
    -              traceIPE(&ent);
    
    177
    -          }
    
    168
    +    /*
    
    169
    +    Usually, traceX functions are defined as a pair of a traceX_ function that
    
    170
    +    traces unconditionally and a traceX functional macro that performs the test
    
    171
    +    for the relevant TRACE_x flag.
    
    172
    +
    
    173
    +    This function is the only function that calls traceIPE, but it takes a lot
    
    174
    +    of work just to prepare the IPE information. If traceIPE does not trace that
    
    175
    +    IPE information, all that work is wasted. Hence, the test of TRACE_ipe is
    
    176
    +    performed in this function instead.
    
    177
    +
    
    178
    +    This function is called via traceInitEvent in RtsStartup.c, which registers
    
    179
    +    it as an init event handler. It is important that this happens regardless
    
    180
    +    of whether or not IPE tracing is enabled at startup, since IPE tracing can
    
    181
    +    be started/stopped at runtime using the dynamic trace flags API.
    
    182
    +
    
    183
    +    IPE tracing is enabled whenever IPE debug printing is enabled via -DI, so
    
    184
    +    this test does not prevent IPE debug printing.
    
    185
    +    */
    
    186
    +    if (RTS_UNLIKELY(TRACE_ipe)) {
    
    187
    +        // Dump pending entries
    
    188
    +        IpeBufferListNode *node = RELAXED_LOAD(&ipeBufferList);
    
    189
    +        while (node != NULL) {
    
    190
    +            if (ipe_node_valid(node)){
    
    191
    +              decompressIPEBufferListNodeIfCompressed(node);
    
    192
    +
    
    193
    +              for (uint32_t i = 0; i < node->count; i++) {
    
    194
    +                  const InfoProvEnt ent = ipeBufferEntryToIpe(node, i);
    
    195
    +                  traceIPE(&ent);
    
    196
    +              }
    
    197
    +            }
    
    198
    +            node = node->next;
    
    178 199
             }
    
    179
    -        node = node->next;
    
    180
    -    }
    
    181 200
     
    
    182
    -    // Dump entries already in hashmap
    
    183
    -    ACQUIRE_LOCK(&ipeMapLock);
    
    184
    -    if (ipeMap != NULL) {
    
    185
    -        mapHashTable(ipeMap, NULL, &traceIPEFromHashTable);
    
    201
    +        // Dump entries already in hashmap
    
    202
    +        ACQUIRE_LOCK(&ipeMapLock);
    
    203
    +        if (ipeMap != NULL) {
    
    204
    +            mapHashTable(ipeMap, NULL, &traceIPEFromHashTable);
    
    205
    +        }
    
    206
    +        RELEASE_LOCK(&ipeMapLock);
    
    186 207
         }
    
    187
    -    RELEASE_LOCK(&ipeMapLock);
    
    188 208
     }
    
    189 209
     
    
    190 210
     
    

  • rts/RtsFlags.c
    ... ... @@ -249,6 +249,7 @@ void initRtsFlagsDefaults(void)
    249 249
         RtsFlags.TraceFlags.sparks_sampled= false;
    
    250 250
         RtsFlags.TraceFlags.sparks_full   = false;
    
    251 251
         RtsFlags.TraceFlags.user          = false;
    
    252
    +    RtsFlags.TraceFlags.ipe           = false;
    
    252 253
         RtsFlags.TraceFlags.ticky         = false;
    
    253 254
         RtsFlags.TraceFlags.trace_output  = NULL;
    
    254 255
     #  if defined(THREADED_RTS)
    
    ... ... @@ -449,6 +450,7 @@ usage_text[] = {
    449 450
     "                p    par spark events (sampled)",
    
    450 451
     "                f    par spark events (full detail)",
    
    451 452
     "                u    user events (emitted from Haskell code)",
    
    453
    +"                I    IPE events",
    
    452 454
     #if defined(TICKY_TICKY)
    
    453 455
     "                T    ticky-ticky counter samples",
    
    454 456
     #endif
    
    ... ... @@ -457,7 +459,7 @@ usage_text[] = {
    457 459
     "                t    add time stamps (only useful with -v)",
    
    458 460
     #  endif
    
    459 461
     "               -x    disable an event class, for any flag above",
    
    460
    -"             the initial enabled event classes are 'sgpu'",
    
    462
    +"             the initial enabled event classes are 'sgIpu'",
    
    461 463
     #  if defined(THREADED_RTS)
    
    462 464
     " --eventlog-flush-interval=<secs>",
    
    463 465
     "             Periodically flush the eventlog at the specified interval.",
    
    ... ... @@ -2528,6 +2530,7 @@ static void read_trace_flags(const char *arg)
    2528 2530
         RtsFlags.TraceFlags.gc             = true;
    
    2529 2531
         RtsFlags.TraceFlags.sparks_sampled = true;
    
    2530 2532
         RtsFlags.TraceFlags.user           = true;
    
    2533
    +    RtsFlags.TraceFlags.ipe            = true;
    
    2531 2534
     
    
    2532 2535
         for (c  = arg; *c != '\0'; c++) {
    
    2533 2536
             switch(*c) {
    
    ... ... @@ -2541,8 +2544,9 @@ static void read_trace_flags(const char *arg)
    2541 2544
                 RtsFlags.TraceFlags.gc             = enabled;
    
    2542 2545
                 RtsFlags.TraceFlags.sparks_sampled = enabled;
    
    2543 2546
                 RtsFlags.TraceFlags.sparks_full    = enabled;
    
    2544
    -            RtsFlags.TraceFlags.user           = enabled;
    
    2545 2547
                 RtsFlags.TraceFlags.nonmoving_gc   = enabled;
    
    2548
    +            RtsFlags.TraceFlags.user           = enabled;
    
    2549
    +            RtsFlags.TraceFlags.ipe            = enabled;
    
    2546 2550
     #if defined(TICKY_TICKY)
    
    2547 2551
                 RtsFlags.TraceFlags.ticky          = enabled;
    
    2548 2552
     #endif
    
    ... ... @@ -2577,6 +2581,10 @@ static void read_trace_flags(const char *arg)
    2577 2581
                 RtsFlags.TraceFlags.user      = enabled;
    
    2578 2582
                 enabled = true;
    
    2579 2583
                 break;
    
    2584
    +        case 'I':
    
    2585
    +            RtsFlags.TraceFlags.ipe       = enabled;
    
    2586
    +            enabled = true;
    
    2587
    +            break;
    
    2580 2588
             case 'T':
    
    2581 2589
     #if defined(TICKY_TICKY)
    
    2582 2590
                 RtsFlags.TraceFlags.ticky     = enabled;
    

  • rts/Trace.c
    ... ... @@ -47,6 +47,8 @@ bool getTraceFlag(RUNTIME_TRACE_FLAG flag) {
    47 47
         return RuntimeTraceFlagCache.user;
    
    48 48
       case TRACE_CAP:
    
    49 49
         return RuntimeTraceFlagCache.cap;
    
    50
    +  case TRACE_IPE:
    
    51
    +    return RuntimeTraceFlagCache.ipe;
    
    50 52
       default:
    
    51 53
         return false;
    
    52 54
       }
    
    ... ... @@ -75,6 +77,9 @@ void setTraceFlag(RUNTIME_TRACE_FLAG flag, bool value) {
    75 77
       case TRACE_CAP:
    
    76 78
         RuntimeTraceFlagCache.cap = value;
    
    77 79
         break;
    
    80
    +  case TRACE_IPE:
    
    81
    +    RuntimeTraceFlagCache.ipe = value;
    
    82
    +    break;
    
    78 83
       }
    
    79 84
     }
    
    80 85
     
    
    ... ... @@ -119,13 +124,19 @@ static void updateTraceFlagCache(void) {
    119 124
       RuntimeTraceFlagCache.user =
    
    120 125
         RtsFlags.TraceFlags.user;
    
    121 126
     
    
    127
    +  // -DI turns on IPE tracing too
    
    128
    +  RuntimeTraceFlagCache.ipe =
    
    129
    +      RtsFlags.TraceFlags.ipe ||
    
    130
    +      RtsFlags.DebugFlags.ipe;
    
    131
    +
    
    122 132
       // We trace cap events if we're tracing anything else
    
    123 133
       RuntimeTraceFlagCache.cap =
    
    124 134
         TRACE_sched ||
    
    125 135
         TRACE_gc ||
    
    126 136
         TRACE_spark_sampled ||
    
    127 137
         TRACE_spark_full ||
    
    128
    -    TRACE_user;
    
    138
    +    TRACE_user ||
    
    139
    +    TRACE_ipe;
    
    129 140
     }
    
    130 141
     
    
    131 142
     void initTracing (void)
    
    ... ... @@ -720,6 +731,7 @@ void traceHeapProfSampleString(const char *label, StgWord residency)
    720 731
         }
    
    721 732
     }
    
    722 733
     
    
    734
    +// The TRACE_ipe test happens in dumpIPEToEventLog.
    
    723 735
     void traceIPE(const InfoProvEnt *ipe)
    
    724 736
     {
    
    725 737
     #if defined(DEBUG)
    

  • rts/Trace.h
    ... ... @@ -79,6 +79,7 @@ enum CapsetType { CapsetTypeCustom = CAPSET_TYPE_CUSTOM,
    79 79
     #define TRACE_spark_full    ((const bool)RuntimeTraceFlagCache.spark_full)
    
    80 80
     #define TRACE_user          ((const bool)RuntimeTraceFlagCache.user)
    
    81 81
     #define TRACE_cap           ((const bool)RuntimeTraceFlagCache.cap)
    
    82
    +#define TRACE_ipe           ((const bool)RuntimeTraceFlagCache.ipe)
    
    82 83
     
    
    83 84
     /*
    
    84 85
      * Runtime trace flags.
    
    ... ... @@ -91,6 +92,7 @@ typedef struct {
    91 92
       bool spark_full;
    
    92 93
       bool user;
    
    93 94
       bool cap;
    
    95
    +  bool ipe;
    
    94 96
     } RUNTIME_TRACE_FLAG_CACHE;
    
    95 97
     
    
    96 98
     /*
    

  • rts/include/rts/EventLogWriter.h
    ... ... @@ -90,6 +90,7 @@ typedef enum {
    90 90
       TRACE_SPARK_FULL,
    
    91 91
       TRACE_USER,
    
    92 92
       TRACE_CAP,
    
    93
    +  TRACE_IPE,
    
    93 94
     } RUNTIME_TRACE_FLAG;
    
    94 95
     
    
    95 96
     /*
    

  • rts/include/rts/Flags.h
    ... ... @@ -191,6 +191,7 @@ typedef struct _TRACE_FLAGS {
    191 191
         bool sparks_full;    /* trace spark events 100% accurately */
    
    192 192
         bool ticky;          /* trace ticky-ticky samples */
    
    193 193
         bool user;           /* trace user events (emitted from Haskell code) */
    
    194
    +    bool ipe;            /* trace IPE events */
    
    194 195
     #if defined(THREADED_RTS)
    
    195 196
         /* Time between force eventlog flushes (or 0 if disabled) */
    
    196 197
         Time eventlogFlushTime;
    

  • testsuite/tests/rts/T25275/DebugIpe.hs
    1
    +module Main where
    
    2
    +
    
    3
    +import GHC.RTS.Flags.Experimental (DebugFlags (..), getDebugFlags)
    
    4
    +
    
    5
    +main :: IO ()
    
    6
    +main = print . ipe =<< getDebugFlags

  • testsuite/tests/rts/T25275/T25275_A.stdout
    1
    +False
    \ No newline at end of file

  • testsuite/tests/rts/T25275/T25275_B.stdout
    1
    +True
    \ No newline at end of file

  • testsuite/tests/rts/T25275/T25275_C.stdout
    1
    +False
    \ No newline at end of file

  • testsuite/tests/rts/T25275/T25275_D.stdout
    1
    +True
    \ No newline at end of file

  • testsuite/tests/rts/T25275/TraceIpe.hs
    1
    +module Main where
    
    2
    +
    
    3
    +import GHC.RTS.Flags.Experimental (TraceFlags (..), getTraceFlags)
    
    4
    +
    
    5
    +main :: IO ()
    
    6
    +main = print . traceIpe =<< getTraceFlags

  • testsuite/tests/rts/T25275/all.T
    1
    +# Compile and run with default RTS options
    
    2
    +test(
    
    3
    +    'T25275_A',
    
    4
    +    [
    
    5
    +        extra_files(['TraceIpe.hs']),
    
    6
    +    ],
    
    7
    +    multimod_compile_and_run,
    
    8
    +    ['TraceIpe', ''],
    
    9
    +)
    
    10
    +
    
    11
    +# Compile and run with -lI
    
    12
    +test(
    
    13
    +    'T25275_B',
    
    14
    +    [
    
    15
    +        extra_files(['TraceIpe.hs']),
    
    16
    +        extra_run_opts('+RTS -lI -RTS'),
    
    17
    +    ],
    
    18
    +    multimod_compile_and_run,
    
    19
    +    ['TraceIpe', ''],
    
    20
    +)
    
    21
    +
    
    22
    +# Compile and run with default RTS options
    
    23
    +test(
    
    24
    +    'T25275_C',
    
    25
    +    [
    
    26
    +        only_ways(['debug']),
    
    27
    +        extra_files(['DebugIpe.hs']),
    
    28
    +    ],
    
    29
    +    multimod_compile_and_run,
    
    30
    +    ['DebugIpe', ''],
    
    31
    +)
    
    32
    +
    
    33
    +# Compile and run with -DI
    
    34
    +test(
    
    35
    +    'T25275_D',
    
    36
    +    [
    
    37
    +        only_ways(['debug']),
    
    38
    +        extra_files(['DebugIpe.hs']),
    
    39
    +        extra_run_opts('+RTS -DI -RTS'),
    
    40
    +    ],
    
    41
    +    multimod_compile_and_run,
    
    42
    +    ['DebugIpe', ''],
    
    43
    +)