Ruby 2.1.5p273(2014-11-13revision48405)

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