@@ -48,8 +48,41 @@ pub struct InterpCx<'mir, 'tcx, M: Machine<'mir, 'tcx>> {
4848 FxHashMap < ( Ty < ' tcx > , Option < ty:: PolyExistentialTraitRef < ' tcx > > ) , Pointer < M :: PointerTag > > ,
4949}
5050
51+ // The Phantomdata exists to prevent this type from being `Send`. If it were sent across a thread
52+ // boundary and dropped in the other thread, it would exit the span in the other thread.
53+ struct SpanGuard ( tracing:: Span , std:: marker:: PhantomData < * const u8 > ) ;
54+
55+ impl SpanGuard {
56+ /// By default a `SpanGuard` does nothing.
57+ fn new ( ) -> Self {
58+ Self ( tracing:: Span :: none ( ) , std:: marker:: PhantomData )
59+ }
60+
61+ /// If a span is entered, we exit the previous span (if any, normally none) and enter the
62+ /// new span. This is mainly so we don't have to use `Option` for the `tracing_span` field of
63+ /// `Frame` by creating a dummy span to being with and then entering it once the frame has
64+ /// been pushed.
65+ fn enter ( & mut self , span : tracing:: Span ) {
66+ // This executes the destructor on the previous instance of `SpanGuard`, ensuring that
67+ // we never enter or exit more spans than vice versa. Unless you `mem::leak`, then we
68+ // can't protect the tracing stack, but that'll just lead to weird logging, no actual
69+ // problems.
70+ * self = Self ( span, std:: marker:: PhantomData ) ;
71+ self . 0 . with_subscriber ( |( id, dispatch) | {
72+ dispatch. enter ( id) ;
73+ } ) ;
74+ }
75+ }
76+
77+ impl Drop for SpanGuard {
78+ fn drop ( & mut self ) {
79+ self . 0 . with_subscriber ( |( id, dispatch) | {
80+ dispatch. exit ( id) ;
81+ } ) ;
82+ }
83+ }
84+
5185/// A stack frame.
52- #[ derive( Clone ) ]
5386pub struct Frame < ' mir , ' tcx , Tag = ( ) , Extra = ( ) > {
5487 ////////////////////////////////////////////////////////////////////////////////
5588 // Function and callsite information
@@ -80,6 +113,11 @@ pub struct Frame<'mir, 'tcx, Tag = (), Extra = ()> {
80113 /// can either directly contain `Scalar` or refer to some part of an `Allocation`.
81114 pub locals : IndexVec < mir:: Local , LocalState < ' tcx , Tag > > ,
82115
116+ /// The span of the `tracing` crate is stored here.
117+ /// When the guard is dropped, the span is exited. This gives us
118+ /// a full stack trace on all tracing statements.
119+ tracing_span : SpanGuard ,
120+
83121 ////////////////////////////////////////////////////////////////////////////////
84122 // Current position within the function
85123 ////////////////////////////////////////////////////////////////////////////////
@@ -184,6 +222,7 @@ impl<'mir, 'tcx, Tag> Frame<'mir, 'tcx, Tag> {
184222 locals : self . locals ,
185223 loc : self . loc ,
186224 extra,
225+ tracing_span : self . tracing_span ,
187226 }
188227 }
189228}
@@ -637,11 +676,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
637676 return_place : Option < PlaceTy < ' tcx , M :: PointerTag > > ,
638677 return_to_block : StackPopCleanup ,
639678 ) -> InterpResult < ' tcx > {
640- if !self . stack ( ) . is_empty ( ) {
641- info ! ( "PAUSING({}) {}" , self . frame_idx( ) , self . frame( ) . instance) ;
642- }
643- :: log_settings:: settings ( ) . indentation += 1 ;
644-
645679 // first push a stack frame so we have access to the local substs
646680 let pre_frame = Frame {
647681 body,
@@ -652,6 +686,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
652686 // all methods actually know about the frame
653687 locals : IndexVec :: new ( ) ,
654688 instance,
689+ tracing_span : SpanGuard :: new ( ) ,
655690 extra : ( ) ,
656691 } ;
657692 let frame = M :: init_frame_extra ( self , pre_frame) ?;
@@ -696,7 +731,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
696731 self . frame_mut ( ) . locals = locals;
697732 M :: after_stack_push ( self ) ?;
698733 self . frame_mut ( ) . loc = Ok ( mir:: Location :: START ) ;
699- info ! ( "ENTERING({}) {}" , self . frame_idx( ) , self . frame( ) . instance) ;
734+
735+ let span = info_span ! ( "frame" , "{}" , instance) ;
736+ self . frame_mut ( ) . tracing_span . enter ( span) ;
700737
701738 Ok ( ( ) )
702739 }
@@ -746,12 +783,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
746783 /// The cleanup block ends with a special `Resume` terminator, which will
747784 /// cause us to continue unwinding.
748785 pub ( super ) fn pop_stack_frame ( & mut self , unwinding : bool ) -> InterpResult < ' tcx > {
749- info ! (
750- "LEAVING({}) {} (unwinding = {})" ,
751- self . frame_idx( ) ,
752- self . frame( ) . instance,
753- unwinding
754- ) ;
786+ info ! ( unwinding) ;
755787
756788 // Sanity check `unwinding`.
757789 assert_eq ! (
@@ -766,7 +798,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
766798 throw_ub_format ! ( "unwinding past the topmost frame of the stack" ) ;
767799 }
768800
769- :: log_settings:: settings ( ) . indentation -= 1 ;
770801 let frame =
771802 self . stack_mut ( ) . pop ( ) . expect ( "tried to pop a stack frame, but there were none" ) ;
772803
@@ -824,12 +855,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
824855 }
825856
826857 if !self . stack ( ) . is_empty ( ) {
827- info ! (
828- "CONTINUING({}) {} (unwinding = {})" ,
829- self . frame_idx( ) ,
830- self . frame( ) . instance,
831- unwinding
832- ) ;
858+ info ! ( unwinding) ;
833859 }
834860
835861 Ok ( ( ) )
@@ -995,7 +1021,16 @@ where
9951021{
9961022 fn hash_stable ( & self , hcx : & mut StableHashingContext < ' ctx > , hasher : & mut StableHasher ) {
9971023 // Exhaustive match on fields to make sure we forget no field.
998- let Frame { body, instance, return_to_block, return_place, locals, loc, extra } = self ;
1024+ let Frame {
1025+ body,
1026+ instance,
1027+ return_to_block,
1028+ return_place,
1029+ locals,
1030+ loc,
1031+ extra,
1032+ tracing_span : _,
1033+ } = self ;
9991034 body. hash_stable ( hcx, hasher) ;
10001035 instance. hash_stable ( hcx, hasher) ;
10011036 return_to_block. hash_stable ( hcx, hasher) ;
0 commit comments