Ruby 2.0.0p353(2013-11-22revision43784)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

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 {
35 rb_event_hook_flag_t hook_flags;
36 rb_event_flag_t events;
37 rb_event_hook_func_t func;
38 VALUE data;
39 struct rb_event_hook_struct *next;
40 } rb_event_hook_t;
41
42 typedef void (*rb_event_hook_raw_arg_func_t)(VALUE data, const rb_trace_arg_t *arg);
43
44 #define MAX_EVENT_NUM 32
45
46 static int ruby_event_flag_count[MAX_EVENT_NUM] = {0};
47
48 /* called from vm.c */
49
50 void
51 vm_trace_mark_event_hooks(rb_hook_list_t *hooks)
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
64 recalc_add_ruby_vm_event_flags(rb_event_flag_t events)
65 {
66 int i;
67 ruby_vm_event_flags = 0;
68
69 for (i=0; i<MAX_EVENT_NUM; i++) {
70 if (events & (1 << i)) {
71 ruby_event_flag_count[i]++;
72 }
73 ruby_vm_event_flags |= ruby_event_flag_count[i] ? (1<<i) : 0;
74 }
75 }
76
77 static void
78 recalc_remove_ruby_vm_event_flags(rb_event_flag_t events)
79 {
80 int i;
81 ruby_vm_event_flags = 0;
82
83 for (i=0; i<MAX_EVENT_NUM; i++) {
84 if (events & (1 << i)) {
85 ruby_event_flag_count[i]--;
86 }
87 ruby_vm_event_flags |= ruby_event_flag_count[i] ? (1<<i) : 0;
88 }
89 }
90
91 /* add/remove hooks */
92
93 static rb_thread_t *
94 thval2thread_t(VALUE thval)
95 {
96 rb_thread_t *th;
97 GetThreadPtr(thval, th);
98 return th;
99 }
100
101 static rb_event_hook_t *
102 alloc_event_hook(rb_event_hook_func_t func, rb_event_flag_t events, VALUE data, rb_event_hook_flag_t hook_flags)
103 {
104 rb_event_hook_t *hook = ALLOC(rb_event_hook_t);
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
113 connect_event_hook(rb_hook_list_t *list, rb_event_hook_t *hook)
114 {
115 hook->next = list->hooks;
116 list->hooks = hook;
117 recalc_add_ruby_vm_event_flags(hook->events);
118 list->events |= hook->events;
119 }
120
121 static void
122 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)
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
129 rb_thread_add_event_hook(VALUE thval, rb_event_hook_func_t func, rb_event_flag_t events, VALUE data)
130 {
131 rb_threadptr_add_event_hook(thval2thread_t(thval), func, events, data, RUBY_EVENT_HOOK_FLAG_SAFE);
132 }
133
134 void
135 rb_add_event_hook(rb_event_hook_func_t func, rb_event_flag_t events, VALUE data)
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
142 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)
143 {
144 rb_threadptr_add_event_hook(thval2thread_t(thval), func, events, data, hook_flags);
145 }
146
147 void
148 rb_add_event_hook2(rb_event_hook_func_t func, rb_event_flag_t events, VALUE data, rb_event_hook_flag_t hook_flags)
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
156 remove_event_hook(rb_hook_list_t *list, rb_event_hook_func_t func, VALUE data)
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) {
164 hook->hook_flags |= RUBY_EVENT_HOOK_FLAG_DELETED;
165 ret+=1;
166 list->need_clean++;
167 }
168 }
169 hook = hook->next;
170 }
171
172 return ret;
173 }
174
175 static int
176 rb_threadptr_remove_event_hook(rb_thread_t *th, rb_event_hook_func_t func, VALUE data)
177 {
178 return remove_event_hook(&th->event_hooks, func, data);
179 }
180
181 int
182 rb_thread_remove_event_hook(VALUE thval, rb_event_hook_func_t func)
183 {
184 return rb_threadptr_remove_event_hook(thval2thread_t(thval), func, Qundef);
185 }
186
187 int
188 rb_thread_remove_event_hook_with_data(VALUE thval, rb_event_hook_func_t func, VALUE data)
189 {
190 return rb_threadptr_remove_event_hook(thval2thread_t(thval), func, data);
191 }
192
193 int
194 rb_remove_event_hook(rb_event_hook_func_t func)
195 {
196 return remove_event_hook(&GET_VM()->event_hooks, func, Qundef);
197 }
198
199 int
200 rb_remove_event_hook_with_data(rb_event_hook_func_t func, VALUE data)
201 {
202 return remove_event_hook(&GET_VM()->event_hooks, func, data);
203 }
204
205 static int
206 clear_trace_func_i(st_data_t key, st_data_t val, st_data_t flag)
207 {
208 rb_thread_t *th;
209 GetThreadPtr((VALUE)key, th);
210 rb_threadptr_remove_event_hook(th, 0, Qundef);
211 return ST_CONTINUE;
212 }
213
214 void
215 rb_clear_trace_func(void)
216 {
217 st_foreach(GET_VM()->living_threads, clear_trace_func_i, (st_data_t) 0);
218 rb_remove_event_hook(0);
219 }
220
221 /* invoke hooks */
222
223 static void
224 clean_hooks(rb_hook_list_t *list)
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) {
232 if (hook->hook_flags & RUBY_EVENT_HOOK_FLAG_DELETED) {
233 *nextp = hook->next;
234 recalc_remove_ruby_vm_event_flags(hook->events);
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) {
276 rb_threadptr_set_raised(th);
277 }
278
279 return state;
280 }
281
282 static void
283 rb_threadptr_exec_event_hooks_orig(rb_trace_arg_t *trace_arg, int pop_p)
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 {
297 rb_hook_list_t *list;
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 }
323 th->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp);
324 }
325 TH_JUMP_TAG(th, state);
326 }
327 th->state = outer_state;
328 }
329 }
330
331 void
332 rb_threadptr_exec_event_hooks_and_pop_frame(rb_trace_arg_t *trace_arg)
333 {
334 rb_threadptr_exec_event_hooks_orig(trace_arg, 1);
335 }
336
337 void
338 rb_threadptr_exec_event_hooks(rb_trace_arg_t *trace_arg)
339 {
340 rb_threadptr_exec_event_hooks_orig(trace_arg, 0);
341 }
342
343 VALUE
344 rb_suppress_tracing(VALUE (*func)(VALUE), VALUE arg)
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) {
368 rb_threadptr_set_raised(th);
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
444 set_trace_func(VALUE obj, VALUE trace)
445 {
446 rb_secure(4);
447
448 rb_remove_event_hook(call_trace_func);
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
458 rb_add_event_hook(call_trace_func, RUBY_EVENT_ALL, trace);
459 return trace;
460 }
461
462 static void
463 thread_add_trace_func(rb_thread_t *th, VALUE trace)
464 {
465 if (!rb_obj_is_proc(trace)) {
466 rb_raise(rb_eTypeError, "trace_func needs to be Proc");
467 }
468
469 rb_threadptr_add_event_hook(th, call_trace_func, RUBY_EVENT_ALL, trace, RUBY_EVENT_HOOK_FLAG_SAFE);
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
481 thread_add_trace_func_m(VALUE obj, VALUE trace)
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
502 thread_set_trace_func_m(VALUE obj, VALUE trace)
503 {
504 rb_thread_t *th;
505
506 rb_secure(4);
507 GetThreadPtr(obj, th);
508 rb_threadptr_remove_event_hook(th, call_trace_func, Qundef);
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 *
519 get_event_name(rb_event_flag_t event)
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
536 get_event_id(rb_event_flag_t event)
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
597 static VALUE rb_cTracePoint;
598
599 typedef struct rb_tp_struct {
600 rb_event_flag_t events;
601 rb_thread_t *target_th;
602 void (*func)(VALUE tpval, void *data);
603 void *data;
604 VALUE proc;
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",
633 {tp_mark, tp_free, tp_memsize,},
634 };
635
636 static VALUE
637 tp_alloc(VALUE klass)
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
644 symbol2event_flag(VALUE v)
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 *
676 get_trace_arg(void)
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 *
686 rb_tracearg_from_tracepoint(VALUE tpval)
687 {
688 return get_trace_arg();
689 }
690
691 VALUE
692 rb_tracearg_event(rb_trace_arg_t *trace_arg)
693 {
694 return ID2SYM(get_event_id(trace_arg->event));
695 }
696
697 static void
698 fill_path_and_lineno(rb_trace_arg_t *trace_arg)
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
715 rb_tracearg_lineno(rb_trace_arg_t *trace_arg)
716 {
717 fill_path_and_lineno(trace_arg);
718 return INT2FIX(trace_arg->lineno);
719 }
720 VALUE
721 rb_tracearg_path(rb_trace_arg_t *trace_arg)
722 {
723 fill_path_and_lineno(trace_arg);
724 return trace_arg->path;
725 }
726
727 static void
728 fill_id_and_klass(rb_trace_arg_t *trace_arg)
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
749 rb_tracearg_method_id(rb_trace_arg_t *trace_arg)
750 {
751 fill_id_and_klass(trace_arg);
752 return trace_arg->id ? ID2SYM(trace_arg->id) : Qnil;
753 }
754
755 VALUE
756 rb_tracearg_defined_class(rb_trace_arg_t *trace_arg)
757 {
758 fill_id_and_klass(trace_arg);
759 return trace_arg->klass;
760 }
761
762 VALUE
763 rb_tracearg_binding(rb_trace_arg_t *trace_arg)
764 {
765 rb_control_frame_t *cfp;
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
777 rb_tracearg_self(rb_trace_arg_t *trace_arg)
778 {
779 return trace_arg->self;
780 }
781
782 VALUE
783 rb_tracearg_return_value(rb_trace_arg_t *trace_arg)
784 {
785 if (trace_arg->event & (RUBY_EVENT_RETURN | RUBY_EVENT_C_RETURN | RUBY_EVENT_B_RETURN)) {
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
798 rb_tracearg_raised_exception(rb_trace_arg_t *trace_arg)
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
818 tracepoint_attr_event(VALUE tpval)
819 {
820 return rb_tracearg_event(get_trace_arg());
821 }
822
823 /*
824 * Line number of the event
825 */
826 static VALUE
827 tracepoint_attr_lineno(VALUE tpval)
828 {
829 return rb_tracearg_lineno(get_trace_arg());
830 }
831
832 /*
833 * Path of the file being run
834 */
835 static VALUE
836 tracepoint_attr_path(VALUE tpval)
837 {
838 return rb_tracearg_path(get_trace_arg());
839 }
840
841 /*
842 * Return the name of the method being called
843 */
844 static VALUE
845 tracepoint_attr_method_id(VALUE tpval)
846 {
847 return rb_tracearg_method_id(get_trace_arg());
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
885 tracepoint_attr_defined_class(VALUE tpval)
886 {
887 return rb_tracearg_defined_class(get_trace_arg());
888 }
889
890 /*
891 * Return the generated binding object from event
892 */
893 static VALUE
894 tracepoint_attr_binding(VALUE tpval)
895 {
896 return rb_tracearg_binding(get_trace_arg());
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
906 tracepoint_attr_self(VALUE tpval)
907 {
908 return rb_tracearg_self(get_trace_arg());
909 }
910
911 /*
912 * Return value from +:return+, +c_return+, and +b_return+ event
913 */
914 static VALUE
915 tracepoint_attr_return_value(VALUE tpval)
916 {
917 return rb_tracearg_return_value(get_trace_arg());
918 }
919
920 /*
921 * Value from exception raised on the +:raise+ event
922 */
923 static VALUE
924 tracepoint_attr_raised_exception(VALUE tpval)
925 {
926 return rb_tracearg_raised_exception(get_trace_arg());
927 }
928
929 static void
930 tp_call_trace(VALUE tpval, rb_trace_arg_t *trace_arg)
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
943 rb_tracepoint_enable(VALUE tpval)
944 {
945 rb_tp_t *tp;
946
947 rb_secure(4);
948 tp = tpptr(tpval);
949
950 if (tp->target_th) {
951 rb_thread_add_event_hook2(tp->target_th->self, (rb_event_hook_func_t)tp_call_trace, tp->events, tpval,
952 RUBY_EVENT_HOOK_FLAG_SAFE | RUBY_EVENT_HOOK_FLAG_RAW_ARG);
953 }
954 else {
955 rb_add_event_hook2((rb_event_hook_func_t)tp_call_trace, tp->events, tpval,
956 RUBY_EVENT_HOOK_FLAG_SAFE | RUBY_EVENT_HOOK_FLAG_RAW_ARG);
957 }
958 tp->tracing = 1;
959 return Qundef;
960 }
961
962 VALUE
963 rb_tracepoint_disable(VALUE tpval)
964 {
965 rb_tp_t *tp;
966
967 rb_secure(4);
968 tp = tpptr(tpval);
969
970 if (tp->target_th) {
971 rb_thread_remove_event_hook_with_data(tp->target_th->self, (rb_event_hook_func_t)tp_call_trace, tpval);
972 }
973 else {
974 rb_remove_event_hook_with_data((rb_event_hook_func_t)tp_call_trace, tpval);
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
1018 tracepoint_enable_m(VALUE tpval)
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
1069 tracepoint_disable_m(VALUE tpval)
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
1092 rb_tracepoint_enabled_p(VALUE tpval)
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
1175 tracepoint_new_s(int argc, VALUE *argv, VALUE self)
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
1197 tracepoint_trace_s(int argc, VALUE *argv, VALUE self)
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
1213 tracepoint_inspect(VALUE self)
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:
1221 case RUBY_EVENT_SPECIFIED_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)));
1241 case RUBY_EVENT_THREAD_BEGIN:
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:
1247 default_inspect:
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
1261 Init_vm_trace(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
data
VALUE data
Definition: tcltklib.c:3368
rb_event_hook_func_t
void(* rb_event_hook_func_t)(rb_event_flag_t evflag, VALUE data, VALUE self, ID mid, VALUE klass)
Definition: ripper.y:1604
RB_TYPE_P
#define RB_TYPE_P(obj, type)
rb_thread_struct::cfp
rb_control_frame_t * cfp
Definition: vm_core.h:500
rb_tp_struct::self
VALUE self
Definition: vm_trace.c:606
rb_trace_arg_struct::klass
VALUE klass
Definition: vm_core.h:961
ALLOC
#define ALLOC(type)
RUBY_EVENT_B_RETURN
#define RUBY_EVENT_B_RETURN
RUBY_EVENT_THREAD_END
#define RUBY_EVENT_THREAD_END
rb_thread_struct::vm
rb_vm_t * vm
Definition: vm_core.h:495
rb_hook_list_struct::need_clean
int need_clean
Definition: vm_core.h:334
sym
VALUE sym
Definition: tkutil.c:1299
RUBY_EVENT_THREAD_BEGIN
#define RUBY_EVENT_THREAD_BEGIN
rb_bug
void rb_bug(const char *fmt,...)
Definition: error.c:290
rb_vm_get_binding_creatable_next_cfp
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
th
static VALUE VALUE th
Definition: tcltklib.c:2948
rb_vm_get_sourceline
int rb_vm_get_sourceline(const rb_control_frame_t *cfp)
Definition: vm_backtrace.c:33
RUBY_EVENT_CLASS
#define RUBY_EVENT_CLASS
VM_FRAME_TYPE_FINISH_P
#define VM_FRAME_TYPE_FINISH_P(cfp)
Definition: vm_core.h:741
FL_TEST
#define FL_TEST(x, f)
rb_define_singleton_method
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
RUBY_VM_PREVIOUS_CONTROL_FRAME
#define RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp)
Definition: vm_core.h:787
rb_thread_remove_event_hook
int rb_thread_remove_event_hook(VALUE thval, rb_event_hook_func_t func)
Definition: vm_trace.c:182
ruby.h
set_trace_func
static VALUE set_trace_func(VALUE obj, VALUE trace)
Definition: vm_trace.c:444
T_ICLASS
#define T_ICLASS
proc
VALUE proc
Definition: tcltklib.c:2959
func
SSL_METHOD *(* func)(void)
Definition: ossl_ssl.c:108
rb_secure
void rb_secure(int)
Definition: safe.c:79
debug.h
rb_event_hook_struct
Definition: vm_trace.c:34
i
ssize_t i
Definition: bigdecimal.c:5655
tp_alloc
static VALUE tp_alloc(VALUE klass)
Definition: vm_trace.c:637
RUBY_EVENT_C_RETURN
#define RUBY_EVENT_C_RETURN
RUBY_EVENT_LINE
#define RUBY_EVENT_LINE
eval_intern.h
tracepoint_new
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
ret
int ret
Definition: tcltklib.c:280
tracepoint_attr_path
static VALUE tracepoint_attr_path(VALUE tpval)
Definition: vm_trace.c:836
rb_iv_get
VALUE rb_iv_get(VALUE, const char *)
Definition: variable.c:2583
connect_event_hook
static void connect_event_hook(rb_hook_list_t *list, rb_event_hook_t *hook)
Definition: vm_trace.c:113
rb_trace_arg_struct::th
rb_thread_t * th
Definition: vm_core.h:957
thread_add_trace_func_m
static VALUE thread_add_trace_func_m(VALUE obj, VALUE trace)
Definition: vm_trace.c:481
rb_eTypeError
VALUE rb_eTypeError
Definition: error.c:511
rb_thread_add_event_hook
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
TH_JUMP_TAG
#define TH_JUMP_TAG(th, st)
Definition: eval_intern.h:116
rb_iseq_location_struct::path
VALUE path
Definition: vm_core.h:187
rb_add_event_hook2
void rb_add_event_hook2(rb_event_hook_func_t func, rb_event_flag_t events, VALUE data, rb_event_hook_flag_t hook_flag)
Definition: vm_trace.c:148
rb_threadptr_exec_event_hooks_orig
static void rb_threadptr_exec_event_hooks_orig(rb_trace_arg_t *trace_arg, int pop_p)
Definition: vm_trace.c:283
rb_tracearg_binding
VALUE rb_tracearg_binding(rb_trace_arg_t *trace_arg)
Definition: vm_trace.c:763
get_event_id
static ID get_event_id(rb_event_flag_t event)
Definition: vm_trace.c:536
CLASS_OF
#define CLASS_OF(v)
NIL_P
NIL_P(eventloop_thread)
Definition: tcltklib.c:4068
tp_memsize
static size_t tp_memsize(const void *ptr)
Definition: vm_trace.c:626
tpptr
static rb_tp_t * tpptr(VALUE tpval)
Definition: vm_trace.c:668
xfree
#define xfree
tp
register C_block * tp
Definition: crypt.c:311
rb_raise
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:1780
rb_thread_remove_event_hook_with_data
int rb_thread_remove_event_hook_with_data(VALUE thval, rb_event_hook_func_t func, VALUE data)
Definition: vm_trace.c:188
Qtrue
return Qtrue
Definition: tcltklib.c:9610
tracepoint_attr_event
static VALUE tracepoint_attr_event(VALUE tpval)
Definition: vm_trace.c:818
rb_tp_struct::target_th
rb_thread_t * target_th
Definition: vm_trace.c:601
C
#define C
Definition: util.c:194
RUBY_EVENT_END
#define RUBY_EVENT_END
TH_EXEC_TAG
#define TH_EXEC_TAG()
Definition: eval_intern.h:111
clean_hooks
static void clean_hooks(rb_hook_list_t *list)
Definition: vm_trace.c:224
rb_hook_list_struct
Definition: vm_core.h:331
recalc_remove_ruby_vm_event_flags
static void recalc_remove_ruby_vm_event_flags(rb_event_flag_t events)
Definition: vm_trace.c:78
rb_str_new2
#define rb_str_new2
rb_define_global_function
void rb_define_global_function(const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a global function.
Definition: class.c:1526
state
int state
Definition: tcltklib.c:1462
rb_tracepoint_enabled_p
VALUE rb_tracepoint_enabled_p(VALUE tpval)
Definition: vm_trace.c:1092
rb_hook_list_struct::events
rb_event_flag_t events
Definition: vm_core.h:333
rb_thread_struct
Definition: vm_core.h:493
RUBY_EVENT_TRACEPOINT_ALL
#define RUBY_EVENT_TRACEPOINT_ALL
ID2SYM
#define ID2SYM(x)
get_event_name
static const char * get_event_name(rb_event_flag_t event)
Definition: vm_trace.c:519
LIKELY
#define LIKELY(x)
Definition: vm_core.h:114
rb_undef_method
void rb_undef_method(VALUE klass, const char *name)
Definition: class.c:1362
recalc_add_ruby_vm_event_flags
static void recalc_add_ruby_vm_event_flags(rb_event_flag_t events)
Definition: vm_trace.c:64
rb_tp_t
struct rb_tp_struct rb_tp_t
flag
flag
Definition: tcltklib.c:2048
clear_trace_func_i
static int clear_trace_func_i(st_data_t key, st_data_t val, st_data_t flag)
Definition: vm_trace.c:206
rb_event_flag_t
unsigned long rb_event_flag_t
Definition: ripper.y:1603
Init_vm_trace
void Init_vm_trace(void)
Definition: vm_trace.c:1261
call_trace_func
static void call_trace_func(rb_event_flag_t, VALUE data, VALUE self, ID id, VALUE klass)
Definition: vm_trace.c:563
st_data_t
unsigned long st_data_t
Definition: ripper.y:35
rb_tracearg_event
VALUE rb_tracearg_event(rb_trace_arg_t *trace_arg)
Definition: vm_trace.c:692
rb_vm_control_frame_id_and_class
int rb_vm_control_frame_id_and_class(const rb_control_frame_t *cfp, ID *idp, VALUE *klassp)
Definition: vm.c:1455
thval2thread_t
static rb_thread_t * thval2thread_t(VALUE thval)
Definition: vm_trace.c:94
TH_POP_TAG
#define TH_POP_TAG()
Definition: eval_intern.h:101
rb_binding_new
VALUE rb_binding_new(void)
Definition: proc.c:343
rb_block_proc
VALUE rb_block_proc(void)
Definition: proc.c:479
Qfalse
return Qfalse
Definition: tcltklib.c:6779
rb_thread_method_id_and_class
int rb_thread_method_id_and_class(rb_thread_t *th, ID *idp, VALUE *klassp)
Definition: vm.c:1483
rb_trace_arg_struct::klass_solved
int klass_solved
Definition: vm_core.h:964
TypedData_Get_Struct
#define TypedData_Get_Struct(obj, type, data_type, sval)
rb_vm_struct::trace_running
int trace_running
Definition: vm_core.h:351
rb_block_given_p
int rb_block_given_p(void)
Definition: eval.c:672
rb_threadptr_set_raised
int rb_threadptr_set_raised(rb_thread_t *th)
Definition: thread.c:2043
Qnil
#define Qnil
Definition: tcltklib.c:1896
rb_vm_get_ruby_level_next_cfp
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
rb_event_hook_struct::next
struct rb_event_hook_struct * next
Definition: vm_trace.c:39
val
#define val
Definition: tcltklib.c:1949
rb_eRuntimeError
VALUE rb_eRuntimeError
Definition: error.c:510
rb_tp_struct::func
void(* func)(VALUE tpval, void *data)
Definition: vm_trace.c:602
tracepoint_enable_m
static VALUE tracepoint_enable_m(VALUE tpval)
Definition: vm_trace.c:1018
rb_threadptr_add_event_hook
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
rb_tracearg_raised_exception
VALUE rb_tracearg_raised_exception(rb_trace_arg_t *trace_arg)
Definition: vm_trace.c:798
RUBY_EVENT_HOOK_FLAG_SAFE
Definition: debug.h:74
rb_cTracePoint
static VALUE rb_cTracePoint
Definition: vm_trace.c:597
exec_hooks
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
rb_binding_new_with_cfp
VALUE rb_binding_new_with_cfp(rb_thread_t *th, const rb_control_frame_t *src_cfp)
Definition: proc.c:314
ID
unsigned long ID
Definition: ripper.y:105
rb_tp_struct::tracing
int tracing
Definition: vm_trace.c:605
rb_gc_mark
void rb_gc_mark(VALUE)
Definition: gc.c:2598
JUMP_TAG
#define JUMP_TAG(st)
Definition: eval_intern.h:120
rb_control_frame_struct::iseq
rb_iseq_t * iseq
Definition: vm_core.h:428
tracepoint_attr_defined_class
static VALUE tracepoint_attr_defined_class(VALUE tpval)
Definition: vm_trace.c:885
rb_threadptr_exec_event_hooks_and_pop_frame
void rb_threadptr_exec_event_hooks_and_pop_frame(struct rb_trace_arg_struct *trace_arg)
Definition: vm_trace.c:332
UNLIKELY
#define UNLIKELY(x)
Definition: vm_core.h:115
thread_set_trace_func_m
static VALUE thread_set_trace_func_m(VALUE obj, VALUE trace)
Definition: vm_trace.c:502
rb_define_class
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:499
rb_trace_arg_struct::cfp
rb_control_frame_t * cfp
Definition: vm_core.h:958
obj
static VALUE VALUE obj
Definition: tcltklib.c:3158
FIX2INT
#define FIX2INT(x)
INT2FIX
#define INT2FIX(i)
RUBY_EVENT_HOOK_FLAG_DELETED
Definition: debug.h:75
RUBY_EVENT_RETURN
#define RUBY_EVENT_RETURN
rb_tp_struct::proc
VALUE proc
Definition: vm_trace.c:604
rb_sourcefile
#define rb_sourcefile()
Definition: tcltklib.c:97
rb_suppress_tracing
VALUE rb_suppress_tracing(VALUE(*func)(VALUE), VALUE arg)
Definition: vm_trace.c:344
rb_hook_list_struct::hooks
struct rb_event_hook_struct * hooks
Definition: vm_core.h:332
key
static int VALUE key
Definition: tkutil.c:265
rb_control_frame_struct
Definition: vm_core.h:425
fill_path_and_lineno
static void fill_path_and_lineno(rb_trace_arg_t *trace_arg)
Definition: vm_trace.c:698
encoding.h
ruby_event_flag_count
static int ruby_event_flag_count[MAX_EVENT_NUM]
Definition: vm_trace.c:46
END
#define END(no)
Definition: re.c:26
rb_tracearg_from_tracepoint
rb_trace_arg_t * rb_tracearg_from_tracepoint(VALUE tpval)
Definition: vm_trace.c:686
alloc_event_hook
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
tracepoint_inspect
static VALUE tracepoint_inspect(VALUE self)
Definition: vm_trace.c:1213
symbol2event_flag
static rb_event_flag_t symbol2event_flag(VALUE v)
Definition: vm_trace.c:644
fill_id_and_klass
static void fill_id_and_klass(rb_trace_arg_t *trace_arg)
Definition: vm_trace.c:728
RETURN
#define RETURN(val)
Definition: dir.c:177
argv
VALUE * argv
Definition: tcltklib.c:1971
rb_thread_struct::event_hooks
rb_hook_list_t event_hooks
Definition: vm_core.h:603
rb_yield
VALUE rb_yield(VALUE)
Definition: vm_eval.c:934
rb_event_hook_struct::func
rb_event_hook_func_t func
Definition: vm_trace.c:37
RTEST
#define RTEST(v)
id
const int id
Definition: nkf.c:209
st_foreach
int st_foreach(st_table *, int(*)(ANYARGS), st_data_t)
Definition: st.c:1000
TRUE
#define TRUE
Definition: nkf.h:175
result
q result
Definition: tcltklib.c:7070
rb_tracearg_method_id
VALUE rb_tracearg_method_id(rb_trace_arg_t *trace_arg)
Definition: vm_trace.c:749
tracepoint_attr_raised_exception
static VALUE tracepoint_attr_raised_exception(VALUE tpval)
Definition: vm_trace.c:924
rb_tp_struct::data
void * data
Definition: vm_trace.c:603
rb_sprintf
VALUE rb_sprintf(const char *format,...)
Definition: sprintf.c:1270
rb_event_hook_raw_arg_func_t
void(* rb_event_hook_raw_arg_func_t)(VALUE data, const rb_trace_arg_t *arg)
Definition: vm_trace.c:42
rb_tracearg_defined_class
VALUE rb_tracearg_defined_class(rb_trace_arg_t *trace_arg)
Definition: vm_trace.c:756
CONST_ID
#define CONST_ID(var, str)
tp_free
static void tp_free(void *ptr)
Definition: vm_trace.c:620
void
VP_EXPORT void
Definition: bigdecimal.c:5083
remove_event_hook
static int remove_event_hook(rb_hook_list_t *list, rb_event_hook_func_t func, VALUE data)
Definition: vm_trace.c:156
rb_proc_call_with_block
VALUE rb_proc_call_with_block(VALUE, int argc, VALUE *argv, VALUE)
Definition: proc.c:605
rb_trace_arg_struct::id
ID id
Definition: vm_core.h:960
internal.h
RUBY_EVENT_HOOK_FLAG_RAW_ARG
Definition: debug.h:76
tracepoint_attr_return_value
static VALUE tracepoint_attr_return_value(VALUE tpval)
Definition: vm_trace.c:915
rb_tracepoint_new
VALUE rb_tracepoint_new(VALUE target_thread_not_supported_yet, rb_event_flag_t events, void(*func)(VALUE, void *), void *data)
Definition: vm_trace.c:1115
vm_core.h
argc
int argc
Definition: tcltklib.c:1970
rb_remove_event_hook
int rb_remove_event_hook(rb_event_hook_func_t func)
Definition: vm_trace.c:194
rb_event_hook_flag_t
rb_event_hook_flag_t
Definition: debug.h:73
rb_threadptr_reset_raised
int rb_threadptr_reset_raised(rb_thread_t *th)
Definition: thread.c:2053
rb_undef_alloc_func
void rb_undef_alloc_func(VALUE)
Definition: vm_method.c:482
rb_tracearg_lineno
VALUE rb_tracearg_lineno(rb_trace_arg_t *trace_arg)
Definition: vm_trace.c:715
rb_iseq_struct::location
rb_iseq_location_t location
Definition: vm_core.h:213
TH_PUSH_TAG
#define TH_PUSH_TAG(th)
Definition: eval_intern.h:94
ST_CONTINUE
Definition: ripper.y:108
rb_ensure
VALUE rb_ensure(VALUE(*b_proc)(ANYARGS), VALUE data1, VALUE(*e_proc)(ANYARGS), VALUE data2)
Definition: eval.c:804
tp_data_type
static const rb_data_type_t tp_data_type
Definition: vm_trace.c:631
rb_event_hook_struct::hook_flags
rb_event_hook_flag_t hook_flags
Definition: vm_trace.c:35
rb_sourceline
int rb_sourceline(void)
Definition: vm.c:816
ptr
return ptr
Definition: tcltklib.c:784
rb_threadptr_remove_event_hook
static int rb_threadptr_remove_event_hook(rb_thread_t *th, rb_event_hook_func_t func, VALUE data)
Definition: vm_trace.c:176
rb_obj_is_proc
VALUE rb_obj_is_proc(VALUE)
Definition: proc.c:91
tracepoint_attr_lineno
static VALUE tracepoint_attr_lineno(VALUE tpval)
Definition: vm_trace.c:827
tracepoint_disable_m
static VALUE tracepoint_disable_m(VALUE tpval)
Definition: vm_trace.c:1069
end
gz end
Definition: zlib.c:2272
vm_trace_mark_event_hooks
void vm_trace_mark_event_hooks(rb_hook_list_t *hooks)
Definition: vm_trace.c:51
get_trace_arg
static rb_trace_arg_t * get_trace_arg(void)
Definition: vm_trace.c:676
rb_mRubyVMFrozenCore
VALUE rb_mRubyVMFrozenCore
Definition: vm.c:92
thread_add_trace_func
static void thread_add_trace_func(rb_thread_t *th, VALUE trace)
Definition: vm_trace.c:463
arg
arg
Definition: ripper.y:1315
T_SYMBOL
#define T_SYMBOL
tracepoint_trace_s
static VALUE tracepoint_trace_s(int argc, VALUE *argv, VALUE self)
Definition: vm_trace.c:1197
rb_event_hook_t
struct rb_event_hook_struct rb_event_hook_t
tp_call_trace
static void tp_call_trace(VALUE tpval, rb_trace_arg_t *trace_arg)
Definition: vm_trace.c:930
MAX_EVENT_NUM
#define MAX_EVENT_NUM
Definition: vm_trace.c:44
FL_SINGLETON
#define FL_SINGLETON
Qundef
#define Qundef
rb_trace_arg_struct::self
VALUE self
Definition: vm_core.h:959
tp_mark
static void tp_mark(void *ptr)
Definition: vm_trace.c:610
RUBY_EVENT_SPECIFIED_LINE
#define RUBY_EVENT_SPECIFIED_LINE
rb_thread_add_event_hook2
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_flag)
Definition: vm_trace.c:142
rb_data_type_struct
Definition: ripper.y:960
rb_vm_struct::event_hooks
rb_hook_list_t event_hooks
Definition: vm_core.h:377
rb_trace_arg_struct::path
VALUE path
Definition: vm_core.h:968
TypedData_Make_Struct
#define TypedData_Make_Struct(klass, type, data_type, sval)
rb_cObject
RUBY_EXTERN VALUE rb_cObject
Definition: ripper.y:1426
RBASIC
#define RBASIC(obj)
tracepoint_attr_binding
static VALUE tracepoint_attr_binding(VALUE tpval)
Definition: vm_trace.c:894
rb_trace_arg_struct
Definition: vm_core.h:955
rb_tp_struct
Definition: vm_trace.c:599
klass
klass
Definition: tcltklib.c:3504
ruby_vm_event_flags
rb_event_flag_t ruby_vm_event_flags
Definition: vm.c:98
list
struct rb_encoding_entry * list
Definition: encoding.c:50
rb_tracearg_path
VALUE rb_tracearg_path(rb_trace_arg_t *trace_arg)
Definition: vm_trace.c:721
rb_thread_struct::state
int state
Definition: vm_core.h:506
GetThreadPtr
#define GetThreadPtr(obj, ptr)
Definition: vm_core.h:452
RUBY_EVENT_RAISE
#define RUBY_EVENT_RAISE
rb_trace_arg_struct::lineno
int lineno
Definition: vm_core.h:967
rb_trace_arg_struct::event
rb_event_flag_t event
Definition: vm_core.h:956
rb_id2name
const char * rb_id2name(ID id)
Definition: ripper.c:17005
rb_thread_struct::self
VALUE self
Definition: vm_core.h:494
PRIsVALUE
#define PRIsVALUE
rb_thread_struct::tag
struct rb_vm_tag * tag
Definition: vm_core.h:561
rb_vm_tag::prev
struct rb_vm_tag * prev
Definition: vm_core.h:472
VALUE
unsigned long VALUE
Definition: ripper.y:104
rb_tracepoint_enable
VALUE rb_tracepoint_enable(VALUE tpval)
Definition: vm_trace.c:943
rb_event_hook_struct::data
VALUE data
Definition: vm_trace.c:38
rb_trace_arg_struct::data
VALUE data
Definition: vm_core.h:962
rb_clear_trace_func
void rb_clear_trace_func(void)
Definition: vm_trace.c:215
rb_threadptr_exec_event_hooks
void rb_threadptr_exec_event_hooks(struct rb_trace_arg_struct *trace_arg)
Definition: vm_trace.c:338
RUBY_EVENT_ALL
#define RUBY_EVENT_ALL
v
BDIGIT v
Definition: bigdecimal.c:5656
rb_add_event_hook
void rb_add_event_hook(rb_event_hook_func_t func, rb_event_flag_t events, VALUE data)
Definition: vm_trace.c:135
rb_tracearg_return_value
VALUE rb_tracearg_return_value(rb_trace_arg_t *trace_arg)
Definition: vm_trace.c:783
rb_thread_struct::errinfo
VALUE errinfo
Definition: vm_core.h:542
tracepoint_attr_self
static VALUE tracepoint_attr_self(VALUE tpval)
Definition: vm_trace.c:906
CALL
#define CALL(n)
Definition: inits.c:15
rb_remove_event_hook_with_data
int rb_remove_event_hook_with_data(rb_event_hook_func_t func, VALUE data)
Definition: vm_trace.c:200
GET_THREAD
static rb_thread_t * GET_THREAD(void)
Definition: vm_core.h:883
rb_define_method
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1344
RUBY_EVENT_C_CALL
#define RUBY_EVENT_C_CALL
tracepoint_attr_method_id
static VALUE tracepoint_attr_method_id(VALUE tpval)
Definition: vm_trace.c:845
rb_tracearg_self
VALUE rb_tracearg_self(rb_trace_arg_t *trace_arg)
Definition: vm_trace.c:777
rb_tracepoint_disable
VALUE rb_tracepoint_disable(VALUE tpval)
Definition: vm_trace.c:963
rb_event_hook_struct::events
rb_event_flag_t events
Definition: vm_trace.c:36
default_inspect
static VALUE default_inspect(VALUE self, const char *class_name)
Definition: win32ole.c:2003
SYM2ID
#define SYM2ID(x)
rb_eThreadError
VALUE rb_eThreadError
Definition: eval.c:690
rb_tp_struct::events
rb_event_flag_t events
Definition: vm_trace.c:600
rb_eArgError
VALUE rb_eArgError
Definition: error.c:512
rb_convert_type
VALUE rb_convert_type(VALUE, int, const char *, const char *)
Definition: object.c:2368
rb_cThread
RUBY_EXTERN VALUE rb_cThread
Definition: ripper.y:1459
rb_thread_struct::trace_arg
struct rb_trace_arg_struct * trace_arg
Definition: vm_core.h:604
RUBY_EVENT_CALL
#define RUBY_EVENT_CALL
tracepoint_new_s
static VALUE tracepoint_new_s(int argc, VALUE *argv, VALUE self)
Definition: vm_trace.c:1175
GET_VM
#define GET_VM()
Definition: vm_core.h:876