Skip to content

Commit 4a4a702

Browse files
committed
* vm_trace.c, vm_core.h: simplify tracing mechanism.
(1) add rb_hook_list_t data structure which includes hooks, events (flag) and `need_clean' flag. If the last flag is true, then clean the hooks list. In other words, deleted hooks are contained by `hooks'. Cleanup process should run before traversing the list. (2) Change check mechanism See EXEC_EVENT_HOOK() in vm_core.h. (3) Add `raw' hooks APIs Normal hooks are guarded from exception by rb_protect(). However, this protection is overhead for too simple functions which never cause exceptions. `raw' hooks are executed without protection and faster. Now, we only provide registration APIs. All `raw' hooks are kicked under protection (same as normal hooks). * include/ruby/ruby.h: remove internal data definition and macros. * internal.h (ruby_suppress_tracing), vm_trace.c: rename ruby_suppress_tracing() to rb_suppress_tracing() and remove unused function parameter. * parse.y: fix to use renamed rb_suppress_tracing(). * thread.c (thread_create_core): no need to set RUBY_VM_VM. * vm.c (mark_event_hooks): move definition to vm_trace.c. * vm.c (ruby_vm_event_flags): add a global variable. This global variable represents all of Threads and VM's event masks (T1#events | T2#events | ... | VM#events). You can check the possibility kick trace func or not with ruby_vm_event_flags. ruby_vm_event_flags is maintained by vm_trace.c. * cont.c (fiber_switch, rb_cont_call): restore tracing status. [Feature ruby#4347] * test/ruby/test_continuation.rb: ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@36715 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
1 parent 9528358 commit 4a4a702

File tree

10 files changed

+335
-329
lines changed

10 files changed

+335
-329
lines changed

ChangeLog

+44
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,47 @@
1+
Thu Aug 16 19:54:24 2012 Koichi Sasada <ko1@atdot.net>
2+
3+
* vm_trace.c, vm_core.h: simplify tracing mechanism.
4+
5+
(1) add rb_hook_list_t data structure which includes
6+
hooks, events (flag) and `need_clean' flag.
7+
If the last flag is true, then clean the hooks list.
8+
In other words, deleted hooks are contained by `hooks'.
9+
Cleanup process should run before traversing the list.
10+
(2) Change check mechanism
11+
See EXEC_EVENT_HOOK() in vm_core.h.
12+
(3) Add `raw' hooks APIs
13+
Normal hooks are guarded from exception by rb_protect().
14+
However, this protection is overhead for too simple
15+
functions which never cause exceptions. `raw' hooks
16+
are executed without protection and faster.
17+
Now, we only provide registration APIs. All `raw'
18+
hooks are kicked under protection (same as normal hooks).
19+
20+
* include/ruby/ruby.h: remove internal data definition and
21+
macros.
22+
23+
* internal.h (ruby_suppress_tracing), vm_trace.c: rename
24+
ruby_suppress_tracing() to rb_suppress_tracing()
25+
and remove unused function parameter.
26+
27+
* parse.y: fix to use renamed rb_suppress_tracing().
28+
29+
* thread.c (thread_create_core): no need to set RUBY_VM_VM.
30+
31+
* vm.c (mark_event_hooks): move definition to vm_trace.c.
32+
33+
* vm.c (ruby_vm_event_flags): add a global variable.
34+
This global variable represents all of Threads and VM's
35+
event masks (T1#events | T2#events | ... | VM#events).
36+
You can check the possibility kick trace func or not
37+
with ruby_vm_event_flags.
38+
ruby_vm_event_flags is maintained by vm_trace.c.
39+
40+
* cont.c (fiber_switch, rb_cont_call): restore tracing status.
41+
[Feature #4347]
42+
43+
* test/ruby/test_continuation.rb: ditto.
44+
145
Thu Aug 16 19:15:23 2012 Nobuyoshi Nakada <nobu@ruby-lang.org>
246

347
* object.c (rb_class_initialize): forbid inheriting uninitialized

cont.c

+7
Original file line numberDiff line numberDiff line change
@@ -929,6 +929,9 @@ rb_cont_call(int argc, VALUE *argv, VALUE contval)
929929
cont->argc = argc;
930930
cont->value = make_passing_arg(argc, argv);
931931

932+
/* restore `tracing' context. see [Feature #4347] */
933+
th->trace_running = cont->saved_thread.trace_running;
934+
932935
cont_restore_0(cont, &contval);
933936
return Qnil; /* unreachable */
934937
}
@@ -1317,6 +1320,10 @@ fiber_switch(VALUE fibval, int argc, VALUE *argv, int is_resume)
13171320
if (is_resume) {
13181321
fib->prev = rb_fiber_current();
13191322
}
1323+
else {
1324+
/* restore `tracing' context. see [Feature #4347] */
1325+
th->trace_running = cont->saved_thread.trace_running;
1326+
}
13201327

