@@ -23,6 +23,17 @@ static VALUE idAtCatchpoint;
2323static VALUE idFileFilter ;
2424static VALUE idAccept ;
2525
26+ static void
27+ print_debug (const char * message , ...)
28+ {
29+ va_list ap ;
30+
31+ if (verbose == Qfalse ) return ;
32+ va_start (ap , message );
33+ vfprintf (stderr , message , ap );
34+ va_end (ap );
35+ }
36+
2637static VALUE
2738is_path_accepted (VALUE path ) {
2839 VALUE filter ;
@@ -49,6 +60,82 @@ Debase_current_context(VALUE self)
4960 return Debase_thread_context (self , rb_thread_current ());
5061}
5162
63+ static int
64+ set_recalc_flag (VALUE thread , VALUE context_object , VALUE ignored )
65+ {
66+ debug_context_t * context ;
67+
68+ Data_Get_Struct (context_object , debug_context_t , context );
69+ CTX_FL_SET (context , CTX_FL_UPDATE_STACK );
70+
71+ return ST_CONTINUE ;
72+ }
73+
74+ static int
75+ can_disable_trace_points (VALUE thread , VALUE context_object , VALUE result )
76+ {
77+ debug_context_t * context ;
78+
79+ Data_Get_Struct (context_object , debug_context_t , context );
80+
81+ if (-1 != context -> dest_frame
82+ || context -> stop_line >= 0
83+ || -1 != context -> stop_next
84+ || context -> stop_reason != CTX_STOP_NONE
85+ || context -> thread_pause != 0 )
86+ {
87+ print_debug ("can_disable_tp: %d %d %d %d\n" , context -> dest_frame , context -> stop_line ,
88+ context -> stop_next , context -> stop_reason );
89+ * ((VALUE * ) result ) = Qfalse ;
90+ return ST_STOP ;
91+ }
92+ return ST_CONTINUE ;
93+ }
94+
95+ static void
96+ try_disable_trace_points ()
97+ {
98+ VALUE can_disable = Qtrue ;
99+
100+ if (RARRAY_LEN (breakpoints ) != 0 ) return ;
101+ print_debug ("disable_tps: no breakpoints\n" );
102+ if (RHASH_EMPTY_P (catchpoints )) return ;
103+ print_debug ("disable_tps: no catchpoints\n" );
104+ if (rb_tracepoint_enabled_p (tpLine ) == Qfalse ) return ;
105+ print_debug ("disable_tps: tps are enabled\n" );
106+
107+ rb_hash_foreach (contexts , can_disable_trace_points , (VALUE )& can_disable );
108+ if (can_disable == Qfalse ) return ;
109+ print_debug ("disable_tps: can disable contexts\n" );
110+
111+ rb_tracepoint_disable (tpLine );
112+ rb_tracepoint_disable (tpCall );
113+ rb_tracepoint_disable (tpReturn );
114+ rb_tracepoint_disable (tpRaise );
115+ rb_hash_foreach (contexts , set_recalc_flag , 0 );
116+ }
117+
118+ extern VALUE
119+ enable_trace_points ()
120+ {
121+ print_debug ("enable_tps: \n" );
122+ if (rb_tracepoint_enabled_p (tpLine ) == Qtrue ) return Qtrue ;
123+ print_debug ("enable_tps: need to enable\n" );
124+
125+ rb_tracepoint_enable (tpLine );
126+ rb_tracepoint_enable (tpCall );
127+ rb_tracepoint_enable (tpReturn );
128+ rb_tracepoint_enable (tpRaise );
129+
130+ return Qfalse ;
131+ }
132+
133+ static VALUE
134+ Debase_enable_trace_points (VALUE self )
135+ {
136+ return enable_trace_points ();
137+ }
138+
52139static int
53140remove_dead_threads (VALUE thread , VALUE context , VALUE ignored )
54141{
@@ -71,6 +158,8 @@ cleanup(debug_context_t *context)
71158 thread = remove_from_locked ();
72159 if (thread != Qnil )
73160 rb_thread_run (thread );
161+
162+ try_disable_trace_points ();
74163}
75164
76165static int
@@ -377,15 +466,18 @@ Debase_setup_tracepoints(VALUE self)
377466 catchpoints = rb_hash_new ();
378467
379468 tpLine = rb_tracepoint_new (Qnil , RUBY_EVENT_LINE , process_line_event , NULL );
380- rb_tracepoint_enable (tpLine );
381- tpReturn = rb_tracepoint_new (Qnil , RUBY_EVENT_RETURN | RUBY_EVENT_B_RETURN | RUBY_EVENT_C_RETURN | RUBY_EVENT_END ,
469+ rb_global_variable (& tpLine );
470+
471+ tpReturn = rb_tracepoint_new (Qnil , RUBY_EVENT_RETURN | RUBY_EVENT_B_RETURN | RUBY_EVENT_C_RETURN | RUBY_EVENT_END ,
382472 process_return_event , NULL );
383- rb_tracepoint_enable (tpReturn );
384- tpCall = rb_tracepoint_new (Qnil , RUBY_EVENT_CALL | RUBY_EVENT_B_CALL | RUBY_EVENT_C_CALL | RUBY_EVENT_CLASS ,
473+ rb_global_variable (& tpReturn );
474+
475+ tpCall = rb_tracepoint_new (Qnil , RUBY_EVENT_CALL | RUBY_EVENT_B_CALL | RUBY_EVENT_C_CALL | RUBY_EVENT_CLASS ,
385476 process_call_event , NULL );
386- rb_tracepoint_enable (tpCall );
477+ rb_global_variable (& tpCall );
478+
387479 tpRaise = rb_tracepoint_new (Qnil , RUBY_EVENT_RAISE , process_raise_event , NULL );
388- Debase_current_context ( self );
480+ rb_global_variable ( & tpRaise );
389481
390482 return Qnil ;
391483}
@@ -418,7 +510,10 @@ debase_prepare_context(VALUE self, VALUE file, VALUE stop)
418510 context_object = Debase_current_context (self );
419511 Data_Get_Struct (context_object , debug_context_t , context );
420512
421- if (RTEST (stop )) context -> stop_next = 1 ;
513+ if (RTEST (stop )) {
514+ context -> stop_next = 1 ;
515+ Debase_enable_trace_points (self );
516+ }
422517 ruby_script (RSTRING_PTR (file ));
423518 return self ;
424519}
@@ -510,18 +605,6 @@ Debase_set_verbose(VALUE self, VALUE value)
510605 return value ;
511606}
512607
513- /*
514- * call-seq:
515- * Debase.tp_raise -> TracePoint
516- *
517- * Returns trace point we use to track :raise events
518- */
519- static VALUE
520- Debase_get_tp_raise (VALUE self )
521- {
522- return tpRaise ;
523- }
524-
525608/*
526609 * Document-class: Debase
527610 *
@@ -541,10 +624,10 @@ Init_debase_internals()
541624 rb_define_module_function (mDebase , "contexts" , Debase_contexts , 0 );
542625 rb_define_module_function (mDebase , "breakpoints" , Debase_breakpoints , 0 );
543626 rb_define_module_function (mDebase , "catchpoints" , Debase_catchpoints , 0 );
544- rb_define_module_function (mDebase , "tp_raise" , Debase_get_tp_raise , 0 );
545627 rb_define_module_function (mDebase , "started?" , Debase_started , 0 );
546628 rb_define_module_function (mDebase , "verbose?" , Debase_verbose , 0 );
547629 rb_define_module_function (mDebase , "verbose=" , Debase_set_verbose , 1 );
630+ rb_define_module_function (mDebase , "enable_trace_points" , Debase_enable_trace_points , 0 );
548631
549632 idAlive = rb_intern ("alive?" );
550633 idAtLine = rb_intern ("at_line" );
0 commit comments