Skip to content

Commit ec245ef

Browse files
authored
Merge pull request #180 from Shopify/yjit-head-compat
Use postponed jobs if YJIT is enabled.
2 parents df24b85 + 179c5ac commit ec245ef

3 files changed

Lines changed: 35 additions & 19 deletions

File tree

ext/stackprof/stackprof.c

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -25,20 +25,14 @@
2525
#define FAKE_FRAME_MARK INT2FIX(1)
2626
#define FAKE_FRAME_SWEEP INT2FIX(2)
2727

28-
/*
29-
* As of Ruby 3.0, it should be safe to read stack frames at any time
30-
* See https://github.com/ruby/ruby/commit/0e276dc458f94d9d79a0f7c7669bde84abe80f21
31-
*/
32-
#if RUBY_API_VERSION_MAJOR < 3
33-
#define USE_POSTPONED_JOB
34-
#endif
35-
3628
static const char *fake_frame_cstrs[] = {
3729
"(garbage collection)",
3830
"(marking)",
3931
"(sweeping)",
4032
};
4133

34+
static int stackprof_use_postponed_job = 1;
35+
4236
#define TOTAL_FAKE_FRAMES (sizeof(fake_frame_cstrs) / sizeof(char *))
4337

4438
#ifdef _POSIX_MONOTONIC_CLOCK
@@ -701,15 +695,13 @@ stackprof_job_record_gc(void *data)
701695
stackprof_record_gc_samples();
702696
}
703697

704-
#ifdef USE_POSTPONED_JOB
705698
static void
706699
stackprof_job_sample_and_record(void *data)
707700
{
708701
if (!_stackprof.running) return;
709702

710703
stackprof_sample_and_record();
711704
}
712-
#endif
713705

714706
static void
715707
stackprof_job_record_buffer(void *data)
@@ -740,15 +732,15 @@ stackprof_signal_handler(int sig, siginfo_t *sinfo, void *ucontext)
740732
_stackprof.unrecorded_gc_samples++;
741733
rb_postponed_job_register_one(0, stackprof_job_record_gc, (void*)0);
742734
} else {
743-
#ifdef USE_POSTPONED_JOB
744-
rb_postponed_job_register_one(0, stackprof_job_sample_and_record, (void*)0);
745-
#else
746-
// Buffer a sample immediately, if an existing sample exists this will
747-
// return immediately
748-
stackprof_buffer_sample();
749-
// Enqueue a job to record the sample
750-
rb_postponed_job_register_one(0, stackprof_job_record_buffer, (void*)0);
751-
#endif
735+
if (stackprof_use_postponed_job) {
736+
rb_postponed_job_register_one(0, stackprof_job_sample_and_record, (void*)0);
737+
} else {
738+
// Buffer a sample immediately, if an existing sample exists this will
739+
// return immediately
740+
stackprof_buffer_sample();
741+
// Enqueue a job to record the sample
742+
rb_postponed_job_register_one(0, stackprof_job_record_buffer, (void*)0);
743+
}
752744
}
753745
pthread_mutex_unlock(&lock);
754746
}
@@ -826,9 +818,24 @@ stackprof_atfork_child(void)
826818
stackprof_stop(rb_mStackProf);
827819
}
828820

821+
static VALUE
822+
stackprof_use_postponed_job_l(VALUE self)
823+
{
824+
stackprof_use_postponed_job = 1;
825+
return Qnil;
826+
}
827+
829828
void
830829
Init_stackprof(void)
831830
{
831+
/*
832+
* As of Ruby 3.0, it should be safe to read stack frames at any time, unless YJIT is enabled
833+
* See https://github.com/ruby/ruby/commit/0e276dc458f94d9d79a0f7c7669bde84abe80f21
834+
*/
835+
#if RUBY_API_VERSION_MAJOR < 3
836+
stackprof_use_postponed_job = 0;
837+
#endif
838+
832839
size_t i;
833840
#define S(name) sym_##name = ID2SYM(rb_intern(#name));
834841
S(object);
@@ -890,6 +897,7 @@ Init_stackprof(void)
890897
rb_define_singleton_method(rb_mStackProf, "stop", stackprof_stop, 0);
891898
rb_define_singleton_method(rb_mStackProf, "results", stackprof_results, -1);
892899
rb_define_singleton_method(rb_mStackProf, "sample", stackprof_sample, 0);
900+
rb_define_singleton_method(rb_mStackProf, "use_postponed_job!", stackprof_use_postponed_job_l, 0);
893901

894902
pthread_atfork(stackprof_atfork_prepare, stackprof_atfork_parent, stackprof_atfork_child);
895903
}

lib/stackprof.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
require "stackprof/stackprof"
22

3+
if defined?(RubyVM::YJIT) && RubyVM::YJIT.enabled?
4+
StackProf.use_postponed_job!
5+
end
6+
37
module StackProf
48
VERSION = '0.2.19'
59
end

test/test_stackprof.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55
require 'pathname'
66

77
class StackProfTest < MiniTest::Test
8+
def setup
9+
Object.new # warm some caches to avoid flakiness
10+
end
11+
812
def test_info
913
profile = StackProf.run{}
1014
assert_equal 1.2, profile[:version]

0 commit comments

Comments
 (0)