Ruby  2.0.0p353(2013-11-22revision43784)
vm_trace.c
Go to the documentation of this file.
1 /**********************************************************************
2 
3  vm_trace.c -
4 
5  $Author: ko1 $
6  created at: Tue Aug 14 19:37:09 2012
7 
8  Copyright (C) 1993-2012 Yukihiro Matsumoto
9 
10 **********************************************************************/
11 
12 /*
13  * This file incldue two parts:
14  *
15  * (1) set_trace_func internal mechanisms
16  * and C level API
17  *
18  * (2) Ruby level API
19  * (2-1) set_trace_func API
20  * (2-2) TracePoint API (not yet)
21  *
22  */
23 
24 #include "ruby/ruby.h"
25 #include "ruby/debug.h"
26 #include "ruby/encoding.h"
27 
28 #include "internal.h"
29 #include "vm_core.h"
30 #include "eval_intern.h"
31 
32 /* (1) trace mechanisms */
33 
34 typedef struct rb_event_hook_struct {
41 
43 
44 #define MAX_EVENT_NUM 32
45 
47 
48 /* called from vm.c */
49 
50 void
52 {
53  rb_event_hook_t *hook = hooks->hooks;
54 
55  while (hook) {
56  rb_gc_mark(hook->data);
57  hook = hook->next;
58  }
59 }
60 
61 /* ruby_vm_event_flags management */
62 
63 static void
65 {
66  int i;
68 
69  for (i=0; i<MAX_EVENT_NUM; i++) {
70  if (events & (1 << i)) {
72  }
74  }
75 }
76 
77 static void
79 {
80  int i;
82 
83  for (i=0; i<MAX_EVENT_NUM; i++) {
84  if (events & (1 << i)) {
86  }
88  }
89 }
90 
91 /* add/remove hooks */
92 
93 static rb_thread_t *
95 {
96  rb_thread_t *th;
97  GetThreadPtr(thval, th);
98  return th;
99 }
100 
101 static rb_event_hook_t *
103 {
105  hook->hook_flags = hook_flags;
106  hook->events = events;
107  hook->func = func;
108  hook->data = data;
109  return hook;
110 }
111 
112 static void
114 {
115  hook->next = list->hooks;
116  list->hooks = hook;
118  list->events |= hook->events;
119 }
120 
121 static void
123 {
124  rb_event_hook_t *hook = alloc_event_hook(func, events, data, hook_flags);
125  connect_event_hook(&th->event_hooks, hook);
126 }
127 
128 void
130 {
132 }
133 
134 void
136 {
137  rb_event_hook_t *hook = alloc_event_hook(func, events, data, RUBY_EVENT_HOOK_FLAG_SAFE);
138  connect_event_hook(&GET_VM()->event_hooks, hook);
139 }
140 
141 void
143 {
144  rb_threadptr_add_event_hook(thval2thread_t(thval), func, events, data, hook_flags);
145 }
146 
147 void
149 {
150  rb_event_hook_t *hook = alloc_event_hook(func, events, data, hook_flags);
151  connect_event_hook(&GET_VM()->event_hooks, hook);
152 }
153 
154 /* if func is 0, then clear all funcs */
155 static int
157 {
158  int ret = 0;
159  rb_event_hook_t *hook = list->hooks;
160 
161  while (hook) {
162  if (func == 0 || hook->func == func) {
163  if (data == Qundef || hook->data == data) {
165  ret+=1;
166  list->need_clean++;
167  }
168  }
169  hook = hook->next;
170  }
171 
172  return ret;
173 }
174 
175 static int
177 {
178  return remove_event_hook(&th->event_hooks, func, data);
179 }
180 
181 int
183 {
185 }
186 
187 int
189 {
190  return rb_threadptr_remove_event_hook(thval2thread_t(thval), func, data);
191 }
192 
193 int
195 {
196  return remove_event_hook(&GET_VM()->event_hooks, func, Qundef);
197 }
198 
199 int
201 {
202  return remove_event_hook(&GET_VM()->event_hooks, func, data);
203 }
204 
205 static int
207 {
208  rb_thread_t *th;
209  GetThreadPtr((VALUE)key, th);
211  return ST_CONTINUE;
212 }
213 
214 void
216 {
217  st_foreach(GET_VM()->living_threads, clear_trace_func_i, (st_data_t) 0);
219 }
220 
221 /* invoke hooks */
222 
223 static void
225 {
226  rb_event_hook_t *hook, **nextp = &list->hooks;
227 
228  list->events = 0;
229  list->need_clean = 0;
230 
231  while ((hook = *nextp) != 0) {
233  *nextp = hook->next;
235  xfree(hook);
236  }
237  else {
238  list->events |= hook->events; /* update active events */
239  nextp = &hook->next;
240  }
241  }
242 }
243 
244 static int
245 exec_hooks(rb_thread_t *th, rb_hook_list_t *list, const rb_trace_arg_t *trace_arg, int can_clean_hooks)
246 {
247  int state;
248  volatile int raised;
249 
250  if (UNLIKELY(list->need_clean > 0) && can_clean_hooks) {
251  clean_hooks(list);
252  }
253 
254  raised = rb_threadptr_reset_raised(th);
255 
256  /* TODO: Support !RUBY_EVENT_HOOK_FLAG_SAFE hooks */
257 
258  TH_PUSH_TAG(th);
259  if ((state = TH_EXEC_TAG()) == 0) {
260  rb_event_hook_t *hook;
261 
262  for (hook = list->hooks; hook; hook = hook->next) {
263  if (LIKELY(!(hook->hook_flags & RUBY_EVENT_HOOK_FLAG_DELETED)) && (trace_arg->event & hook->events)) {
264  if (!(hook->hook_flags & RUBY_EVENT_HOOK_FLAG_RAW_ARG)) {
265  (*hook->func)(trace_arg->event, hook->data, trace_arg->self, trace_arg->id, trace_arg->klass);
266  }
267  else {
268  (*((rb_event_hook_raw_arg_func_t)hook->func))(hook->data, trace_arg);
269  }
270  }
271  }
272  }
273  TH_POP_TAG();
274 
275  if (raised) {
277  }
278 
279  return state;
280 }
281 
282 static void
284 {
285  rb_thread_t *th = trace_arg->th;
286  if (th->trace_arg == 0 &&
287  trace_arg->self != rb_mRubyVMFrozenCore /* skip special methods. TODO: remove it. */) {
288  const int vm_tracing = th->vm->trace_running;
289  const VALUE errinfo = th->errinfo;
290  const int outer_state = th->state;
291  int state = 0;
292  th->state = 0;
293 
294  th->vm->trace_running++;
295  th->trace_arg = trace_arg;
296  {
298 
299  /* thread local traces */
300  list = &th->event_hooks;
301  if (list->events & trace_arg->event) {
302  state = exec_hooks(th, list, trace_arg, TRUE);
303  if (state) goto terminate;
304  }
305 
306  /* vm global traces */
307  list = &th->vm->event_hooks;
308  if (list->events & trace_arg->event) {
309  state = exec_hooks(th, list, trace_arg, !vm_tracing);
310  if (state) goto terminate;
311  }
312  th->errinfo = errinfo;
313  }
314  terminate:
315  th->trace_arg = 0;
316  th->vm->trace_running--;
317 
318  if (state) {
319  if (pop_p) {
320  if (VM_FRAME_TYPE_FINISH_P(th->cfp)) {
321  th->tag = th->tag->prev;
322  }
324  }
325  TH_JUMP_TAG(th, state);
326  }
327  th->state = outer_state;
328  }
329 }
330 
331 void
333 {
335 }
336 
337 void
339 {
341 }
342 
343 VALUE
345 {
346  volatile int raised;
347  volatile int outer_state;
348  VALUE result = Qnil;
349  rb_thread_t *th = GET_THREAD();
350  int state;
351  const int tracing = th->trace_arg ? 1 : 0;
352  rb_trace_arg_t dummy_trace_arg;
353 
354  if (!tracing) th->vm->trace_running++;
355  if (!th->trace_arg) th->trace_arg = &dummy_trace_arg;
356 
357  raised = rb_threadptr_reset_raised(th);
358  outer_state = th->state;
359  th->state = 0;
360 
361  TH_PUSH_TAG(th);
362  if ((state = TH_EXEC_TAG()) == 0) {
363  result = (*func)(arg);
364  }
365  TH_POP_TAG();
366 
367  if (raised) {
369  }
370 
371  if (th->trace_arg == &dummy_trace_arg) th->trace_arg = 0;
372  if (!tracing) th->vm->trace_running--;
373 
374  if (state) {
375  JUMP_TAG(state);
376  }
377 
378  th->state = outer_state;
379  return result;
380 }
381 
382 static void call_trace_func(rb_event_flag_t, VALUE data, VALUE self, ID id, VALUE klass);
383 
384 /* (2-1) set_trace_func (old API) */
385 
386 /*
387  * call-seq:
388  * set_trace_func(proc) -> proc
389  * set_trace_func(nil) -> nil
390  *
391  * Establishes _proc_ as the handler for tracing, or disables
392  * tracing if the parameter is +nil+.
393  *
394  * _proc_ takes up to six parameters:
395  *
396  * * an event name
397  * * a filename
398  * * a line number
399  * * an object id
400  * * a binding
401  * * the name of a class
402  *
403  * _proc_ is invoked whenever an event occurs.
404  *
405  * Events are:
406  *
407  * +c-call+:: call a C-language routine
408  * +c-return+:: return from a C-language routine
409  * +call+:: call a Ruby method
410  * +class+:: start a class or module definition),
411  * +end+:: finish a class or module definition),
412  * +line+:: execute code on a new line
413  * +raise+:: raise an exception
414  * +return+:: return from a Ruby method
415  *
416  * Tracing is disabled within the context of _proc_.
417  *
418  * class Test
419  * def test
420  * a = 1
421  * b = 2
422  * end
423  * end
424  *
425  * set_trace_func proc { |event, file, line, id, binding, classname|
426  * printf "%8s %s:%-2d %10s %8s\n", event, file, line, id, classname
427  * }
428  * t = Test.new
429  * t.test
430  *
431  * line prog.rb:11 false
432  * c-call prog.rb:11 new Class
433  * c-call prog.rb:11 initialize Object
434  * c-return prog.rb:11 initialize Object
435  * c-return prog.rb:11 new Class
436  * line prog.rb:12 false
437  * call prog.rb:2 test Test
438  * line prog.rb:3 test Test
439  * line prog.rb:4 test Test
440  * return prog.rb:4 test Test
441  */
442 
443 static VALUE
445 {
446  rb_secure(4);
447 
449 
450  if (NIL_P(trace)) {
451  return Qnil;
452  }
453 
454  if (!rb_obj_is_proc(trace)) {
455  rb_raise(rb_eTypeError, "trace_func needs to be Proc");
456  }
457 
459  return trace;
460 }
461 
462 static void
464 {
465  if (!rb_obj_is_proc(trace)) {
466  rb_raise(rb_eTypeError, "trace_func needs to be Proc");
467  }
468 
470 }
471 
472 /*
473  * call-seq:
474  * thr.add_trace_func(proc) -> proc
475  *
476  * Adds _proc_ as a handler for tracing.
477  * See <code>Thread#set_trace_func</code> and +set_trace_func+.
478  */
479 
480 static VALUE
482 {
483  rb_thread_t *th;
484 
485  rb_secure(4);
486  GetThreadPtr(obj, th);
487  thread_add_trace_func(th, trace);
488  return trace;
489 }
490 
491 /*
492  * call-seq:
493  * thr.set_trace_func(proc) -> proc
494  * thr.set_trace_func(nil) -> nil
495  *
496  * Establishes _proc_ on _thr_ as the handler for tracing, or
497  * disables tracing if the parameter is +nil+.
498  * See +set_trace_func+.
499  */
500 
501 static VALUE
503 {
504  rb_thread_t *th;
505 
506  rb_secure(4);
507  GetThreadPtr(obj, th);
509 
510  if (NIL_P(trace)) {
511  return Qnil;
512  }
513 
514  thread_add_trace_func(th, trace);
515  return trace;
516 }
517 
518 static const char *
520 {
521  switch (event) {
522  case RUBY_EVENT_LINE: return "line";
523  case RUBY_EVENT_CLASS: return "class";
524  case RUBY_EVENT_END: return "end";
525  case RUBY_EVENT_CALL: return "call";
526  case RUBY_EVENT_RETURN: return "return";
527  case RUBY_EVENT_C_CALL: return "c-call";
528  case RUBY_EVENT_C_RETURN: return "c-return";
529  case RUBY_EVENT_RAISE: return "raise";
530  default:
531  return "unknown";
532  }
533 }
534 
535 static ID
537 {
538  ID id;
539 
540  switch (event) {
541 #define C(name, NAME) case RUBY_EVENT_##NAME: CONST_ID(id, #name); return id;
542  C(line, LINE);
543  C(class, CLASS);
544  C(end, END);
545  C(call, CALL);
546  C(return, RETURN);
547  C(c_call, C_CALL);
548  C(c_return, C_RETURN);
549  C(raise, RAISE);
550  C(b_call, B_CALL);
551  C(b_return, B_RETURN);
552  C(thread_begin, THREAD_BEGIN);
553  C(thread_end, THREAD_END);
554  C(specified_line, SPECIFIED_LINE);
555  case RUBY_EVENT_LINE | RUBY_EVENT_SPECIFIED_LINE: CONST_ID(id, "line"); return id;
556 #undef C
557  default:
558  return 0;
559  }
560 }
561 
562 static void
563 call_trace_func(rb_event_flag_t event, VALUE proc, VALUE self, ID id, VALUE klass)
564 {
565  const char *srcfile = rb_sourcefile();
566  VALUE eventname = rb_str_new2(get_event_name(event));
567  VALUE filename = srcfile ? rb_str_new2(srcfile) : Qnil;
568  VALUE argv[6];
569  int line = rb_sourceline();
570  rb_thread_t *th = GET_THREAD();
571 
572  if (!klass) {
573  rb_thread_method_id_and_class(th, &id, &klass);
574  }
575 
576  if (klass) {
577  if (RB_TYPE_P(klass, T_ICLASS)) {
578  klass = RBASIC(klass)->klass;
579  }
580  else if (FL_TEST(klass, FL_SINGLETON)) {
581  klass = rb_iv_get(klass, "__attached__");
582  }
583  }
584 
585  argv[0] = eventname;
586  argv[1] = filename;
587  argv[2] = INT2FIX(line);
588  argv[3] = id ? ID2SYM(id) : Qnil;
589  argv[4] = (self && srcfile) ? rb_binding_new() : Qnil;
590  argv[5] = klass ? klass : Qnil;
591 
592  rb_proc_call_with_block(proc, 6, argv, Qnil);
593 }
594 
595 /* (2-2) TracePoint API */
596 
598 
599 typedef struct rb_tp_struct {
602  void (*func)(VALUE tpval, void *data);
603  void *data;
605  int tracing;
606  VALUE self;
607 } rb_tp_t;
608 
609 static void
610 tp_mark(void *ptr)
611 {
612  if (ptr) {
613  rb_tp_t *tp = (rb_tp_t *)ptr;
614  rb_gc_mark(tp->proc);
615  if (tp->target_th) rb_gc_mark(tp->target_th->self);
616  }
617 }
618 
619 static void
620 tp_free(void *ptr)
621 {
622  /* do nothing */
623 }
624 
625 static size_t
626 tp_memsize(const void *ptr)
627 {
628  return sizeof(rb_tp_t);
629 }
630 
631 static const rb_data_type_t tp_data_type = {
632  "tracepoint",
634 };
635 
636 static VALUE
638 {
639  rb_tp_t *tp;
640  return TypedData_Make_Struct(klass, rb_tp_t, &tp_data_type, tp);
641 }
642 
643 static rb_event_flag_t
645 {
646  static ID id;
647  VALUE sym = rb_convert_type(v, T_SYMBOL, "Symbol", "to_sym");
648 
649 #define C(name, NAME) CONST_ID(id, #name); if (sym == ID2SYM(id)) return RUBY_EVENT_##NAME
650  C(line, LINE);
651  C(class, CLASS);
652  C(end, END);
653  C(call, CALL);
654  C(return, RETURN);
655  C(c_call, C_CALL);
656  C(c_return, C_RETURN);
657  C(raise, RAISE);
658  C(b_call, B_CALL);
659  C(b_return, B_RETURN);
660  C(thread_begin, THREAD_BEGIN);
661  C(thread_end, THREAD_END);
662  C(specified_line, SPECIFIED_LINE);
663 #undef C
664  rb_raise(rb_eArgError, "unknown event: %s", rb_id2name(SYM2ID(sym)));
665 }
666 
667 static rb_tp_t *
668 tpptr(VALUE tpval)
669 {
670  rb_tp_t *tp;
671  TypedData_Get_Struct(tpval, rb_tp_t, &tp_data_type, tp);
672  return tp;
673 }
674 
675 static rb_trace_arg_t *
677 {
678  rb_trace_arg_t *trace_arg = GET_THREAD()->trace_arg;
679  if (trace_arg == 0) {
680  rb_raise(rb_eRuntimeError, "access from outside");
681  }
682  return trace_arg;
683 }
684 
685 struct rb_trace_arg_struct *
687 {
688  return get_trace_arg();
689 }
690 
691 VALUE
693 {
694  return ID2SYM(get_event_id(trace_arg->event));
695 }
696 
697 static void
699 {
700  if (trace_arg->path == Qundef) {
701  rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(trace_arg->th, trace_arg->cfp);
702 
703  if (cfp) {
704  trace_arg->path = cfp->iseq->location.path;
705  trace_arg->lineno = rb_vm_get_sourceline(cfp);
706  }
707  else {
708  trace_arg->path = Qnil;
709  trace_arg->lineno = 0;
710  }
711  }
712 }
713 
714 VALUE
716 {
717  fill_path_and_lineno(trace_arg);
718  return INT2FIX(trace_arg->lineno);
719 }
720 VALUE
722 {
723  fill_path_and_lineno(trace_arg);
724  return trace_arg->path;
725 }
726 
727 static void
729 {
730  if (!trace_arg->klass_solved) {
731  if (!trace_arg->klass) {
732  rb_vm_control_frame_id_and_class(trace_arg->cfp, &trace_arg->id, &trace_arg->klass);
733  }
734 
735  if (trace_arg->klass) {
736  if (RB_TYPE_P(trace_arg->klass, T_ICLASS)) {
737  trace_arg->klass = RBASIC(trace_arg->klass)->klass;
738  }
739  }
740  else {
741  trace_arg->klass = Qnil;
742  }
743 
744  trace_arg->klass_solved = 1;
745  }
746 }
747 
748 VALUE
750 {
751  fill_id_and_klass(trace_arg);
752  return trace_arg->id ? ID2SYM(trace_arg->id) : Qnil;
753 }
754 
755 VALUE
757 {
758  fill_id_and_klass(trace_arg);
759  return trace_arg->klass;
760 }
761 
762 VALUE
764 {
766  cfp = rb_vm_get_binding_creatable_next_cfp(trace_arg->th, trace_arg->cfp);
767 
768  if (cfp) {
769  return rb_binding_new_with_cfp(trace_arg->th, cfp);
770  }
771  else {
772  return Qnil;
773  }
774 }
775 
776 VALUE
778 {
779  return trace_arg->self;
780 }
781 
782 VALUE
784 {
786  /* ok */
787  }
788  else {
789  rb_raise(rb_eRuntimeError, "not supported by this event");
790  }
791  if (trace_arg->data == Qundef) {
792  rb_bug("tp_attr_return_value_m: unreachable");
793  }
794  return trace_arg->data;
795 }
796 
797 VALUE
799 {
800  if (trace_arg->event & (RUBY_EVENT_RAISE)) {
801  /* ok */
802  }
803  else {
804  rb_raise(rb_eRuntimeError, "not supported by this event");
805  }
806  if (trace_arg->data == Qundef) {
807  rb_bug("tp_attr_raised_exception_m: unreachable");
808  }
809  return trace_arg->data;
810 }
811 
812 /*
813  * Type of event
814  *
815  * See TracePoint@Events for more information.
816  */
817 static VALUE
819 {
821 }
822 
823 /*
824  * Line number of the event
825  */
826 static VALUE
828 {
830 }
831 
832 /*
833  * Path of the file being run
834  */
835 static VALUE
837 {
839 }
840 
841 /*
842  * Return the name of the method being called
843  */
844 static VALUE
846 {
848 }
849 
850 /*
851  * Return class or module of the method being called.
852  *
853  * class C; def foo; end; end
854  * trace = TracePoint.new(:call) do |tp|
855  * p tp.defined_class #=> C
856  * end.enable do
857  * C.new.foo
858  * end
859  *
860  * If method is defined by a module, then that module is returned.
861  *
862  * module M; def foo; end; end
863  * class C; include M; end;
864  * trace = TracePoint.new(:call) do |tp|
865  * p tp.defined_class #=> M
866  * end.enable do
867  * C.new.foo
868  * end
869  *
870  * <b>Note:</b> #defined_class returns singleton class.
871  *
872  * 6th block parameter of Kernel#set_trace_func passes original class
873  * of attached by singleton class.
874  *
875  * <b>This is a difference between Kernel#set_trace_func and TracePoint.</b>
876  *
877  * class C; def self.foo; end; end
878  * trace = TracePoint.new(:call) do |tp|
879  * p tp.defined_class #=> #<Class:C>
880  * end.enable do
881  * C.foo
882  * end
883  */
884 static VALUE
886 {
888 }
889 
890 /*
891  * Return the generated binding object from event
892  */
893 static VALUE
895 {
897 }
898 
899 /*
900  * Return the trace object during event
901  *
902  * Same as TracePoint#binding:
903  * trace.binding.eval('self')
904  */
905 static VALUE
907 {
909 }
910 
911 /*
912  * Return value from +:return+, +c_return+, and +b_return+ event
913  */
914 static VALUE
916 {
918 }
919 
920 /*
921  * Value from exception raised on the +:raise+ event
922  */
923 static VALUE
925 {
927 }
928 
929 static void
931 {
932  rb_tp_t *tp = tpptr(tpval);
933 
934  if (tp->func) {
935  (*tp->func)(tpval, tp->data);
936  }
937  else {
938  rb_proc_call_with_block((VALUE)tp->proc, 1, &tpval, Qnil);
939  }
940 }
941 
942 VALUE
944 {
945  rb_tp_t *tp;
946 
947  rb_secure(4);
948  tp = tpptr(tpval);
949 
950  if (tp->target_th) {
953  }
954  else {
957  }
958  tp->tracing = 1;
959  return Qundef;
960 }
961 
962 VALUE
964 {
965  rb_tp_t *tp;
966 
967  rb_secure(4);
968  tp = tpptr(tpval);
969 
970  if (tp->target_th) {
972  }
973  else {
975  }
976  tp->tracing = 0;
977  return Qundef;
978 }
979 
980 /*
981  * call-seq:
982  * trace.enable -> true or false
983  * trace.enable { block } -> obj
984  *
985  * Activates the trace
986  *
987  * Return true if trace was enabled.
988  * Return false if trace was disabled.
989  *
990  * trace.enabled? #=> false
991  * trace.enable #=> false (previous state)
992  * # trace is enabled
993  * trace.enabled? #=> true
994  * trace.enable #=> true (previous state)
995  * # trace is still enabled
996  *
997  * If a block is given, the trace will only be enabled within the scope of the
998  * block.
999  *
1000  * trace.enabled?
1001  * #=> false
1002  *
1003  * trace.enable do
1004  * trace.enabled?
1005  * # only enabled for this block
1006  * end
1007  *
1008  * trace.enabled?
1009  * #=> false
1010  *
1011  * Note: You cannot access event hooks within the block.
1012  *
1013  * trace.enable { p tp.lineno }
1014  * #=> RuntimeError: access from outside
1015  *
1016  */
1017 static VALUE
1019 {
1020  rb_tp_t *tp = tpptr(tpval);
1021  int previous_tracing = tp->tracing;
1022  rb_tracepoint_enable(tpval);
1023 
1024  if (rb_block_given_p()) {
1025  return rb_ensure(rb_yield, Qnil,
1026  previous_tracing ? rb_tracepoint_enable : rb_tracepoint_disable,
1027  tpval);
1028  }
1029  else {
1030  return previous_tracing ? Qtrue : Qfalse;
1031  }
1032 }
1033 
1034 /*
1035  * call-seq:
1036  * trace.disable -> true or false
1037  * trace.disable { block } -> obj
1038  *
1039  * Deactivates the trace
1040  *
1041  * Return true if trace was enabled.
1042  * Return false if trace was disabled.
1043  *
1044  * trace.enabled? #=> true
1045  * trace.disable #=> false (previous status)
1046  * trace.enabled? #=> false
1047  * trace.disable #=> false
1048  *
1049  * If a block is given, the trace will only be disable within the scope of the
1050  * block.
1051  *
1052  * trace.enabled?
1053  * #=> true
1054  *
1055  * trace.disable do
1056  * trace.enabled?
1057  * # only disabled for this block
1058  * end
1059  *
1060  * trace.enabled?
1061  * #=> true
1062  *
1063  * Note: You cannot access event hooks within the block.
1064  *
1065  * trace.disable { p tp.lineno }
1066  * #=> RuntimeError: access from outside
1067  */
1068 static VALUE
1070 {
1071  rb_tp_t *tp = tpptr(tpval);
1072  int previous_tracing = tp->tracing;
1073  rb_tracepoint_disable(tpval);
1074 
1075  if (rb_block_given_p()) {
1076  return rb_ensure(rb_yield, Qnil,
1077  previous_tracing ? rb_tracepoint_enable : rb_tracepoint_disable,
1078  tpval);
1079  }
1080  else {
1081  return previous_tracing ? Qtrue : Qfalse;
1082  }
1083 }
1084 
1085 /*
1086  * call-seq:
1087  * trace.enabled? -> true or false
1088  *
1089  * The current status of the trace
1090  */
1091 VALUE
1093 {
1094  rb_tp_t *tp = tpptr(tpval);
1095  return tp->tracing ? Qtrue : Qfalse;
1096 }
1097 
1098 static VALUE
1099 tracepoint_new(VALUE klass, rb_thread_t *target_th, rb_event_flag_t events, void (func)(VALUE, void*), void *data, VALUE proc)
1100 {
1101  VALUE tpval = tp_alloc(klass);
1102  rb_tp_t *tp;
1103  TypedData_Get_Struct(tpval, rb_tp_t, &tp_data_type, tp);
1104 
1105  tp->proc = proc;
1106  tp->func = func;
1107  tp->data = data;
1108  tp->events = events;
1109  tp->self = tpval;
1110 
1111  return tpval;
1112 }
1113 
1114 VALUE
1115 rb_tracepoint_new(VALUE target_thval, rb_event_flag_t events, void (*func)(VALUE, void *), void *data)
1116 {
1117  rb_thread_t *target_th = 0;
1118  if (RTEST(target_thval)) {
1119  GetThreadPtr(target_thval, target_th);
1120  /* TODO: Test it!
1121  * Warning: This function is not tested.
1122  */
1123  }
1124  return tracepoint_new(rb_cTracePoint, target_th, events, func, data, Qundef);
1125 }
1126 
1127 /*
1128  * call-seq:
1129  * TracePoint.new(*events) { |obj| block } -> obj
1130  *
1131  * Returns a new TracePoint object, not enabled by default.
1132  *
1133  * Next, in order to activate the trace, you must use TracePoint.enable
1134  *
1135  * trace = TracePoint.new(:call) do |tp|
1136  * p [tp.lineno, tp.defined_class, tp.method_id, tp.event]
1137  * end
1138  * #=> #<TracePoint:0x007f17372cdb20>
1139  *
1140  * trace.enable
1141  * #=> #<TracePoint:0x007f17372cdb20>
1142  *
1143  * puts "Hello, TracePoint!"
1144  * # ...
1145  * # [48, IRB::Notifier::AbstractNotifier, :printf, :call]
1146  * # ...
1147  *
1148  * When you want to deactivate the trace, you must use TracePoint.disable
1149  *
1150  * trace.disable
1151  *
1152  * See TracePoint@Events for possible events and more information.
1153  *
1154  * A block must be given, otherwise a ThreadError is raised.
1155  *
1156  * If the trace method isn't included in the given events filter, a
1157  * RuntimeError is raised.
1158  *
1159  * TracePoint.trace(:line) do |tp|
1160  * p tp.raised_exception
1161  * end
1162  * #=> RuntimeError: 'raised_exception' not supported by this event
1163  *
1164  * If the trace method is called outside block, a RuntimeError is raised.
1165  *
1166  * TracePoint.trace(:line) do |tp|
1167  * $tp = tp
1168  * end
1169  * $tp.line #=> access from outside (RuntimeError)
1170  *
1171  * Access from other threads is also forbidden.
1172  *
1173  */
1174 static VALUE
1176 {
1177  rb_event_flag_t events = 0;
1178  int i;
1179 
1180  if (argc > 0) {
1181  for (i=0; i<argc; i++) {
1182  events |= symbol2event_flag(argv[i]);
1183  }
1184  }
1185  else {
1186  events = RUBY_EVENT_TRACEPOINT_ALL;
1187  }
1188 
1189  if (!rb_block_given_p()) {
1190  rb_raise(rb_eThreadError, "must be called with a block");
1191  }
1192 
1193  return tracepoint_new(self, 0, events, 0, 0, rb_block_proc());
1194 }
1195 
1196 static VALUE
1198 {
1199  VALUE trace = tracepoint_new_s(argc, argv, self);
1200  rb_tracepoint_enable(trace);
1201  return trace;
1202 }
1203 
1204 /*
1205  * call-seq:
1206  * trace.inspect -> string
1207  *
1208  * Return a string containing a human-readable TracePoint
1209  * status.
1210  */
1211 
1212 static VALUE
1214 {
1215  rb_tp_t *tp = tpptr(self);
1216  rb_trace_arg_t *trace_arg = GET_THREAD()->trace_arg;
1217 
1218  if (trace_arg) {
1219  switch (trace_arg->event) {
1220  case RUBY_EVENT_LINE:
1222  {
1223  VALUE sym = rb_tracearg_method_id(trace_arg);
1224  if (NIL_P(sym))
1225  goto default_inspect;
1226  return rb_sprintf("#<TracePoint:%"PRIsVALUE"@%"PRIsVALUE":%d in `%"PRIsVALUE"'>",
1227  rb_tracearg_event(trace_arg),
1228  rb_tracearg_path(trace_arg),
1229  FIX2INT(rb_tracearg_lineno(trace_arg)),
1230  sym);
1231  }
1232  case RUBY_EVENT_CALL:
1233  case RUBY_EVENT_C_CALL:
1234  case RUBY_EVENT_RETURN:
1235  case RUBY_EVENT_C_RETURN:
1236  return rb_sprintf("#<TracePoint:%"PRIsVALUE" `%"PRIsVALUE"'@%"PRIsVALUE":%d>",
1237  rb_tracearg_event(trace_arg),
1238  rb_tracearg_method_id(trace_arg),
1239  rb_tracearg_path(trace_arg),
1240  FIX2INT(rb_tracearg_lineno(trace_arg)));
1242  case RUBY_EVENT_THREAD_END:
1243  return rb_sprintf("#<TracePoint:%"PRIsVALUE" %"PRIsVALUE">",
1244  rb_tracearg_event(trace_arg),
1245  rb_tracearg_self(trace_arg));
1246  default:
1248  return rb_sprintf("#<TracePoint:%"PRIsVALUE"@%"PRIsVALUE":%d>",
1249  rb_tracearg_event(trace_arg),
1250  rb_tracearg_path(trace_arg),
1251  FIX2INT(rb_tracearg_lineno(trace_arg)));
1252  }
1253  }
1254  else {
1255  return rb_sprintf("#<TracePoint:%s>", tp->tracing ? "enabled" : "disabled");
1256  }
1257 }
1258 
1259 /* This function is called from inits.c */
1260 void
1262 {
1263  /* trace_func */
1264  rb_define_global_function("set_trace_func", set_trace_func, 1);
1265  rb_define_method(rb_cThread, "set_trace_func", thread_set_trace_func_m, 1);
1266  rb_define_method(rb_cThread, "add_trace_func", thread_add_trace_func_m, 1);
1267 
1268  /*
1269  * Document-class: TracePoint
1270  *
1271  * A class that provides the functionality of Kernel#set_trace_func in a
1272  * nice Object-Oriented API.
1273  *
1274  * == Example
1275  *
1276  * We can use TracePoint to gather information specifically for exceptions:
1277  *
1278  * trace = TracePoint.new(:raise) do |tp|
1279  * p [tp.lineno, tp.event, tp.raised_exception]
1280  * end
1281  * #=> #<TracePoint:0x007f786a452448>
1282  *
1283  * trace.enable
1284  * #=> #<TracePoint:0x007f786a452448>
1285  *
1286  * 0 / 0
1287  * #=> [5, :raise, #<ZeroDivisionError: divided by 0>]
1288  *
1289  * == Events
1290  *
1291  * If you don't specify the type of events you want to listen for,
1292  * TracePoint will include all available events.
1293  *
1294  * *Note* do not depend on current event set, as this list is subject to
1295  * change. Instead, it is recommended you specify the type of events you
1296  * want to use.
1297  *
1298  * To filter what is traced, you can pass any of the following as +events+:
1299  *
1300  * +:line+:: execute code on a new line
1301  * +:class+:: start a class or module definition
1302  * +:end+:: finish a class or module definition
1303  * +:call+:: call a Ruby method
1304  * +:return+:: return from a Ruby method
1305  * +:c_call+:: call a C-language routine
1306  * +:c_return+:: return from a C-language routine
1307  * +:raise+:: raise an exception
1308  * +:b_call+:: event hook at block entry
1309  * +:b_return+:: event hook at block ending
1310  * +:thread_begin+:: event hook at thread beginning
1311  * +:thread_end+:: event hook at thread ending
1312  *
1313  */
1314  rb_cTracePoint = rb_define_class("TracePoint", rb_cObject);
1315  rb_undef_alloc_func(rb_cTracePoint);
1316  rb_undef_method(CLASS_OF(rb_cTracePoint), "new");
1317  rb_define_singleton_method(rb_cTracePoint, "new", tracepoint_new_s, -1);
1318  /*
1319  * Document-method: trace
1320  *
1321  * call-seq:
1322  * TracePoint.trace(*events) { |obj| block } -> obj
1323  *
1324  * A convenience method for TracePoint.new, that activates the trace
1325  * automatically.
1326  *
1327  * trace = TracePoint.trace(:call) { |tp| [tp.lineno, tp.event] }
1328  * #=> #<TracePoint:0x007f786a452448>
1329  *
1330  * trace.enabled? #=> true
1331  */
1332  rb_define_singleton_method(rb_cTracePoint, "trace", tracepoint_trace_s, -1);
1333 
1334  rb_define_method(rb_cTracePoint, "enable", tracepoint_enable_m, 0);
1335  rb_define_method(rb_cTracePoint, "disable", tracepoint_disable_m, 0);
1336  rb_define_method(rb_cTracePoint, "enabled?", rb_tracepoint_enabled_p, 0);
1337 
1338  rb_define_method(rb_cTracePoint, "inspect", tracepoint_inspect, 0);
1339 
1340  rb_define_method(rb_cTracePoint, "event", tracepoint_attr_event, 0);
1341  rb_define_method(rb_cTracePoint, "lineno", tracepoint_attr_lineno, 0);
1342  rb_define_method(rb_cTracePoint, "path", tracepoint_attr_path, 0);
1343  rb_define_method(rb_cTracePoint, "method_id", tracepoint_attr_method_id, 0);
1344  rb_define_method(rb_cTracePoint, "defined_class", tracepoint_attr_defined_class, 0);
1345  rb_define_method(rb_cTracePoint, "binding", tracepoint_attr_binding, 0);
1346  rb_define_method(rb_cTracePoint, "self", tracepoint_attr_self, 0);
1347  rb_define_method(rb_cTracePoint, "return_value", tracepoint_attr_return_value, 0);
1348  rb_define_method(rb_cTracePoint, "raised_exception", tracepoint_attr_raised_exception, 0);
1349 }
1350 
rb_control_frame_t * cfp
Definition: vm_core.h:500
#define RUBY_EVENT_B_RETURN
Definition: ruby.h:1593
VALUE self
Definition: vm_trace.c:606
#define T_SYMBOL
Definition: ruby.h:502
#define RUBY_EVENT_THREAD_END
Definition: ruby.h:1595
rb_vm_t * vm
Definition: vm_core.h:495
VALUE rb_tracearg_lineno(rb_trace_arg_t *trace_arg)
Definition: vm_trace.c:715
#define RUBY_EVENT_C_RETURN
Definition: ruby.h:1587
void rb_bug(const char *fmt,...)
Definition: error.c:290
rb_control_frame_t * rb_vm_get_binding_creatable_next_cfp(rb_thread_t *th, const rb_control_frame_t *cfp)
Definition: vm.c:189
int i
Definition: win32ole.c:784
int rb_vm_get_sourceline(const rb_control_frame_t *cfp)
Definition: vm_backtrace.c:33
#define RUBY_EVENT_RETURN
Definition: ruby.h:1585
#define VM_FRAME_TYPE_FINISH_P(cfp)
Definition: vm_core.h:741
void rb_undef_alloc_func(VALUE)
Definition: vm_method.c:482
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
Definition: class.c:1497
#define RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp)
Definition: vm_core.h:787
static VALUE set_trace_func(VALUE obj, VALUE trace)
Definition: vm_trace.c:444
#define CLASS_OF(v)
Definition: ruby.h:448
#define RUBY_EVENT_RAISE
Definition: ruby.h:1588
#define Qtrue
Definition: ruby.h:434
VALUE rb_proc_call_with_block(VALUE, int argc, VALUE *argv, VALUE)
Definition: proc.c:605
#define RUBY_EVENT_ALL
Definition: ruby.h:1589
static VALUE tp_alloc(VALUE klass)
Definition: vm_trace.c:637
#define TypedData_Get_Struct(obj, type, data_type, sval)
Definition: ruby.h:1030
const int id
Definition: nkf.c:209
VALUE rb_tracearg_return_value(rb_trace_arg_t *trace_arg)
Definition: vm_trace.c:783
static VALUE tracepoint_new(VALUE klass, rb_thread_t *target_th, rb_event_flag_t events, void(func)(VALUE, void *), void *data, VALUE proc)
Definition: vm_trace.c:1099
static VALUE tracepoint_attr_path(VALUE tpval)
Definition: vm_trace.c:836
static void connect_event_hook(rb_hook_list_t *list, rb_event_hook_t *hook)
Definition: vm_trace.c:113
rb_thread_t * th
Definition: vm_core.h:957
static VALUE thread_add_trace_func_m(VALUE obj, VALUE trace)
Definition: vm_trace.c:481
#define RUBY_EVENT_CALL
Definition: ruby.h:1584
VALUE rb_eTypeError
Definition: error.c:511
#define TH_JUMP_TAG(th, st)
Definition: eval_intern.h:116
SSL_METHOD *(* func)(void)
Definition: ossl_ssl.c:108
static void rb_threadptr_exec_event_hooks_orig(rb_trace_arg_t *trace_arg, int pop_p)
Definition: vm_trace.c:283
#define SYM2ID(x)
Definition: ruby.h:364
static ID get_event_id(rb_event_flag_t event)
Definition: vm_trace.c:536
void rb_threadptr_exec_event_hooks(rb_trace_arg_t *trace_arg)
Definition: vm_trace.c:338
static size_t tp_memsize(const void *ptr)
Definition: vm_trace.c:626
static rb_tp_t * tpptr(VALUE tpval)
Definition: vm_trace.c:668
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:1780
static VALUE tracepoint_attr_event(VALUE tpval)
Definition: vm_trace.c:818
rb_thread_t * target_th
Definition: vm_trace.c:601
VALUE rb_convert_type(VALUE, int, const char *, const char *)
Definition: object.c:2368
#define TH_EXEC_TAG()
Definition: eval_intern.h:111
VALUE rb_tracearg_path(rb_trace_arg_t *trace_arg)
Definition: vm_trace.c:721
static void clean_hooks(rb_hook_list_t *list)
Definition: vm_trace.c:224
VALUE rb_tracearg_method_id(rb_trace_arg_t *trace_arg)
Definition: vm_trace.c:749
void rb_gc_mark(VALUE ptr)
Definition: gc.c:2598
void rb_thread_add_event_hook2(VALUE thval, rb_event_hook_func_t func, rb_event_flag_t events, VALUE data, rb_event_hook_flag_t hook_flags)
Definition: vm_trace.c:142
void rb_clear_trace_func(void)
Definition: vm_trace.c:215
static void recalc_remove_ruby_vm_event_flags(rb_event_flag_t events)
Definition: vm_trace.c:78
void rb_define_global_function(const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a global function.
Definition: class.c:1526
rb_event_flag_t events
Definition: vm_core.h:333
VALUE rb_tracearg_event(rb_trace_arg_t *trace_arg)
Definition: vm_trace.c:692
int rb_remove_event_hook(rb_event_hook_func_t func)
Definition: vm_trace.c:194
static const char * get_event_name(rb_event_flag_t event)
Definition: vm_trace.c:519
#define LIKELY(x)
Definition: vm_core.h:114
void rb_undef_method(VALUE klass, const char *name)
Definition: class.c:1362
static void recalc_add_ruby_vm_event_flags(rb_event_flag_t events)
Definition: vm_trace.c:64
struct rb_tp_struct rb_tp_t
void rb_threadptr_exec_event_hooks_and_pop_frame(rb_trace_arg_t *trace_arg)
Definition: vm_trace.c:332
static int clear_trace_func_i(st_data_t key, st_data_t val, st_data_t flag)
Definition: vm_trace.c:206
#define sym(x)
Definition: date_core.c:3715
void Init_vm_trace(void)
Definition: vm_trace.c:1261
#define RUBY_EVENT_CLASS
Definition: ruby.h:1582
static void call_trace_func(rb_event_flag_t, VALUE data, VALUE self, ID id, VALUE klass)
Definition: vm_trace.c:563
#define FL_SINGLETON
Definition: ruby.h:1111
struct rb_trace_arg_struct * rb_tracearg_from_tracepoint(VALUE tpval)
Definition: vm_trace.c:686
int rb_vm_control_frame_id_and_class(const rb_control_frame_t *cfp, ID *idp, VALUE *klassp)
Definition: vm.c:1455
#define RB_TYPE_P(obj, type)
Definition: ruby.h:1537
VALUE rb_binding_new(void)
Definition: proc.c:343
static rb_thread_t * thval2thread_t(VALUE thval)
Definition: vm_trace.c:94
#define TH_POP_TAG()
Definition: eval_intern.h:101
VALUE rb_tracearg_self(rb_trace_arg_t *trace_arg)
Definition: vm_trace.c:777
#define FL_TEST(x, f)
Definition: ruby.h:1146
VALUE rb_tracepoint_disable(VALUE tpval)
Definition: vm_trace.c:963
int rb_thread_method_id_and_class(rb_thread_t *th, ID *idp, VALUE *klassp)
Definition: vm.c:1483
int trace_running
Definition: vm_core.h:351
int rb_block_given_p(void)
Definition: eval.c:672
int rb_threadptr_set_raised(rb_thread_t *th)
Definition: thread.c:2043
rb_control_frame_t * rb_vm_get_ruby_level_next_cfp(rb_thread_t *th, const rb_control_frame_t *cfp)
Definition: vm.c:201
struct rb_event_hook_struct * next
Definition: vm_trace.c:39
#define val
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:1426
VALUE rb_eRuntimeError
Definition: error.c:510
static VALUE tracepoint_enable_m(VALUE tpval)
Definition: vm_trace.c:1018
static void rb_threadptr_add_event_hook(rb_thread_t *th, rb_event_hook_func_t func, rb_event_flag_t events, VALUE data, rb_event_hook_flag_t hook_flags)
Definition: vm_trace.c:122
static VALUE rb_cTracePoint
Definition: vm_trace.c:597
VALUE rb_tracearg_raised_exception(rb_trace_arg_t *trace_arg)
Definition: vm_trace.c:798
static int exec_hooks(rb_thread_t *th, rb_hook_list_t *list, const rb_trace_arg_t *trace_arg, int can_clean_hooks)
Definition: vm_trace.c:245
VALUE rb_binding_new_with_cfp(rb_thread_t *th, const rb_control_frame_t *src_cfp)
Definition: proc.c:314
VALUE rb_tracepoint_enabled_p(VALUE tpval)
Definition: vm_trace.c:1092
VALUE rb_iv_get(VALUE, const char *)
Definition: variable.c:2583
#define JUMP_TAG(st)
Definition: eval_intern.h:120
rb_iseq_t * iseq
Definition: vm_core.h:428
static VALUE tracepoint_attr_defined_class(VALUE tpval)
Definition: vm_trace.c:885
#define NIL_P(v)
Definition: ruby.h:446
#define UNLIKELY(x)
Definition: vm_core.h:115
static VALUE thread_set_trace_func_m(VALUE obj, VALUE trace)
Definition: vm_trace.c:502
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:499
rb_control_frame_t * cfp
Definition: vm_core.h:958
VALUE rb_tracearg_defined_class(rb_trace_arg_t *trace_arg)
Definition: vm_trace.c:756
int argc
Definition: ruby.c:130
VALUE proc
Definition: vm_trace.c:604
void(* rb_event_hook_func_t)(rb_event_flag_t evflag, VALUE data, VALUE self, ID mid, VALUE klass)
Definition: ruby.h:1604
#define Qfalse
Definition: ruby.h:433
#define rb_sourcefile()
Definition: tcltklib.c:97
VALUE rb_tracearg_binding(rb_trace_arg_t *trace_arg)
Definition: vm_trace.c:763
#define RUBY_EVENT_C_CALL
Definition: ruby.h:1586
struct rb_event_hook_struct * hooks
Definition: vm_core.h:332
static void fill_path_and_lineno(rb_trace_arg_t *trace_arg)
Definition: vm_trace.c:698
static int ruby_event_flag_count[MAX_EVENT_NUM]
Definition: vm_trace.c:46
#define ALLOC(type)
Definition: ruby.h:1224
#define END(no)
Definition: re.c:26
static rb_event_hook_t * alloc_event_hook(rb_event_hook_func_t func, rb_event_flag_t events, VALUE data, rb_event_hook_flag_t hook_flags)
Definition: vm_trace.c:102
static VALUE tracepoint_inspect(VALUE self)
Definition: vm_trace.c:1213
static rb_event_flag_t symbol2event_flag(VALUE v)
Definition: vm_trace.c:644
static void fill_id_and_klass(rb_trace_arg_t *trace_arg)
Definition: vm_trace.c:728
#define RETURN(val)
Definition: dir.c:177
rb_hook_list_t event_hooks
Definition: vm_core.h:603
rb_event_hook_func_t func
Definition: vm_trace.c:37
#define RUBY_EVENT_SPECIFIED_LINE
Definition: ruby.h:1599
VALUE rb_yield(VALUE)
Definition: vm_eval.c:934
#define TRUE
Definition: nkf.h:175
VALUE rb_obj_is_proc(VALUE)
Definition: proc.c:91
static VALUE tracepoint_attr_raised_exception(VALUE tpval)
Definition: vm_trace.c:924
int rb_thread_remove_event_hook_with_data(VALUE thval, rb_event_hook_func_t func, VALUE data)
Definition: vm_trace.c:188
#define C(name, NAME)
void * data
Definition: vm_trace.c:603
VALUE rb_sprintf(const char *format,...)
Definition: sprintf.c:1270
static void tp_free(void *ptr)
Definition: vm_trace.c:620
static int remove_event_hook(rb_hook_list_t *list, rb_event_hook_func_t func, VALUE data)
Definition: vm_trace.c:156
#define RUBY_EVENT_LINE
Definition: ruby.h:1581
#define PRIsVALUE
Definition: ruby.h:147
unsigned long ID
Definition: ruby.h:105
int rb_thread_remove_event_hook(VALUE thval, rb_event_hook_func_t func)
Definition: vm_trace.c:182
static VALUE tracepoint_attr_return_value(VALUE tpval)
Definition: vm_trace.c:915
#define Qnil
Definition: ruby.h:435
unsigned long VALUE
Definition: ruby.h:104
static VALUE result
Definition: nkf.c:40
RUBY_EXTERN VALUE rb_cThread
Definition: ruby.h:1459
#define RBASIC(obj)
Definition: ruby.h:1094
rb_event_hook_flag_t
Definition: debug.h:73
int rb_threadptr_reset_raised(rb_thread_t *th)
Definition: thread.c:2053
#define FIX2INT(x)
Definition: ruby.h:624
#define RUBY_EVENT_THREAD_BEGIN
Definition: ruby.h:1594
rb_iseq_location_t location
Definition: vm_core.h:213
#define TH_PUSH_TAG(th)
Definition: eval_intern.h:94
VALUE rb_ensure(VALUE(*b_proc)(ANYARGS), VALUE data1, VALUE(*e_proc)(ANYARGS), VALUE data2)
Definition: eval.c:804
static const rb_data_type_t tp_data_type
Definition: vm_trace.c:631
#define RUBY_EVENT_TRACEPOINT_ALL
Definition: ruby.h:1596
rb_event_hook_flag_t hook_flags
Definition: vm_trace.c:35
static int rb_threadptr_remove_event_hook(rb_thread_t *th, rb_event_hook_func_t func, VALUE data)
Definition: vm_trace.c:176
void xfree(void *)
static VALUE tracepoint_attr_lineno(VALUE tpval)
Definition: vm_trace.c:827
static VALUE tracepoint_disable_m(VALUE tpval)
Definition: vm_trace.c:1069
static rb_trace_arg_t * get_trace_arg(void)
Definition: vm_trace.c:676
VALUE rb_mRubyVMFrozenCore
Definition: vm.c:92
static void thread_add_trace_func(rb_thread_t *th, VALUE trace)
Definition: vm_trace.c:463
static VALUE tracepoint_trace_s(int argc, VALUE *argv, VALUE self)
Definition: vm_trace.c:1197
struct rb_event_hook_struct rb_event_hook_t
static void tp_call_trace(VALUE tpval, rb_trace_arg_t *trace_arg)
Definition: vm_trace.c:930
#define MAX_EVENT_NUM
Definition: vm_trace.c:44
#define INT2FIX(i)
Definition: ruby.h:241
int rb_sourceline(void)
Definition: vm.c:816
VALUE rb_block_proc(void)
Definition: proc.c:479
static void tp_mark(void *ptr)
Definition: vm_trace.c:610
VALUE rb_tracepoint_enable(VALUE tpval)
Definition: vm_trace.c:943
unsigned long rb_event_flag_t
Definition: ruby.h:1603
rb_hook_list_t event_hooks
Definition: vm_core.h:377
void rb_thread_add_event_hook(VALUE thval, rb_event_hook_func_t func, rb_event_flag_t events, VALUE data)
Definition: vm_trace.c:129
uint8_t key[16]
Definition: random.c:1370
static VALUE tracepoint_attr_binding(VALUE tpval)
Definition: vm_trace.c:894
#define RTEST(v)
Definition: ruby.h:445
VALUE rb_suppress_tracing(VALUE(*func)(VALUE), VALUE arg)
Definition: vm_trace.c:344
rb_event_flag_t ruby_vm_event_flags
Definition: vm.c:98
struct rb_encoding_entry * list
Definition: encoding.c:50
void vm_trace_mark_event_hooks(rb_hook_list_t *hooks)
Definition: vm_trace.c:51
v
Definition: win32ole.c:798
#define RUBY_EVENT_END
Definition: ruby.h:1583
#define TypedData_Make_Struct(klass, type, data_type, sval)
Definition: ruby.h:1019
#define GetThreadPtr(obj, ptr)
Definition: vm_core.h:452
VALUE rb_tracepoint_new(VALUE target_thval, rb_event_flag_t events, void(*func)(VALUE, void *), void *data)
Definition: vm_trace.c:1115
#define ID2SYM(x)
Definition: ruby.h:363
rb_event_flag_t event
Definition: vm_core.h:956
const char * rb_id2name(ID id)
Definition: ripper.c:17005
unsigned long st_data_t
Definition: st.h:35
struct rb_vm_tag * tag
Definition: vm_core.h:561
struct rb_vm_tag * prev
Definition: vm_core.h:472
void rb_secure(int)
Definition: safe.c:79
void rb_add_event_hook2(rb_event_hook_func_t func, rb_event_flag_t events, VALUE data, rb_event_hook_flag_t hook_flags)
Definition: vm_trace.c:148
#define CONST_ID(var, str)
Definition: ruby.h:1318
int rb_remove_event_hook_with_data(rb_event_hook_func_t func, VALUE data)
Definition: vm_trace.c:200
#define Qundef
Definition: ruby.h:436
#define T_ICLASS
Definition: ruby.h:487
static VALUE tracepoint_attr_self(VALUE tpval)
Definition: vm_trace.c:906
#define CALL(n)
Definition: inits.c:15
static rb_thread_t * GET_THREAD(void)
Definition: vm_core.h:883
void(* rb_event_hook_raw_arg_func_t)(VALUE data, const rb_trace_arg_t *arg)
Definition: vm_trace.c:42
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1344
int st_foreach(st_table *, int(*)(ANYARGS), st_data_t)
Definition: st.c:1000
static VALUE tracepoint_attr_method_id(VALUE tpval)
Definition: vm_trace.c:845
VALUE rb_str_new2(const char *)
rb_event_flag_t events
Definition: vm_trace.c:36
static VALUE default_inspect(VALUE self, const char *class_name)
Definition: win32ole.c:2003
VALUE rb_eThreadError
Definition: eval.c:690
rb_event_flag_t events
Definition: vm_trace.c:600
VALUE rb_eArgError
Definition: error.c:512
struct rb_trace_arg_struct * trace_arg
Definition: vm_core.h:604
void(* func)(VALUE tpval, void *data)
Definition: vm_trace.c:602
char ** argv
Definition: ruby.c:131
void rb_add_event_hook(rb_event_hook_func_t func, rb_event_flag_t events, VALUE data)
Definition: vm_trace.c:135
static VALUE tracepoint_new_s(int argc, VALUE *argv, VALUE self)
Definition: vm_trace.c:1175
#define GET_VM()
Definition: vm_core.h:876