13211328
cont->argc = argc;
13221329
cont->value = make_passing_arg(argc, argv);

include/ruby/ruby.h

+2-11
Original file line numberDiff line numberDiff line change
@@ -1408,24 +1408,15 @@ int ruby_native_thread_p(void);
14081408
#define RUBY_EVENT_C_CALL 0x0020
14091409
#define RUBY_EVENT_C_RETURN 0x0040
14101410
#define RUBY_EVENT_RAISE 0x0080
1411-
#define RUBY_EVENT_ALL 0xffff
1412-
#define RUBY_EVENT_VM 0x10000
1411+
#define RUBY_EVENT_ALL 0x00ff
14131412
#define RUBY_EVENT_SWITCH 0x20000
14141413
#define RUBY_EVENT_COVERAGE 0x40000
14151414

14161415
typedef unsigned int rb_event_flag_t;
14171416
typedef void (*rb_event_hook_func_t)(rb_event_flag_t evflag, VALUE data, VALUE self, ID mid, VALUE klass);
14181417

1419-
typedef struct rb_event_hook_struct {
1420-
rb_event_flag_t flag;
1421-
rb_event_hook_func_t func;
1422-
VALUE data;
1423-
struct rb_event_hook_struct *next;
1424-
} rb_event_hook_t;
1425-
14261418
#define RB_EVENT_HOOKS_HAVE_CALLBACK_DATA 1
1427-
void rb_add_event_hook(rb_event_hook_func_t func, rb_event_flag_t events,
1428-
VALUE data);
1419+
void rb_add_event_hook(rb_event_hook_func_t func, rb_event_flag_t events, VALUE data);
14291420
int rb_remove_event_hook(rb_event_hook_func_t func);
14301421

14311422
/* locale insensitive functions */

internal.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ struct timeval rb_time_timeval(VALUE);
247247

248248
/* thread.c */
249249
VALUE rb_obj_is_mutex(VALUE obj);
250-
VALUE ruby_suppress_tracing(VALUE (*func)(VALUE, int), VALUE arg, int always);
250+
VALUE rb_suppress_tracing(VALUE (*func)(VALUE), VALUE arg);
251251
void rb_thread_execute_interrupts(VALUE th);
252252
void rb_clear_trace_func(void);
253253
VALUE rb_get_coverages(void);

parse.y

+2-2
Original file line numberDiff line numberDiff line change
@@ -5418,7 +5418,7 @@ e_option_supplied(struct parser_params *parser)
54185418
}
54195419

54205420
static VALUE
5421-
yycompile0(VALUE arg, int tracing)
5421+
yycompile0(VALUE arg)
54225422
{
54235423
int n;
54245424
NODE *tree;
@@ -5470,7 +5470,7 @@ yycompile(struct parser_params *parser, const char *f, int line)
54705470
{
54715471
ruby_sourcefile = ruby_strdup(f);
54725472
ruby_sourceline = line - 1;
5473-
return (NODE *)ruby_suppress_tracing(yycompile0, (VALUE)parser, TRUE);
5473+
return (NODE *)rb_suppress_tracing(yycompile0, (VALUE)parser);
54745474
}
54755475
#endif /* !RIPPER */
54765476

test/ruby/test_continuation.rb

+13-5
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,12 @@ def tracing_with_set_trace_func
8282
cont = nil
8383
func = lambda do |*args|
8484
if orig_thread == Thread.current
85-
@memo += 1
86-
cont.call(nil)
85+
if cont
86+
@memo += 1
87+
c = cont
88+
cont = nil
89+
c.call(nil)
90+
end
8791
end
8892
end
8993
cont = callcc { |cc| cc }
@@ -105,14 +109,18 @@ def test_tracing_with_set_trace_func
105109
def tracing_with_thread_set_trace_func
106110
cont = nil
107111
func = lambda do |*args|
108-
@memo += 1
109-
cont.call(nil)
112+
if cont
113+
@memo += 1
114+
c = cont
115+
cont = nil
116+
c.call(nil)
117+
end
110118
end
111119
cont = callcc { |cc| cc }
112120
if cont
113121
Thread.current.set_trace_func(func)
114122
else
115-
Thread.current.set_trace_func(nil)
123+
set_trace_func(nil)
116124
end
117125
end
118126

thread.c

-2
Original file line numberDiff line numberDiff line change
@@ -568,8 +568,6 @@ thread_create_core(VALUE thval, VALUE args, VALUE (*fn)(ANYARGS))
568568
RBASIC(th->async_errinfo_mask_stack)->klass = 0;
569569

570570
native_mutex_initialize(&th->interrupt_lock);
571-
if (GET_VM()->event_hooks != NULL)
572-
th->event_flags |= RUBY_EVENT_VM;
573571

574572
/* kick thread */
575573
st_insert(th->vm->living_threads, thval, (st_data_t) th->thread_id);

vm.c

+4-10
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ VALUE ruby_vm_const_missing_count = 0;
8383
char ruby_vm_redefined_flag[BOP_LAST_];
8484
rb_thread_t *ruby_current_thread = 0;
8585
rb_vm_t *ruby_current_vm = 0;
86+
rb_event_flag_t ruby_vm_event_flags;
8687

8788
static void thread_free(void *ptr);
8889

@@ -1462,14 +1463,7 @@ vm_mark_each_thread_func(st_data_t key, st_data_t value, st_data_t dummy)
14621463
return ST_CONTINUE;
14631464
}
14641465

