Ruby  2.0.0p648(2015-12-16revision53162)
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 {
125  connect_event_hook(&th->event_hooks, hook);
126 }
127 
128 void
130 {
132 }
133 
134 void
136 {
138  connect_event_hook(&GET_VM()->event_hooks, hook);
139 }
140 
141 void
143 {
145 }
146 
147 void
149 {
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 {
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  th->errinfo = Qnil;
294 
295  th->vm->trace_running++;
296  th->trace_arg = trace_arg;
297  {
299 
300  /* thread local traces */
301  list = &th->event_hooks;
302  if (list->events & trace_arg->event) {
303  state = exec_hooks(th, list, trace_arg, TRUE);
304  if (state) goto terminate;
305  }
306 
307  /* vm global traces */
308  list = &th->vm->event_hooks;
309  if (list->events & trace_arg->event) {
310  state = exec_hooks(th, list, trace_arg, !vm_tracing);
311  if (state) goto terminate;
312  }
313  th->errinfo = errinfo;
314  }
315  terminate:
316  th->trace_arg = 0;
317  th->vm->trace_running--;
318 
319  if (state) {
320  if (pop_p) {
321  if (VM_FRAME_TYPE_FINISH_P(th->cfp)) {
322  th->tag = th->tag->prev;
323  }
325  }
326  TH_JUMP_TAG(th, state);
327  }
328  th->state = outer_state;
329  }
330 }
331 
332 void
334 {
336 }
337 
338 void
340 {
342 }
343 
344 VALUE
346 {
347  volatile int raised;
348  volatile int outer_state;
349  VALUE result = Qnil;
350  rb_thread_t *th = GET_THREAD();
351  int state;
352  const int tracing = th->trace_arg ? 1 : 0;
353  rb_trace_arg_t dummy_trace_arg;
354 
355  if (!tracing) th->vm->trace_running++;
356  if (!th->trace_arg) th->trace_arg = &dummy_trace_arg;
357 
358  raised = rb_threadptr_reset_raised(th);
359  outer_state = th->state;
360  th->state = 0;
361 
362  TH_PUSH_TAG(th);
363  if ((state = TH_EXEC_TAG()) == 0) {
364  result = (*func)(arg);
365  }
366  TH_POP_TAG();
367 
368  if (raised) {
370  }
371 
372  if (th->trace_arg == &dummy_trace_arg) th->trace_arg = 0;
373  if (!tracing) th->vm->trace_running--;
374 
375  if (state) {
376  JUMP_TAG(state);
377  }
378 
379  th->state = outer_state;
380  return result;
381 }
382 
383 static void call_trace_func(rb_event_flag_t, VALUE data, VALUE self, ID id, VALUE klass);
384 
385 /* (2-1) set_trace_func (old API) */
386 
387 /*
388  * call-seq:
389  * set_trace_func(proc) -> proc
390  * set_trace_func(nil) -> nil
391  *
392  * Establishes _proc_ as the handler for tracing, or disables
393  * tracing if the parameter is +nil+.
394  *
395  * _proc_ takes up to six parameters:
396  *
397  * * an event name
398  * * a filename
399  * * a line number
400  * * an object id
401  * * a binding
402  * * the name of a class
403  *
404  * _proc_ is invoked whenever an event occurs.
405  *
406  * Events are:
407  *
408  * +c-call+:: call a C-language routine
409  * +c-return+:: return from a C-language routine
410  * +call+:: call a Ruby method
411  * +class+:: start a class or module definition),
412  * +end+:: finish a class or module definition),
413  * +line+:: execute code on a new line
414  * +raise+:: raise an exception
415  * +return+:: return from a Ruby method
416  *
417  * Tracing is disabled within the context of _proc_.
418  *
419  * class Test
420  * def test
421  * a = 1
422  * b = 2
423  * end
424  * end
425  *
426  * set_trace_func proc { |event, file, line, id, binding, classname|
427  * printf "%8s %s:%-2d %10s %8s\n", event, file, line, id, classname
428  * }
429  * t = Test.new
430  * t.test
431  *
432  * line prog.rb:11 false
433  * c-call prog.rb:11 new Class
434  * c-call prog.rb:11 initialize Object
435  * c-return prog.rb:11 initialize Object
436  * c-return prog.rb:11 new Class
437  * line prog.rb:12 false
438  * call prog.rb:2 test Test
439  * line prog.rb:3 test Test
440  * line prog.rb:4 test Test
441  * return prog.rb:4 test Test
442  */
443 
444 static VALUE
446 {
447  rb_secure(4);
448 
450 
451  if (NIL_P(trace)) {
452  return Qnil;
453  }
454 
455  if (!rb_obj_is_proc(trace)) {
456  rb_raise(rb_eTypeError, "trace_func needs to be Proc");
457  }
458 
460  return trace;
461 }
462 
463 static void
465 {
466  if (!rb_obj_is_proc(trace)) {
467  rb_raise(rb_eTypeError, "trace_func needs to be Proc");
468  }
469 
471 }
472 
473 /*
474  * call-seq:
475  * thr.add_trace_func(proc) -> proc
476  *
477  * Adds _proc_ as a handler for tracing.
478  * See <code>Thread#set_trace_func</code> and +set_trace_func+.
479  */
480 
481 static VALUE
483 {
484  rb_thread_t *th;
485 
486  rb_secure(4);
487  GetThreadPtr(obj, th);
488  thread_add_trace_func(th, trace);
489  return trace;
490 }
491 
492 /*
493  * call-seq:
494  * thr.set_trace_func(proc) -> proc
495  * thr.set_trace_func(nil) -> nil
496  *
497  * Establishes _proc_ on _thr_ as the handler for tracing, or
498  * disables tracing if the parameter is +nil+.
499  * See +set_trace_func+.
500  */
501 
502 static VALUE
504 {
505  rb_thread_t *th;
506 
507  rb_secure(4);
508  GetThreadPtr(obj, th);
510 
511  if (NIL_P(trace)) {
512  return Qnil;
513  }
514 
515  thread_add_trace_func(th, trace);
516  return trace;
517 }
518 
519 static const char *
521 {
522  switch (event) {
523  case RUBY_EVENT_LINE: return "line";
524  case RUBY_EVENT_CLASS: return "class";
525  case RUBY_EVENT_END: return "end";
526  case RUBY_EVENT_CALL: return "call";
527  case RUBY_EVENT_RETURN: return "return";
528  case RUBY_EVENT_C_CALL: return "c-call";
529  case RUBY_EVENT_C_RETURN: return "c-return";
530  case RUBY_EVENT_RAISE: return "raise";
531  default:
532  return "unknown";
533  }
534 }
535 
536 static ID
538 {
539  ID id;
540 
541  switch (event) {
542 #define C(name, NAME) case RUBY_EVENT_##NAME: CONST_ID(id, #name); return id;
543  C(line, LINE);
544  C(class, CLASS);
545  C(end, END);
546  C(call, CALL);
547  C(return, RETURN);
548  C(c_call, C_CALL);
549  C(c_return, C_RETURN);
550  C(raise, RAISE);
551  C(b_call, B_CALL);
552  C(b_return, B_RETURN);
553  C(thread_begin, THREAD_BEGIN);
554  C(thread_end, THREAD_END);
555  C(specified_line, SPECIFIED_LINE);
556  case RUBY_EVENT_LINE | RUBY_EVENT_SPECIFIED_LINE: CONST_ID(id, "line"); return id;
557 #undef C
558  default:
559  return 0;
560  }
561 }
562 
563 static void
564 call_trace_func(rb_event_flag_t event, VALUE proc, VALUE self, ID id, VALUE klass)
565 {
566  const char *srcfile = rb_sourcefile();
567  VALUE eventname = rb_str_new2(get_event_name(event));
568  VALUE filename = srcfile ? rb_str_new2(srcfile) : Qnil;
569  VALUE argv[6];
570  int line = rb_sourceline();
571  rb_thread_t *th = GET_THREAD();
572 
573  if (!klass) {
574  rb_thread_method_id_and_class(th, &id, &klass);
575  }
576 
577  if (klass) {
578  if (RB_TYPE_P(klass, T_ICLASS)) {
579  klass = RBASIC(klass)->klass;
580  }
581  else if (FL_TEST(klass, FL_SINGLETON)) {
582  klass = rb_iv_get(klass, "__attached__");
583  }
584  }
585 
586  argv[0] = eventname;
587  argv[1] = filename;
588  argv[2] = INT2FIX(line);
589  argv[3] = id ? ID2SYM(id) : Qnil;
590  argv[4] = (self && srcfile) ? rb_binding_new() : Qnil;
591  argv[5] = klass ? klass : Qnil;
592 
593  rb_proc_call_with_block(proc, 6, argv, Qnil);
594 }
595 
596 /* (2-2) TracePoint API */
597 
599 
600 typedef struct rb_tp_struct {
603  void (*func)(VALUE tpval, void *data);
604  void *data;
606  int tracing;
607  VALUE self;
608 } rb_tp_t;
609 
610 static void
611 tp_mark(void *ptr)
612 {
613  if (ptr) {
614  rb_tp_t *tp = (rb_tp_t *)ptr;
615  rb_gc_mark(tp->proc);
616  if (tp->target_th) rb_gc_mark(tp->target_th->self);
617  }
618 }
619 
620 static void
621 tp_free(void *ptr)
622 {
623  /* do nothing */
624 }
625 
626 static size_t
627 tp_memsize(const void *ptr)
628 {
629  return sizeof(rb_tp_t);
630 }
631 
632 static const rb_data_type_t tp_data_type = {
633  "tracepoint",
635 };
636 
637 static VALUE
639 {
640  rb_tp_t *tp;
641  return TypedData_Make_Struct(klass, rb_tp_t, &tp_data_type, tp);
642 }
643 
644 static rb_event_flag_t
646 {
647  static ID id;
648  VALUE sym = rb_convert_type(v, T_SYMBOL, "Symbol", "to_sym");
649 
650 #define C(name, NAME) CONST_ID(id, #name); if (sym == ID2SYM(id)) return RUBY_EVENT_##NAME
651  C(line, LINE);
652  C(class, CLASS);
653  C(end, END);
654  C(call, CALL);
655  C(return, RETURN);
656  C(c_call, C_CALL);
657  C(c_return, C_RETURN);
658  C(raise, RAISE);
659  C(b_call, B_CALL);
660  C(b_return, B_RETURN);
661  C(thread_begin, THREAD_BEGIN);
662  C(thread_end, THREAD_END);
663  C(specified_line, SPECIFIED_LINE);
664 #undef C
665  rb_raise(rb_eArgError, "unknown event: %s", rb_id2name(SYM2ID(sym)));
666 }
667 
668 static rb_tp_t *
669 tpptr(VALUE tpval)
670 {
671  rb_tp_t *tp;
673  return tp;
674 }
675 
676 static rb_trace_arg_t *
678 {
679  rb_trace_arg_t *trace_arg = GET_THREAD()->trace_arg;
680  if (trace_arg == 0) {
681  rb_raise(rb_eRuntimeError, "access from outside");
682  }
683  return trace_arg;
684 }
685 
686 struct rb_trace_arg_struct *
688 {
689  return get_trace_arg();
690 }
691 
692 VALUE
694 {
695  return ID2SYM(get_event_id(trace_arg->event));
696 }
697 
698 static void
700 {
701  if (trace_arg->path == Qundef) {
702  rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(trace_arg->th, trace_arg->cfp);
703 
704  if (cfp) {
705  trace_arg->path = cfp->iseq->location.path;
706  trace_arg->lineno = rb_vm_get_sourceline(cfp);
707  }
708  else {
709  trace_arg->path = Qnil;
710  trace_arg->lineno = 0;
711  }
712  }
713 }
714 
715 VALUE
717 {
718  fill_path_and_lineno(trace_arg);
719  return INT2FIX(trace_arg->lineno);
720 }
721 VALUE
723 {
724  fill_path_and_lineno(trace_arg);
725  return trace_arg->path;
726 }
727 
728 static void
730 {
731  if (!trace_arg->klass_solved) {
732  if (!trace_arg->klass) {
733  rb_vm_control_frame_id_and_class(trace_arg->cfp, &trace_arg->id, &trace_arg->klass);
734  }
735 
736  if (trace_arg->klass) {
737  if (RB_TYPE_P(trace_arg->klass, T_ICLASS)) {
738  trace_arg->klass = RBASIC(trace_arg->klass)->klass;
739  }
740  }
741  else {
742  trace_arg->klass = Qnil;
743  }
744 
745  trace_arg->klass_solved = 1;
746  }
747 }
748 
749 VALUE
751 {
752  fill_id_and_klass(trace_arg);
753  return trace_arg->id ? ID2SYM(trace_arg->id) : Qnil;
754 }
755 
756 VALUE
758 {
759  fill_id_and_klass(trace_arg);
760  return trace_arg->klass;
761 }
762 
763 VALUE
765 {
767  cfp = rb_vm_get_binding_creatable_next_cfp(trace_arg->th, trace_arg->cfp);
768 
769  if (cfp) {
770  return rb_binding_new_with_cfp(trace_arg->th, cfp);
771  }
772  else {
773  return Qnil;
774  }
775 }
776 
777 VALUE
779 {
780  return trace_arg->self;
781 }
782 
783 VALUE
785 {
787  /* ok */
788  }
789  else {
790  rb_raise(rb_eRuntimeError, "not supported by this event");
791  }
792  if (trace_arg->data == Qundef) {
793  rb_bug("tp_attr_return_value_m: unreachable");
794  }
795  return trace_arg->data;
796 }
797 
798 VALUE
800 {
801  if (trace_arg->event & (RUBY_EVENT_RAISE)) {
802  /* ok */
803  }
804  else {
805  rb_raise(rb_eRuntimeError, "not supported by this event");
806  }
807  if (trace_arg->data == Qundef) {
808  rb_bug("tp_attr_raised_exception_m: unreachable");
809  }
810  return trace_arg->data;
811 }
812 
813 /*
814  * Type of event
815  *
816  * See TracePoint@Events for more information.
817  */
818 static VALUE
820 {
822 }
823 
824 /*
825  * Line number of the event
826  */
827 static VALUE
829 {
831 }
832 
833 /*
834  * Path of the file being run
835  */
836 static VALUE
838 {
840 }
841 
842 /*
843  * Return the name of the method being called
844  */
845 static VALUE
847 {
849 }
850 
851 /*
852  * Return class or module of the method being called.
853  *
854  * class C; def foo; end; end
855  * trace = TracePoint.new(:call) do |tp|
856  * p tp.defined_class #=> C
857  * end.enable do
858  * C.new.foo
859  * end
860  *
861  * If method is defined by a module, then that module is returned.
862  *
863  * module M; def foo; end; end
864  * class C; include M; end;
865  * trace = TracePoint.new(:call) do |tp|
866  * p tp.defined_class #=> M
867  * end.enable do
868  * C.new.foo
869  * end
870  *
871  * <b>Note:</b> #defined_class returns singleton class.
872  *
873  * 6th block parameter of Kernel#set_trace_func passes original class
874  * of attached by singleton class.
875  *
876  * <b>This is a difference between Kernel#set_trace_func and TracePoint.</b>
877  *
878  * class C; def self.foo; end; end
879  * trace = TracePoint.new(:call) do |tp|
880  * p tp.defined_class #=> #<Class:C>
881  * end.enable do
882  * C.foo
883  * end
884  */
885 static VALUE
887 {
889 }
890 
891 /*
892  * Return the generated binding object from event
893  */
894 static VALUE
896 {
898 }
899 
900 /*
901  * Return the trace object during event
902  *
903  * Same as TracePoint#binding:
904  * trace.binding.eval('self')
905  */
906 static VALUE
908 {
910 }
911 
912 /*
913  * Return value from +:return+, +c_return+, and +b_return+ event
914  */
915 static VALUE
917 {
919 }
920 
921 /*
922  * Value from exception raised on the +:raise+ event
923  */
924 static VALUE
926 {
928 }
929 
930 static void
932 {
933  rb_tp_t *tp = tpptr(tpval);
934 
935  if (tp->func) {
936  (*tp->func)(tpval, tp->data);
937  }
938  else {
939  rb_proc_call_with_block((VALUE)tp->proc, 1, &tpval, Qnil);
940  }
941 }
942 
943 VALUE
945 {
946  rb_tp_t *tp;
947 
948  rb_secure(4);
949  tp = tpptr(tpval);
950 
951  if (tp->target_th) {
954  }
955  else {
958  }
959  tp->tracing = 1;
960  return Qundef;
961 }
962 
963 VALUE
965 {
966  rb_tp_t *tp;
967 
968  rb_secure(4);
969  tp = tpptr(tpval);
970 
971  if (tp->target_th) {
973  }
974  else {
976  }
977  tp->tracing = 0;
978  return Qundef;
979 }
980 
981 /*
982  * call-seq:
983  * trace.enable -> true or false
984  * trace.enable { block } -> obj
985  *
986  * Activates the trace
987  *
988  * Return true if trace was enabled.
989  * Return false if trace was disabled.
990  *
991  * trace.enabled? #=> false
992  * trace.enable #=> false (previous state)
993  * # trace is enabled
994  * trace.enabled? #=> true
995  * trace.enable #=> true (previous state)
996  * # trace is still enabled
997  *
998  * If a block is given, the trace will only be enabled within the scope of the
999  * block.
1000  *
1001  * trace.enabled?
1002  * #=> false
1003  *
1004  * trace.enable do
1005  * trace.enabled?
1006  * # only enabled for this block
1007  * end
1008  *
1009  * trace.enabled?
1010  * #=> false
1011  *
1012  * Note: You cannot access event hooks within the block.
1013  *
1014  * trace.enable { p tp.lineno }
1015  * #=> RuntimeError: access from outside
1016  *
1017  */
1018 static VALUE
1020 {
1021  rb_tp_t *tp = tpptr(tpval);
1022  int previous_tracing = tp->tracing;
1023  rb_tracepoint_enable(tpval);
1024 
1025  if (rb_block_given_p()) {
1026  return rb_ensure(rb_yield, Qnil,
1027  previous_tracing ? rb_tracepoint_enable : rb_tracepoint_disable,
1028  tpval);
1029  }
1030  else {
1031  return previous_tracing ? Qtrue : Qfalse;
1032  }
1033 }
1034 
1035 /*
1036  * call-seq:
1037  * trace.disable -> true or false
1038  * trace.disable { block } -> obj
1039  *
1040  * Deactivates the trace
1041  *
1042  * Return true if trace was enabled.
1043  * Return false if trace was disabled.
1044  *
1045  * trace.enabled? #=> true
1046  * trace.disable #=> false (previous status)
1047  * trace.enabled? #=> false
1048  * trace.disable #=> false
1049  *
1050  * If a block is given, the trace will only be disable within the scope of the
1051  * block.
1052  *
1053  * trace.enabled?
1054  * #=> true
1055  *
1056  * trace.disable do
1057  * trace.enabled?
1058  * # only disabled for this block
1059  * end
1060  *
1061  * trace.enabled?
1062  * #=> true
1063  *
1064  * Note: You cannot access event hooks within the block.
1065  *
1066  * trace.disable { p tp.lineno }
1067  * #=> RuntimeError: access from outside
1068  */
1069 static VALUE
1071 {
1072  rb_tp_t *tp = tpptr(tpval);
1073  int previous_tracing = tp->tracing;
1074  rb_tracepoint_disable(tpval);
1075 
1076  if (rb_block_given_p()) {
1077  return rb_ensure(rb_yield, Qnil,
1078  previous_tracing ? rb_tracepoint_enable : rb_tracepoint_disable,
1079  tpval);
1080  }
1081  else {
1082  return previous_tracing ? Qtrue : Qfalse;
1083  }
1084 }
1085 
1086 /*
1087  * call-seq:
1088  * trace.enabled? -> true or false
1089  *
1090  * The current status of the trace
1091  */
1092 VALUE
1094 {
1095  rb_tp_t *tp = tpptr(tpval);
1096  return tp->tracing ? Qtrue : Qfalse;
1097 }
1098 
1099 static VALUE
1100 tracepoint_new(VALUE klass, rb_thread_t *target_th, rb_event_flag_t events, void (func)(VALUE, void*), void *data, VALUE proc)
1101 {
1102  VALUE tpval = tp_alloc(klass);
1103  rb_tp_t *tp;
1105 
1106  tp->proc = proc;
1107  tp->func = func;
1108  tp->data = data;
1109  tp->events = events;
1110  tp->self = tpval;
1111 
1112  return tpval;
1113 }
1114 
1115 VALUE
1116 rb_tracepoint_new(VALUE target_thval, rb_event_flag_t events, void (*func)(VALUE, void *), void *data)
1117 {
1118  rb_thread_t *target_th = 0;
1119  if (RTEST(target_thval)) {
1120  GetThreadPtr(target_thval, target_th);
1121  /* TODO: Test it!
1122  * Warning: This function is not tested.
1123  */
1124  }
1125  return tracepoint_new(rb_cTracePoint, target_th, events, func, data, Qundef);
1126 }
1127 
1128 /*
1129  * call-seq:
1130  * TracePoint.new(*events) { |obj| block } -> obj
1131  *
1132  * Returns a new TracePoint object, not enabled by default.
1133  *
1134  * Next, in order to activate the trace, you must use TracePoint.enable
1135  *
1136  * trace = TracePoint.new(:call) do |tp|
1137  * p [tp.lineno, tp.defined_class, tp.method_id, tp.event]
1138  * end
1139  * #=> #<TracePoint:0x007f17372cdb20>
1140  *
1141  * trace.enable
1142  * #=> #<TracePoint:0x007f17372cdb20>
1143  *
1144  * puts "Hello, TracePoint!"
1145  * # ...
1146  * # [48, IRB::Notifier::AbstractNotifier, :printf, :call]
1147  * # ...
1148  *
1149  * When you want to deactivate the trace, you must use TracePoint.disable
1150  *
1151  * trace.disable
1152  *
1153  * See TracePoint@Events for possible events and more information.
1154  *
1155  * A block must be given, otherwise a ThreadError is raised.
1156  *
1157  * If the trace method isn't included in the given events filter, a
1158  * RuntimeError is raised.
1159  *
1160  * TracePoint.trace(:line) do |tp|
1161  * p tp.raised_exception
1162  * end
1163  * #=> RuntimeError: 'raised_exception' not supported by this event
1164  *
1165  * If the trace method is called outside block, a RuntimeError is raised.
1166  *
1167  * TracePoint.trace(:line) do |tp|
1168  * $tp = tp
1169  * end
1170  * $tp.line #=> access from outside (RuntimeError)
1171  *
1172  * Access from other threads is also forbidden.
1173  *
1174  */
1175 static VALUE
1177 {
1178  rb_event_flag_t events = 0;
1179  int i;
1180 
1181  if (argc > 0) {
1182  for (i=0; i<argc; i++) {
1183  events |= symbol2event_flag(argv[i]);
1184  }
1185  }
1186  else {
1187  events = RUBY_EVENT_TRACEPOINT_ALL;
1188  }
1189 
1190  if (!rb_block_given_p()) {
1191  rb_raise(rb_eThreadError, "must be called with a block");
1192  }
1193 
1194  return tracepoint_new(self, 0, events, 0, 0, rb_block_proc());
1195 }
1196 
1197 static VALUE
1199 {
1200  VALUE trace = tracepoint_new_s(argc, argv, self);
1201  rb_tracepoint_enable(trace);
1202  return trace;
1203 }
1204 
1205 /*
1206  * call-seq:
1207  * trace.inspect -> string
1208  *
1209  * Return a string containing a human-readable TracePoint
1210  * status.
1211  */
1212 
1213 static VALUE
1215 {
1216  rb_tp_t *tp = tpptr(self);
1217  rb_trace_arg_t *trace_arg = GET_THREAD()->trace_arg;
1218 
1219  if (trace_arg) {
1220  switch (trace_arg->event) {
1221  case RUBY_EVENT_LINE:
1223  {
1224  VALUE sym = rb_tracearg_method_id(trace_arg);
1225  if (NIL_P(sym))
1226  goto default_inspect;
1227  return rb_sprintf("#<TracePoint:%"PRIsVALUE"@%"PRIsVALUE":%d in `%"PRIsVALUE"'>",
1228  rb_tracearg_event(trace_arg),
1229  rb_tracearg_path(trace_arg),
1230  FIX2INT(rb_tracearg_lineno(trace_arg)),
1231  sym);
1232  }
1233  case RUBY_EVENT_CALL:
1234  case RUBY_EVENT_C_CALL:
1235  case RUBY_EVENT_RETURN:
1236  case RUBY_EVENT_C_RETURN:
1237  return rb_sprintf("#<TracePoint:%"PRIsVALUE" `%"PRIsVALUE"'@%"PRIsVALUE":%d>",
1238  rb_tracearg_event(trace_arg),
1239  rb_tracearg_method_id(trace_arg),
1240  rb_tracearg_path(trace_arg),
1241  FIX2INT(rb_tracearg_lineno(trace_arg)));
1243  case RUBY_EVENT_THREAD_END:
1244  return rb_sprintf("#<TracePoint:%"PRIsVALUE" %"PRIsVALUE">",
1245  rb_tracearg_event(trace_arg),
1246  rb_tracearg_self(trace_arg));
1247  default:
1249  return rb_sprintf("#<TracePoint:%"PRIsVALUE"@%"PRIsVALUE":%d>",
1250  rb_tracearg_event(trace_arg),
1251  rb_tracearg_path(trace_arg),
1252  FIX2INT(rb_tracearg_lineno(trace_arg)));
1253  }
1254  }
1255  else {
1256  return rb_sprintf("#<TracePoint:%s>", tp->tracing ? "enabled" : "disabled");
1257  }
1258 }
1259 
1260 /* This function is called from inits.c */
1261 void
1263 {
1264  /* trace_func */
1265  rb_define_global_function("set_trace_func", set_trace_func, 1);
1266  rb_define_method(rb_cThread, "set_trace_func", thread_set_trace_func_m, 1);
1267  rb_define_method(rb_cThread, "add_trace_func", thread_add_trace_func_m, 1);
1268 
1269  /*
1270  * Document-class: TracePoint
1271  *
1272  * A class that provides the functionality of Kernel#set_trace_func in a
1273  * nice Object-Oriented API.
1274  *
1275  * == Example
1276  *
1277  * We can use TracePoint to gather information specifically for exceptions:
1278  *
1279  * trace = TracePoint.new(:raise) do |tp|
1280  * p [tp.lineno, tp.event, tp.raised_exception]
1281  * end
1282  * #=> #<TracePoint:0x007f786a452448>
1283  *
1284  * trace.enable
1285  * #=> #<TracePoint:0x007f786a452448>
1286  *
1287  * 0 / 0
1288  * #=> [5, :raise, #<ZeroDivisionError: divided by 0>]
1289  *
1290  * == Events
1291  *
1292  * If you don't specify the type of events you want to listen for,
1293  * TracePoint will include all available events.
1294  *
1295  * *Note* do not depend on current event set, as this list is subject to
1296  * change. Instead, it is recommended you specify the type of events you
1297  * want to use.
1298  *
1299  * To filter what is traced, you can pass any of the following as +events+:
1300  *
1301  * +:line+:: execute code on a new line
1302  * +:class+:: start a class or module definition
1303  * +:end+:: finish a class or module definition
1304  * +:call+:: call a Ruby method
1305  * +:return+:: return from a Ruby method
1306  * +:c_call+:: call a C-language routine
1307  * +:c_return+:: return from a C-language routine
1308  * +:raise+:: raise an exception
1309  * +:b_call+:: event hook at block entry
1310  * +:b_return+:: event hook at block ending
1311  * +:thread_begin+:: event hook at thread beginning
1312  * +:thread_end+:: event hook at thread ending
1313  *
1314  */
1315  rb_cTracePoint = rb_define_class("TracePoint", rb_cObject);
1319  /*
1320  * Document-method: trace
1321  *
1322  * call-seq:
1323  * TracePoint.trace(*events) { |obj| block } -> obj
1324  *
1325  * A convenience method for TracePoint.new, that activates the trace
1326  * automatically.
1327  *
1328  * trace = TracePoint.trace(:call) { |tp| [tp.lineno, tp.event] }
1329  * #=> #<TracePoint:0x007f786a452448>
1330  *
1331  * trace.enabled? #=> true
1332  */
1334 
1338 
1340 
1350 }
1351 
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:607
#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:716
#define RUBY_EVENT_C_RETURN
Definition: ruby.h:1587
void rb_bug(const char *fmt,...)
Definition: error.c:295
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:743
void rb_undef_alloc_func(VALUE)
Definition: vm_method.c:493
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:789
static VALUE set_trace_func(VALUE obj, VALUE trace)
Definition: vm_trace.c:445
#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:584
#define RUBY_EVENT_ALL
Definition: ruby.h:1589
static VALUE tp_alloc(VALUE klass)
Definition: vm_trace.c:638
#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:784
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:1100
static VALUE tracepoint_attr_path(VALUE tpval)
Definition: vm_trace.c:837
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:964
static VALUE thread_add_trace_func_m(VALUE obj, VALUE trace)
Definition: vm_trace.c:482
#define RUBY_EVENT_CALL
Definition: ruby.h:1584
VALUE rb_eTypeError
Definition: error.c:516
#define TH_JUMP_TAG(th, st)
Definition: eval_intern.h:144
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:537
void rb_threadptr_exec_event_hooks(rb_trace_arg_t *trace_arg)
Definition: vm_trace.c:339
static size_t tp_memsize(const void *ptr)
Definition: vm_trace.c:627
static rb_tp_t * tpptr(VALUE tpval)
Definition: vm_trace.c:669
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:1788
static VALUE tracepoint_attr_event(VALUE tpval)
Definition: vm_trace.c:819
rb_thread_t * target_th
Definition: vm_trace.c:602
VALUE rb_convert_type(VALUE, int, const char *, const char *)
Definition: object.c:2425
#define TH_EXEC_TAG()
Definition: eval_intern.h:139
VALUE rb_tracearg_path(rb_trace_arg_t *trace_arg)
Definition: vm_trace.c:722
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:750
void rb_gc_mark(VALUE ptr)
Definition: gc.c:2600
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
VALUE rb_tracearg_event(rb_trace_arg_t *trace_arg)
Definition: vm_trace.c:693
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:520
#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:333
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:1262
#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:564
#define FL_SINGLETON
Definition: ruby.h:1111
struct rb_trace_arg_struct * rb_tracearg_from_tracepoint(VALUE tpval)
Definition: vm_trace.c:687
int rb_vm_control_frame_id_and_class(const rb_control_frame_t *cfp, ID *idp, VALUE *klassp)
Definition: vm.c:1524
#define RB_TYPE_P(obj, type)
Definition: ruby.h:1537
VALUE rb_binding_new(void)
Definition: proc.c:322
static rb_thread_t * thval2thread_t(VALUE thval)
Definition: vm_trace.c:94
#define TH_POP_TAG()
Definition: eval_intern.h:129
VALUE rb_tracearg_self(rb_trace_arg_t *trace_arg)
Definition: vm_trace.c:778
#define FL_TEST(x, f)
Definition: ruby.h:1146
VALUE rb_tracepoint_disable(VALUE tpval)
Definition: vm_trace.c:964
int rb_thread_method_id_and_class(rb_thread_t *th, ID *idp, VALUE *klassp)
Definition: vm.c:1552
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:2051
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:515
static VALUE tracepoint_enable_m(VALUE tpval)
Definition: vm_trace.c:1019
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:598
VALUE rb_tracearg_raised_exception(rb_trace_arg_t *trace_arg)
Definition: vm_trace.c:799
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:316
VALUE rb_tracepoint_enabled_p(VALUE tpval)
Definition: vm_trace.c:1093
VALUE rb_iv_get(VALUE, const char *)
Definition: variable.c:2586
#define JUMP_TAG(st)
Definition: eval_intern.h:148
rb_iseq_t * iseq
Definition: vm_core.h:428
static VALUE tracepoint_attr_defined_class(VALUE tpval)
Definition: vm_trace.c:886
#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:503
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:488
rb_control_frame_t * cfp
Definition: vm_core.h:965
VALUE rb_tracearg_defined_class(rb_trace_arg_t *trace_arg)
Definition: vm_trace.c:757
int argc
Definition: ruby.c:130
VALUE proc
Definition: vm_trace.c:605
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:764
#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:699
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:1214
static rb_event_flag_t symbol2event_flag(VALUE v)
Definition: vm_trace.c:645
static void fill_id_and_klass(rb_trace_arg_t *trace_arg)
Definition: vm_trace.c:729
#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:933
#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:925
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:604
VALUE rb_sprintf(const char *format,...)
Definition: sprintf.c:1275
static void tp_free(void *ptr)
Definition: vm_trace.c:621
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:916
#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:2061
#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:122
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:632
#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:828
static VALUE tracepoint_disable_m(VALUE tpval)
Definition: vm_trace.c:1070
static rb_trace_arg_t * get_trace_arg(void)
Definition: vm_trace.c:677
VALUE rb_mRubyVMFrozenCore
Definition: vm.c:92
static void thread_add_trace_func(rb_thread_t *th, VALUE trace)
Definition: vm_trace.c:464
static VALUE tracepoint_trace_s(int argc, VALUE *argv, VALUE self)
Definition: vm_trace.c:1198
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:931
#define MAX_EVENT_NUM
Definition: vm_trace.c:44
#define INT2FIX(i)
Definition: ruby.h:241
int rb_sourceline(void)
Definition: vm.c:884
VALUE rb_block_proc(void)
Definition: proc.c:458
static void tp_mark(void *ptr)
Definition: vm_trace.c:611
VALUE rb_tracepoint_enable(VALUE tpval)
Definition: vm_trace.c:944
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:895
#define RTEST(v)
Definition: ruby.h:445
VALUE rb_suppress_tracing(VALUE(*func)(VALUE), VALUE arg)
Definition: vm_trace.c:345
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:1116
#define ID2SYM(x)
Definition: ruby.h:363
rb_event_flag_t event
Definition: vm_core.h:963
const char * rb_id2name(ID id)
Definition: ripper.c:17012
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:907
#define CALL(n)
Definition: inits.c:15
static rb_thread_t * GET_THREAD(void)
Definition: vm_core.h:890
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:1006
static VALUE tracepoint_attr_method_id(VALUE tpval)
Definition: vm_trace.c:846
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:2002
VALUE rb_eThreadError
Definition: eval.c:690
rb_event_flag_t events
Definition: vm_trace.c:601
VALUE rb_eArgError
Definition: error.c:517
struct rb_trace_arg_struct * trace_arg
Definition: vm_core.h:604
void(* func)(VALUE tpval, void *data)
Definition: vm_trace.c:603
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:1176
#define GET_VM()
Definition: vm_core.h:883