From a0b0365e905e1ac51998ace7e6fc723406a2f157 Mon Sep 17 00:00:00 2001 From: Alan Wu Date: Tue, 29 Nov 2022 16:14:13 -0500 Subject: YJIT: Deallocate `struct Block` to plug memory leaks Previously we essentially never freed block even after invalidation. Their reference count never reached zero for a couple of reasons: 1. `Branch::block` formed a cycle with the block holding the branch 2. Strong count on a branch that has ever contained a stub never reached 0 because we increment the `.clone()` call for `BranchRef::into_raw()` didn't have a matching decrement. It's not safe to immediately deallocate blocks during invalidation since `branch_stub_hit()` can end up running with a branch pointer from an invalidated branch. To plug the leaks, we wait until code GC or global invalidation and deallocate the blocks for iseqs that are definitely not running. --- bootstraptest/test_yjit.rb | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'bootstraptest') diff --git a/bootstraptest/test_yjit.rb b/bootstraptest/test_yjit.rb index 175f5bd86c..25085f0e8d 100644 --- a/bootstraptest/test_yjit.rb +++ b/bootstraptest/test_yjit.rb @@ -3423,3 +3423,16 @@ assert_equal '1', %q{ bar { } bar { } } + +# test for return stub lifetime issue +assert_equal '1', %q{ + def foo(n) + if n == 2 + return 1.times { Object.define_method(:foo) {} } + end + + foo(n + 1) + end + + foo(1) +} -- cgit v1.2.3