1465-
static void
1466-
mark_event_hooks(rb_event_hook_t *hook)
1467-
{
1468-
while (hook) {
1469-
rb_gc_mark(hook->data);
1470-
hook = hook->next;
1471-
}
1472-
}
1466+
void vm_trace_mark_event_hooks(rb_hook_list_t *hooks);
14731467

14741468
void
14751469
rb_vm_mark(void *ptr)
@@ -1495,7 +1489,7 @@ rb_vm_mark(void *ptr)
14951489
rb_mark_tbl(vm->loading_table);
14961490
}
14971491

1498-
mark_event_hooks(vm->event_hooks);
1492+
vm_trace_mark_event_hooks(&vm->event_hooks);
14991493

15001494
for (i = 0; i < RUBY_NSIG; i++) {
15011495
if (vm->trap_list[i].cmd)
@@ -1671,7 +1665,7 @@ rb_thread_mark(void *ptr)
16711665
sizeof(th->machine_regs) / sizeof(VALUE));
16721666
}
16731667

1674-
mark_event_hooks(th->event_hooks);
1668+
vm_trace_mark_event_hooks(&th->event_hooks);
16751669
}
16761670

16771671
RUBY_MARK_LEAVE("thread");

vm_core.h

+12-7
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,12 @@ struct rb_objspace;
290290
void rb_objspace_free(struct rb_objspace *);
291291
#endif
292292

293+
typedef struct rb_hook_list_struct {
294+
struct rb_event_hook_struct *hooks;
295+
rb_event_flag_t events;
296+
int need_clean;
297+
} rb_hook_list_t;
298+
293299
typedef struct rb_vm_struct {
294300
VALUE self;
295301

@@ -325,7 +331,7 @@ typedef struct rb_vm_struct {
325331
} trap_list[RUBY_NSIG];
326332

327333
/* hook */
328-
rb_event_hook_t *event_hooks;
334+
rb_hook_list_t event_hooks;
329335

330336
int src_encoding_index;
331337

@@ -513,9 +519,8 @@ typedef struct rb_thread_struct {
513519
VALUE stat_insn_usage;
514520

515521
/* tracer */
516-
rb_event_hook_t *event_hooks;
517-
rb_event_flag_t event_flags;
518-
int tracing;
522+
rb_hook_list_t event_hooks;
523+
int trace_running;
519524

520525
/* fiber */
521526
VALUE fiber;
@@ -764,6 +769,7 @@ int rb_autoloading_value(VALUE mod, ID id, VALUE* value);
764769
#if RUBY_VM_THREAD_MODEL == 2
765770
extern rb_thread_t *ruby_current_thread;
766771
extern rb_vm_t *ruby_current_vm;
772+
extern rb_event_flag_t ruby_vm_event_flags;
767773

768774
#define GET_VM() ruby_current_vm
769775
#define GET_THREAD() ruby_current_thread
@@ -817,9 +823,8 @@ void
817823
rb_threadptr_exec_event_hooks(rb_thread_t *th, rb_event_flag_t flag, VALUE self, ID id, VALUE klass);
818824

819825
#define EXEC_EVENT_HOOK(th, flag, self, id, klass) do { \
820-
rb_event_flag_t wait_event__ = (th)->event_flags; \
821-
if (UNLIKELY(wait_event__)) { \
822-
if (wait_event__ & ((flag) | RUBY_EVENT_VM)) { \
826+
if (UNLIKELY(ruby_vm_event_flags & (flag))) { \
827+
if (((th)->event_hooks.events | (th)->vm->event_hooks.events) & (flag)) { \
823828
rb_threadptr_exec_event_hooks((th), (flag), (self), (id), (klass)); \
824829
} \
825830
} \

0 commit comments

Comments
 (0)