@@ -116,15 +116,15 @@ static void msgpack_write_header(void)
116116
117117 /* version */
118118 msgpack_write_key (& hdr , "version" );
119- msgpack_write_uint (& hdr , 2 );
119+ msgpack_write_uint (& hdr , 3 );
120120
121121 /* format */
122122 msgpack_write_key (& hdr , "format" );
123123 msgpack_write_str (& hdr , "tracegrind-msgpack" , -1 );
124124
125125 /* event_schemas - discriminated union: each event type has its own schema */
126126 msgpack_write_key (& hdr , "event_schemas" );
127- msgpack_write_map_header (& hdr , 4 ); /* 4 event types: MARKER, ENTER, EXIT, FORK */
127+ msgpack_write_map_header (& hdr , 6 ); /* 6 event types: MARKER, ENTER, EXIT, FORK, ENTER_INLINED, EXIT_INLINED */
128128
129129 /* Event type 0 (MARKER) schema */
130130 msgpack_write_key (& hdr , "0" );
@@ -156,6 +156,20 @@ static void msgpack_write_header(void)
156156 msgpack_write_str (& hdr , "event" , -1 );
157157 msgpack_write_str (& hdr , "child_pid" , -1 );
158158
159+ /* Event type 4 (ENTER_INLINED) schema - same columns as ENTER/EXIT */
160+ msgpack_write_key (& hdr , "4" );
161+ msgpack_write_array_header (& hdr , mp_state .ncols );
162+ for (Int i = 0 ; i < mp_state .ncols ; i ++ ) {
163+ msgpack_write_str (& hdr , mp_state .col_names [i ], -1 );
164+ }
165+
166+ /* Event type 5 (EXIT_INLINED) schema - same columns as ENTER/EXIT */
167+ msgpack_write_key (& hdr , "5" );
168+ msgpack_write_array_header (& hdr , mp_state .ncols );
169+ for (Int i = 0 ; i < mp_state .ncols ; i ++ ) {
170+ msgpack_write_str (& hdr , mp_state .col_names [i ], -1 );
171+ }
172+
159173 /* Compress and write header chunk */
160174 SizeT src_size = hdr .size ;
161175 SizeT dst_capacity = tg_lz4_compress_bound (src_size );
@@ -164,8 +178,8 @@ static void msgpack_write_header(void)
164178 SizeT compressed_size = tg_lz4_compress (
165179 compressed , dst_capacity , hdr .data , src_size );
166180
167- /* Magic + version (8 bytes): "TGMP" + version(4) - version 2 */
168- UChar magic [8 ] = {'T' , 'G' , 'M' , 'P' , 0x02 , 0x00 , 0x00 , 0x00 };
181+ /* Magic + version (8 bytes): "TGMP" + version(4) - version 3 */
182+ UChar magic [8 ] = {'T' , 'G' , 'M' , 'P' , 0x03 , 0x00 , 0x00 , 0x00 };
169183 VG_ (write )(TG_ (trace_out ).fd , magic , 8 );
170184
171185 /* Header chunk size (4 bytes uncompressed, 4 bytes compressed) */
@@ -439,6 +453,92 @@ void TG_(trace_emit_sample)(ThreadId tid, Bool is_enter,
439453 deltas , es -> size );
440454}
441455
456+ void TG_ (trace_emit_enter_inlined )(ThreadId tid , BB * bb )
457+ {
458+ Int i ;
459+
460+ if (!TG_ (trace_out ).initialized ) return ;
461+ if (TG_ (trace_out ).fd < 0 ) return ;
462+
463+ thread_info * ti = TG_ (get_current_thread )();
464+ if (!ti ) return ;
465+
466+ EventSet * es = TG_ (sets ).full ;
467+ FullCost current_cost = TG_ (current_state ).cost ;
468+
469+ if (!ti -> last_sample_cost ) {
470+ ti -> last_sample_cost = TG_ (get_eventset_cost )(es );
471+ TG_ (init_cost )(es , ti -> last_sample_cost );
472+ }
473+
474+ TG_ (trace_out ).seq ++ ;
475+
476+ const HChar * fn_name = bb -> inl_fn ;
477+ const HChar * obj_name = bb -> obj ? bb -> obj -> name : "???" ;
478+ const HChar * file_name = (bb -> fn && bb -> fn -> file ) ? bb -> fn -> file -> name : "???" ;
479+ UInt line = bb -> line ;
480+
481+ ULong deltas [64 ];
482+ tl_assert (es -> size <= 64 );
483+ if (current_cost && ti -> last_sample_cost ) {
484+ for (i = 0 ; i < es -> size ; i ++ ) {
485+ deltas [i ] = current_cost [i ] - ti -> last_sample_cost [i ];
486+ }
487+ TG_ (copy_cost )(es , ti -> last_sample_cost , current_cost );
488+ } else {
489+ for (i = 0 ; i < es -> size ; i ++ ) {
490+ deltas [i ] = 0 ;
491+ }
492+ }
493+
494+ msgpack_add_row (TG_ (trace_out ).seq , (Int )tid , TG_EV_ENTER_INLINED ,
495+ fn_name , obj_name , file_name , (Int )line ,
496+ deltas , es -> size );
497+ }
498+
499+ void TG_ (trace_emit_exit_inlined )(ThreadId tid , BB * bb , const HChar * inl_fn )
500+ {
501+ Int i ;
502+
503+ if (!TG_ (trace_out ).initialized ) return ;
504+ if (TG_ (trace_out ).fd < 0 ) return ;
505+
506+ thread_info * ti = TG_ (get_current_thread )();
507+ if (!ti ) return ;
508+
509+ EventSet * es = TG_ (sets ).full ;
510+ FullCost current_cost = TG_ (current_state ).cost ;
511+
512+ if (!ti -> last_sample_cost ) {
513+ ti -> last_sample_cost = TG_ (get_eventset_cost )(es );
514+ TG_ (init_cost )(es , ti -> last_sample_cost );
515+ }
516+
517+ TG_ (trace_out ).seq ++ ;
518+
519+ const HChar * fn_name = inl_fn ;
520+ const HChar * obj_name = bb -> obj ? bb -> obj -> name : "???" ;
521+ const HChar * file_name = (bb -> fn && bb -> fn -> file ) ? bb -> fn -> file -> name : "???" ;
522+ UInt line = bb -> line ;
523+
524+ ULong deltas [64 ];
525+ tl_assert (es -> size <= 64 );
526+ if (current_cost && ti -> last_sample_cost ) {
527+ for (i = 0 ; i < es -> size ; i ++ ) {
528+ deltas [i ] = current_cost [i ] - ti -> last_sample_cost [i ];
529+ }
530+ TG_ (copy_cost )(es , ti -> last_sample_cost , current_cost );
531+ } else {
532+ for (i = 0 ; i < es -> size ; i ++ ) {
533+ deltas [i ] = 0 ;
534+ }
535+ }
536+
537+ msgpack_add_row (TG_ (trace_out ).seq , (Int )tid , TG_EV_EXIT_INLINED ,
538+ fn_name , obj_name , file_name , (Int )line ,
539+ deltas , es -> size );
540+ }
541+
442542/*
443543 * Emit a FORK event when a child process is created.
444544 * Called from the post-syscall handler when fork/clone returns in parent.
0 commit comments