diff options
author | Ruby <test@ruby-lang.org> | 2023-07-26 13:39:31 +0900 |
---|---|---|
committer | Koichi Sasada <ko1@atdot.net> | 2023-07-28 10:51:11 +0900 |
commit | c330037c1a38cc257dbe21022fcc7b13159c2821 (patch) | |
tree | 508edd219ceb6c97b83ef8888f505efc4fc95dcf /gc.c | |
parent | 44b19b01e22c0e2b24e97cbcab80aee953f978fd (diff) |
`cc->cme` should not be marked.
cc is callcache.
cc->klass (klass) should not be marked because if the klass is
free'ed, the cc->klass will be cleared by `vm_cc_invalidate()`.
cc->cme (cme) should not be marked because if cc is invalidated
when cme is free'ed.
- klass marks cme if klass uses cme.
- caller classe's ccs->cme marks cc->cme.
- if cc is invalidated (klass doesn't refer the cc),
cc is invalidated by `vm_cc_invalidate()` and cc->cme is
not be accessed.
- On the multi-Ractors, cme will be collected with global GC
so that it is safe if GC is not interleaving while accessing
cc and cme.
fix [Bug #19436]
```ruby
10_000.times{|i|
# p i if (i%1_000) == 0
str = "x" * 1_000_000
def str.foo = nil
eval "def call#{i}(s) = s.foo"
send "call#{i}", str
}
```
Without this patch:
```
real 1m5.639s
user 0m6.637s
sys 0m58.292s
```
and with this patch:
```
real 0m2.045s
user 0m1.627s
sys 0m0.164s
```
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/8120
Diffstat (limited to 'gc.c')
-rw-r--r-- | gc.c | 33 |
1 files changed, 23 insertions, 10 deletions
@@ -7015,11 +7015,22 @@ gc_mark_imemo(rb_objspace_t *objspace, VALUE obj) case imemo_callinfo: return; case imemo_callcache: - { - const struct rb_callcache *cc = (const struct rb_callcache *)obj; - // should not mark klass here - gc_mark(objspace, (VALUE)vm_cc_cme(cc)); - } + /* cc is callcache. + * + * cc->klass (klass) should not be marked because if the klass is + * free'ed, the cc->klass will be cleared by `vm_cc_invalidate()`. + * + * cc->cme (cme) should not be marked because if cc is invalidated + * when cme is free'ed. + * - klass marks cme if klass uses cme. + * - caller classe's ccs->cme marks cc->cme. + * - if cc is invalidated (klass doesn't refer the cc), + * cc is invalidated by `vm_cc_invalidate()` and cc->cme is + * not be accessed. + * - On the multi-Ractors, cme will be collected with global GC + * so that it is safe if GC is not interleaving while accessing + * cc and cme. + */ return; case imemo_constcache: { @@ -10122,12 +10133,14 @@ gc_ref_update_imemo(rb_objspace_t *objspace, VALUE obj) if (!is_live_object(objspace, cc->klass)) { *((VALUE *)(&cc->klass)) = (VALUE)0; } - } - if (cc->cme_) { - TYPED_UPDATE_IF_MOVED(objspace, struct rb_callable_method_entry_struct *, cc->cme_); - if (!is_live_object(objspace, (VALUE)cc->cme_)) { - *((struct rb_callable_method_entry_struct **)(&cc->cme_)) = (struct rb_callable_method_entry_struct *)0; + // cc->cme_ is available if cc->klass is given + + if (cc->cme_) { + TYPED_UPDATE_IF_MOVED(objspace, struct rb_callable_method_entry_struct *, cc->cme_); + if (!is_live_object(objspace, (VALUE)cc->cme_)) { + *((struct rb_callable_method_entry_struct **)(&cc->cme_)) = (struct rb_callable_method_entry_struct *)0; + } } } } |