Skip to content

Commit c706b91

Browse files
committed
YJIT: Add RubyVM::YJIT.code_gc
1 parent 9cf027f commit c706b91

File tree

4 files changed

+24
-11
lines changed

4 files changed

+24
-11
lines changed

test/ruby/test_yjit.rb

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -830,10 +830,10 @@ def foo
830830
def test_code_gc
831831
assert_compiles(code_gc_helpers + <<~'RUBY', exits: :any, result: :ok)
832832
return :not_paged unless add_pages(100) # prepare freeable pages
833-
code_gc # first code GC
833+
RubyVM::YJIT.code_gc # first code GC
834834
return :not_compiled1 unless compiles { nil } # should be JITable again
835835
836-
code_gc # second code GC
836+
RubyVM::YJIT.code_gc # second code GC
837837
return :not_compiled2 unless compiles { nil } # should be JITable again
838838
839839
code_gc_count = RubyVM::YJIT.runtime_stats[:code_gc_count]
@@ -854,7 +854,7 @@ def test_on_stack_code_gc_call
854854
855855
return :not_paged1 unless add_pages(400) # go to a page without initial ocb code
856856
return :broken_resume1 if fiber.resume != 0 # JIT the fiber
857-
code_gc # first code GC, which should not free the fiber page
857+
RubyVM::YJIT.code_gc # first code GC, which should not free the fiber page
858858
return :broken_resume2 if fiber.resume != 0 # The code should be still callable
859859
860860
code_gc_count = RubyVM::YJIT.runtime_stats[:code_gc_count]
@@ -873,19 +873,19 @@ def test_on_stack_code_gc_twice
873873
874874
return :not_paged1 unless add_pages(400) # go to a page without initial ocb code
875875
return :broken_resume1 if fiber.resume(true) != 0 # JIT the fiber
876-
code_gc # first code GC, which should not free the fiber page
876+
RubyVM::YJIT.code_gc # first code GC, which should not free the fiber page
877877
878878
return :not_paged2 unless add_pages(300) # add some stuff to be freed
879879
# Not calling fiber.resume here to test the case that the YJIT payload loses some
880880
# information at the previous code GC. The payload should still be there, and
881881
# thus we could know the fiber ISEQ is still on stack on this second code GC.
882-
code_gc # second code GC, which should still not free the fiber page
882+
RubyVM::YJIT.code_gc # second code GC, which should still not free the fiber page
883883
884884
return :not_paged3 unless add_pages(200) # attempt to overwrite the fiber page (it shouldn't)
885885
return :broken_resume2 if fiber.resume(true) != 0 # The fiber code should be still fine
886886
887887
return :broken_resume3 if fiber.resume(false) != nil # terminate the fiber
888-
code_gc # third code GC, freeing a page that used to be on stack
888+
RubyVM::YJIT.code_gc # third code GC, freeing a page that used to be on stack
889889
890890
return :not_paged4 unless add_pages(100) # check everything still works
891891
@@ -933,11 +933,6 @@ def add_pages(num_jits)
933933
num_jits.times { return false unless eval('compiles { nil.to_i }') }
934934
pages.nil? || pages < RubyVM::YJIT.runtime_stats[:compiled_page_count]
935935
end
936-
937-
def code_gc
938-
RubyVM::YJIT.simulate_oom! # bump write_pos
939-
eval('proc { nil }.call') # trigger code GC
940-
end
941936
RUBY
942937
end
943938

yjit.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1053,6 +1053,7 @@ VALUE rb_yjit_get_stats(rb_execution_context_t *ec, VALUE self);
10531053
VALUE rb_yjit_reset_stats_bang(rb_execution_context_t *ec, VALUE self);
10541054
VALUE rb_yjit_disasm_iseq(rb_execution_context_t *ec, VALUE self, VALUE iseq);
10551055
VALUE rb_yjit_insns_compiled(rb_execution_context_t *ec, VALUE self, VALUE iseq);
1056+
VALUE rb_yjit_code_gc(rb_execution_context_t *ec, VALUE self);
10561057
VALUE rb_yjit_simulate_oom_bang(rb_execution_context_t *ec, VALUE self);
10571058
VALUE rb_yjit_get_exit_locations(rb_execution_context_t *ec, VALUE self);
10581059

yjit.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,11 @@ def self.insns_compiled(iseq)
162162
end
163163
end
164164

165+
# Free and recompile all existing JIT code
166+
def self.code_gc
167+
Primitive.rb_yjit_code_gc
168+
end
169+
165170
def self.simulate_oom!
166171
Primitive.rb_yjit_simulate_oom_bang
167172
end

yjit/src/yjit.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,18 @@ pub extern "C" fn rb_yjit_iseq_gen_entry_point(iseq: IseqPtr, ec: EcPtr) -> *con
7979
}
8080
}
8181

82+
/// Free and recompile all existing JIT code
83+
#[no_mangle]
84+
pub extern "C" fn rb_yjit_code_gc(_ec: EcPtr, _ruby_self: VALUE) -> VALUE {
85+
if !yjit_enabled_p() {
86+
return Qnil;
87+
}
88+
89+
let cb = CodegenGlobals::get_inline_cb();
90+
cb.code_gc();
91+
Qnil
92+
}
93+
8294
/// Simulate a situation where we are out of executable memory
8395
#[no_mangle]
8496
pub extern "C" fn rb_yjit_simulate_oom_bang(_ec: EcPtr, _ruby_self: VALUE) -> VALUE {

0 commit comments

Comments
 (0)