Skip to content

Commit a9f6fe0

Browse files
committed
Avoid marking CC children after invalidation
Once klass becomes Qundef, it's disconnected and won't be invalidated when the CME is. So once that happens we must not mark or attempt to move the cme_ field.
1 parent ba4a36e commit a9f6fe0

File tree

1 file changed

+21
-12
lines changed

1 file changed

+21
-12
lines changed

imemo.c

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -337,28 +337,37 @@ rb_imemo_mark_and_move(VALUE obj, bool reference_updating)
337337
* cc->klass (klass) should not be marked because if the klass is
338338
* free'ed, the cc->klass will be cleared by `vm_cc_invalidate()`.
339339
*
340-
* cc->cme (cme) should not be marked because if cc is invalidated
341-
* when cme is free'ed.
340+
* For "normal" CCs cc->cme (cme) should not be marked because the cc is
341+
* invalidated through the klass when the cme is free'd.
342342
* - klass marks cme if klass uses cme.
343-
* - caller classe's ccs->cme marks cc->cme.
344-
* - if cc is invalidated (klass doesn't refer the cc),
345-
* cc is invalidated by `vm_cc_invalidate()` and cc->cme is
346-
* not be accessed.
347-
* - On the multi-Ractors, cme will be collected with global GC
343+
* - caller class's ccs->cme marks cc->cme.
344+
* - if cc is invalidated (klass doesn't refer the cc), cc is
345+
* invalidated by `vm_cc_invalidate()` after which cc->cme must not
346+
* be accessed.
347+
* - With multi-Ractors, cme will be collected with global GC
348348
* so that it is safe if GC is not interleaving while accessing
349349
* cc and cme.
350-
* - However, cc_type_super and cc_type_refinement are not chained
351-
* from ccs so cc->cme should be marked; the cme might be
352-
* reachable only through cc in these cases.
350+
*
351+
* However cc_type_super and cc_type_refinement are not chained
352+
* from ccs so cc->cme should be marked as long as the cc is valid;
353+
* the cme might be reachable only through cc in these cases.
353354
*/
354355
struct rb_callcache *cc = (struct rb_callcache *)obj;
355-
if (reference_updating) {
356+
if (UNDEF_P(cc->klass)) {
357+
/* If it's invalidated, we must not mark anything.
358+
* All fields should are considered invalid
359+
*/
360+
}
361+
else if (reference_updating) {
356362
if (moved_or_living_object_strictly_p((VALUE)cc->cme_)) {
357363
*((VALUE *)&cc->klass) = rb_gc_location(cc->klass);
358364
*((struct rb_callable_method_entry_struct **)&cc->cme_) =
359365
(struct rb_callable_method_entry_struct *)rb_gc_location((VALUE)cc->cme_);
366+
367+
RUBY_ASSERT(RB_TYPE_P(cc->klass, T_CLASS) || RB_TYPE_P(cc->klass, T_ICLASS));
368+
RUBY_ASSERT(IMEMO_TYPE_P((VALUE)cc->cme_, imemo_ment));
360369
}
361-
else if (vm_cc_valid(cc)) {
370+
else {
362371
vm_cc_invalidate(cc);
363372
}
364373
}

0 commit comments

Comments
 (0)