summaryrefslogtreecommitdiff
path: root/gc.c
diff options
context:
space:
mode:
authorKoichi Sasada <ko1@atdot.net>2023-07-29 13:41:28 +0900
committerKoichi Sasada <ko1@atdot.net>2023-07-29 14:25:15 +0900
commit7a7aba755d8da34555445510dc568380d0d96791 (patch)
tree6a0b69c25d66b27d1437bf83b9c19bd417c95934 /gc.c
parentb0f44cfa5da53b90817732cb25b4d3a1cddecb89 (diff)
check liveness of cc->klass and cc->cme_
`cc->klass` and `cc->cme_` can be free'ed while last marking so that it should be checked bofore updating the pointers. Note that `T_MOVED` is living, but `is_live_object()` returns false.
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/8139
Diffstat (limited to 'gc.c')
-rw-r--r--gc.c22
1 files changed, 13 insertions, 9 deletions
diff --git a/gc.c b/gc.c
index d45bd0b789..d60e564216 100644
--- a/gc.c
+++ b/gc.c
@@ -10128,16 +10128,20 @@ gc_ref_update_imemo(rb_objspace_t *objspace, VALUE obj)
case imemo_callcache:
{
const struct rb_callcache *cc = (const struct rb_callcache *)obj;
- if (cc->klass) {
- UPDATE_IF_MOVED(objspace, cc->klass);
- if (!is_live_object(objspace, cc->klass)) {
- vm_cc_invalidate(cc);
- }
- else if (cc->cme_) { // cc->cme_ is available if cc->klass is given
+
+ if (!cc->klass) {
+ // already invalidated
+ }
+ else {
+ if ( // cc->klass is living
+ (BUILTIN_TYPE(cc->klass) == T_MOVED || is_live_object(objspace, cc->klass)) &&
+ // cc->cme_ is living
+ (cc->cme_ && ((BUILTIN_TYPE((VALUE)cc->cme_) == T_MOVED) || is_live_object(objspace, (VALUE)cc->cme_)))) {
+ UPDATE_IF_MOVED(objspace, cc->klass);
TYPED_UPDATE_IF_MOVED(objspace, struct rb_callable_method_entry_struct *, cc->cme_);
- if (!is_live_object(objspace, (VALUE)cc->cme_)) {
- vm_cc_invalidate(cc);
- }
+ }
+ else {
+ vm_cc_invalidate(cc);
}
}
}