|
4 | 4 | #include <ruby/debug.h> |
5 | 5 | #include <stdbool.h> |
6 | 6 |
|
7 | | -static VALUE caller_frame(int *line, bool ruby_call) { |
8 | | - VALUE frames[2] = {Qnil, Qnil}; |
9 | | - int lines[2] = {0, 0}; |
| 7 | +static VALUE caller_frame(int *line) { |
| 8 | + VALUE frame = Qnil; |
| 9 | + int frame_line = 0; |
10 | 10 |
|
11 | | - // At this point, for ruby calls, the top ruby stack frame is |
12 | | - // for the method being called, so we want to skip that frame |
13 | | - // and get the caller location. This is why we use 1 for ruby |
14 | | - // calls. |
15 | | - // |
16 | | - // However, for C call, the top stack frame is for the caller, |
17 | | - // so we don't want to have to skip over any extra stack frames |
18 | | - // for C calls. |
19 | | - int frame_index = ruby_call ? 1 : 0; |
| 11 | + // For ruby calls, the top frame is the callee — skip it to get the caller. |
| 12 | + // Ruby 4.0+ fixed rb_profile_frames start argument (ruby-lang bug #14607). |
| 13 | + rb_profile_frames(1, 1, &frame, &frame_line); |
20 | 14 |
|
21 | | - // There is currently a bug in rb_profile_frames that |
22 | | - // causes the start argument to effectively always |
23 | | - // act as if it were 0, so we need to also get the top |
24 | | - // frame. (https://bugs.ruby-lang.org/issues/14607) |
25 | | - rb_profile_frames(0, frame_index + 1, frames, lines); |
26 | | - |
27 | | - *line = lines[frame_index]; |
28 | | - return frames[frame_index]; |
| 15 | + *line = frame_line; |
| 16 | + return frame; |
29 | 17 | } |
30 | 18 |
|
31 | 19 | rs_callsite_t c_callsite(rb_trace_arg_t *trace_arg) { |
32 | | - int line; |
33 | | - VALUE frame = caller_frame(&line, false); |
34 | 20 | return (rs_callsite_t){ |
35 | 21 | .filepath = rb_tracearg_path(trace_arg), |
36 | 22 | .lineno = FIX2INT(rb_tracearg_lineno(trace_arg)), |
37 | | - .method_name = rb_profile_frame_method_name(frame), |
38 | | - .singleton_p = rb_profile_frame_singleton_method_p(frame), |
| 23 | + .method_name = Qnil, |
| 24 | + .singleton_p = Qnil, |
| 25 | + .profile_frame = Qnil, |
39 | 26 | }; |
40 | 27 | } |
41 | 28 |
|
42 | 29 | rs_callsite_t ruby_callsite() { |
43 | 30 | int line; |
44 | | - VALUE frame = caller_frame(&line, true); |
| 31 | + VALUE frame = caller_frame(&line); |
45 | 32 |
|
46 | 33 | return (rs_callsite_t){ |
47 | 34 | .filepath = rb_profile_frame_path(frame), |
48 | 35 | .lineno = line, |
49 | | - .method_name = rb_profile_frame_method_name(frame), |
50 | | - .singleton_p = rb_profile_frame_singleton_method_p(frame), |
| 36 | + .method_name = Qnil, // filled from stack or profile_frame in event_hook |
| 37 | + .singleton_p = Qnil, |
| 38 | + .profile_frame = frame, |
51 | 39 | }; |
52 | 40 | } |
0 commit comments