Ruby 4.1.0dev (2026-09-07 revision b57404b461ba8bf34e802d86b0db78388216e182)
imemo.c (b57404b461ba8bf34e802d86b0db78388216e182)
1
2#include "constant.h"
3#include "id_table.h"
4#include "internal.h"
5#include "internal/imemo.h"
6#include "internal/object.h"
7#include "internal/st.h"
8#include "vm_callinfo.h"
9
10size_t rb_iseq_memsize(const rb_iseq_t *iseq);
11void rb_iseq_mark_and_move(rb_iseq_t *iseq, bool reference_updating);
12void rb_iseq_free(const rb_iseq_t *iseq);
13
14ID
15rb_imemo_callinfo_mid(VALUE obj)
16{
17 RUBY_ASSERT(imemo_type(obj) == imemo_callinfo);
18 return vm_ci_mid((const struct rb_callinfo *)obj);
19}
20
21bool
22rb_imemo_callcache_get_data(VALUE obj, struct rb_imemo_callcache_data *data)
23{
24 const struct rb_callcache *cc = (const struct rb_callcache *)obj;
25
26 RUBY_ASSERT(imemo_type(obj) == imemo_callcache);
27
28 if (cc->klass == Qundef) return false;
29
30 data->klass = cc->klass;
31 data->called_id = vm_cc_cme(cc)->called_id;
32 return true;
33}
34
35const char *
36rb_imemo_name(enum imemo_type type)
37{
38 // put no default case to get a warning if an imemo type is missing
39 switch (type) {
40#define IMEMO_NAME(x) case imemo_##x: return #x;
41 IMEMO_NAME(callcache);
42 IMEMO_NAME(callinfo);
43 IMEMO_NAME(constcache);
44 IMEMO_NAME(cref);
45 IMEMO_NAME(env);
46 IMEMO_NAME(ifunc);
47 IMEMO_NAME(iseq);
48 IMEMO_NAME(memo);
49 IMEMO_NAME(ment);
50 IMEMO_NAME(svar);
51 IMEMO_NAME(throw_data);
52 IMEMO_NAME(tmpbuf);
53 IMEMO_NAME(cvar_entry);
54 IMEMO_NAME(fields);
55 IMEMO_NAME(subclasses);
56 IMEMO_NAME(cdhash);
57#undef IMEMO_NAME
58 }
59 rb_bug("unreachable");
60}
61
62/* =========================================================================
63 * allocation
64 * ========================================================================= */
65
67rb_imemo_new(enum imemo_type type, VALUE v0, size_t size, bool is_shareable)
68{
69 VALUE flags = T_IMEMO | (type << FL_USHIFT) | (is_shareable ? FL_SHAREABLE : 0);
70 return rb_newobj_of(v0, flags, size);
71}
72
74rb_imemo_tmpbuf_new(void)
75{
76 VALUE flags = T_IMEMO | (imemo_tmpbuf << FL_USHIFT);
77 UNPROTECTED_NEWOBJ_OF(obj, rb_imemo_tmpbuf_t, 0, flags, sizeof(rb_imemo_tmpbuf_t));
78
79 rb_gc_register_pinning_obj((VALUE)obj);
80
81 obj->marked = false;
82 obj->ptr = NULL;
83 obj->size = 0;
84
85 return (VALUE)obj;
86}
87
88void *
89rb_alloc_tmp_buffer(volatile VALUE *store, long len, bool marked)
90{
91 if (len < 0) {
92 rb_raise(rb_eArgError, "negative buffer size (or size too big)");
93 }
94
95 /* Keep the order; allocate an empty imemo first then xmalloc, to
96 * get rid of potential memory leak */
97 rb_imemo_tmpbuf_t *tmpbuf = (rb_imemo_tmpbuf_t *)rb_imemo_tmpbuf_new();
98 *store = (VALUE)tmpbuf;
99 void *ptr = ruby_xmalloc(len);
100 tmpbuf->marked = marked;
101 tmpbuf->ptr = ptr;
102 tmpbuf->size = len;
103
104 return ptr;
105}
106
107void
108rb_free_tmp_buffer(volatile VALUE *store)
109{
110 if (!*store) return;
111 rb_imemo_tmpbuf_t *s = (rb_imemo_tmpbuf_t*)ATOMIC_VALUE_EXCHANGE(*store, 0);
112 if (s) {
113 void *ptr = ATOMIC_PTR_EXCHANGE(s->ptr, 0);
114 long size = s->size;
115 s->size = 0;
116 ruby_xfree_sized(ptr, size);
117 }
118}
119
120struct MEMO *
121rb_imemo_memo_new(VALUE a, VALUE b, long c)
122{
123 struct MEMO *memo = IMEMO_NEW(struct MEMO, imemo_memo, 0);
124
125 *((VALUE *)&memo->v1) = a;
126 *((VALUE *)&memo->v2) = b;
127 memo->u3.cnt = c;
128
129 return memo;
130}
131
132struct MEMO *
133rb_imemo_memo_new_value(VALUE a, VALUE b, VALUE c)
134{
135 struct MEMO *memo = IMEMO_NEW(struct MEMO, imemo_memo, 0);
136
137 *((VALUE *)&memo->v1) = a;
138 *((VALUE *)&memo->v2) = b;
139 *((VALUE *)&memo->u3.value) = c;
140 memo->flags |= MEMO_U3_IS_VALUE;
141
142 return memo;
143}
144
145VALUE
146rb_imemo_cdhash_new(size_t size, const struct st_hash_type *type)
147{
148 struct rb_imemo_cdhash *memo = IMEMO_NEW(struct rb_imemo_cdhash, imemo_cdhash, 0);
149 memo->tbl.num_entries = 0;
150 st_init_existing_table_with_size(&memo->tbl, type, size);
151 return (VALUE)memo;
152}
153
154static VALUE
155imemo_fields_new(VALUE owner, shape_id_t shape_id, size_t size, bool is_shareable)
156{
157 RUBY_ASSERT(rb_gc_size_allocatable_p(size));
158
159 VALUE flags = T_IMEMO | (imemo_fields << FL_USHIFT) | (is_shareable ? FL_SHAREABLE : 0);
160 // imemo fields objects should always have "RObject" layout. The
161 // layout in the shape describes the layout of the thing on which it is set.
162 // Imemo fields have the same layout as robject, therefore the layout
163 // should reflect that fact.
164 shape_id = rb_shape_transition_robject(shape_id);
165 return rb_newobj(GET_EC(), owner, flags, shape_id, true, size);
166}
167
168VALUE
169rb_imemo_fields_new(VALUE owner, shape_id_t shape_id, bool shareable)
170{
171 size_t capa = RSHAPE(shape_id)->capacity;
172 size_t embedded_size = offsetof(struct rb_fields, as.embed) + capa * sizeof(VALUE);
173
174 VALUE fields = imemo_fields_new(owner, shape_id, embedded_size, shareable);
175 RUBY_ASSERT(IMEMO_TYPE_P(fields, imemo_fields));
176 RUBY_ASSERT(rb_shape_embedded_capacity(RBASIC_SHAPE_ID(fields)) >= capa);
177
178 return fields;
179}
180
181VALUE
182rb_imemo_fields_new_complex_empty(VALUE owner)
183{
184 return imemo_fields_new(owner, ROOT_SHAPE_ID, sizeof(struct rb_fields), false);
185}
186
187VALUE
188rb_imemo_fields_new_complex(VALUE owner, shape_id_t shape_id, size_t capa, bool shareable)
189{
190 st_table tbl;
191 st_init_existing_numtable_with_size(&tbl, capa);
192 VALUE fields = imemo_fields_new(owner, shape_id, sizeof(struct rb_fields), shareable);
193 MEMCPY(&IMEMO_OBJ_FIELDS(fields)->as.complex.table, &tbl, st_table, 1);
194 return fields;
195}
196
197static int
198imemo_fields_complex_wb_i(st_data_t key, st_data_t value, st_data_t arg)
199{
200 RB_OBJ_WRITTEN((VALUE)arg, Qundef, (VALUE)value);
201 return ST_CONTINUE;
202}
203
204VALUE
205rb_imemo_fields_clone(VALUE fields_obj)
206{
207 shape_id_t shape_id = RBASIC_SHAPE_ID(fields_obj);
208 VALUE owner = rb_imemo_fields_owner(fields_obj);
209 VALUE clone;
210
211 if (rb_shape_complex_p(shape_id)) {
212 st_table *src_table = rb_imemo_fields_complex_tbl(fields_obj);
213
214 // We start with ROOT_SHAPE_ID so that if GC trigger in `st_replace` it won't try
215 // to mark an uninitialized table.
216 clone = imemo_fields_new(owner, ROOT_SHAPE_ID, sizeof(struct rb_fields), false /* TODO: check */);
217 st_table *dest_table = rb_imemo_fields_complex_tbl(clone);
218#ifdef RUBY_DEBUG
219 dest_table->entries = NULL;
220#endif
221 st_replace(dest_table, src_table);
222 st_foreach(dest_table, imemo_fields_complex_wb_i, (st_data_t)clone);
223 RBASIC_SET_FULL_SHAPE_ID(clone, shape_id);
224 }
225 else {
226 clone = rb_imemo_fields_new(owner, shape_id, false /* TODO: check */);
227 VALUE *fields = rb_imemo_fields_ptr(clone);
228 attr_index_t fields_count = RSHAPE_LEN(shape_id);
229 MEMCPY(fields, rb_imemo_fields_ptr(fields_obj), VALUE, fields_count);
230 for (attr_index_t i = 0; i < fields_count; i++) {
231 RB_OBJ_WRITTEN(clone, Qundef, fields[i]);
232 }
233 }
234
235 return clone;
236}
237
238void
239rb_imemo_fields_clear(VALUE fields_obj)
240{
241 // Invalidate the ec->gen_fields_cache.
242 RBASIC_CLEAR_CLASS(fields_obj);
243}
244
245VALUE
246rb_imemo_subclasses_new(uint32_t capacity)
247{
248 size_t embed_size = offsetof(struct rb_subclasses, as) + capacity * sizeof(VALUE);
249 struct rb_subclasses *subs;
250
251 if (rb_gc_size_allocatable_p(embed_size)) {
252 subs = (struct rb_subclasses *)rb_imemo_new(imemo_subclasses, 0, embed_size, true);
253 subs->count = 0;
254 subs->capacity = capacity;
255 memset(subs->as.embed, 0, capacity * sizeof(VALUE));
256 rb_gc_declare_weak_references((VALUE)subs);
257 }
258 else {
259 subs = (struct rb_subclasses *)rb_imemo_new(imemo_subclasses, 0, sizeof(struct rb_subclasses), true);
260 subs->as.external = NULL;
261 subs->count = 0;
262 subs->capacity = 0;
263 FL_SET_RAW((VALUE)subs, IMEMO_SUBCLASSES_HEAP);
264 rb_gc_declare_weak_references((VALUE)subs);
265 subs->as.external = ZALLOC_N(VALUE, capacity);
266 subs->capacity = capacity;
267 }
268 return (VALUE)subs;
269}
270
271/* =========================================================================
272 * memsize
273 * ========================================================================= */
274
275size_t
276rb_imemo_memsize(VALUE obj)
277{
278 size_t size = 0;
279 switch (imemo_type(obj)) {
280 case imemo_callcache:
281 break;
282 case imemo_callinfo:
283 break;
284 case imemo_constcache:
285 break;
286 case imemo_cref:
287 break;
288 case imemo_env:
289 size += ((rb_env_t *)obj)->env_size * sizeof(VALUE);
290
291 break;
292 case imemo_ifunc:
293 break;
294 case imemo_iseq:
295 size += rb_iseq_memsize((rb_iseq_t *)obj);
296
297 break;
298 case imemo_memo:
299 break;
300 case imemo_ment:
301 size += sizeof(struct rb_method_definition_struct);
302
303 break;
304 case imemo_svar:
305 break;
306 case imemo_throw_data:
307 break;
308 case imemo_tmpbuf:
309 size += ((rb_imemo_tmpbuf_t *)obj)->size;
310
311 break;
312 case imemo_cvar_entry:
313 break;
314 case imemo_fields:
315 if (rb_obj_shape_complex_p(obj)) {
316 size += st_memsize(rb_imemo_fields_complex_tbl(obj)) - sizeof(st_table);
317 }
318
319 break;
320 case imemo_subclasses: {
321 if (FL_TEST_RAW(obj, IMEMO_SUBCLASSES_HEAP)) {
322 struct rb_subclasses *subs = (struct rb_subclasses *)obj;
323 size += subs->capacity * sizeof(VALUE);
324 }
325
326 break;
327 }
328 case imemo_cdhash:
329 size += st_memsize(rb_imemo_cdhash_tbl(obj)) - sizeof(st_table);
330
331 break;
332 default:
333 rb_bug("unreachable");
334 }
335
336 return size;
337}
338
339/* =========================================================================
340 * mark
341 * ========================================================================= */
342
343static void
344mark_and_move_method_entry(rb_method_entry_t *ment, bool reference_updating)
345{
346 rb_method_definition_t *def = ment->def;
347
348 rb_gc_mark_and_move(&ment->owner);
349 rb_gc_mark_and_move(&ment->defined_class);
350
351 if (def) {
352 rb_gc_mark_and_move(&def->original_module);
353
354 switch (def->type) {
355 case VM_METHOD_TYPE_ISEQ:
356 if (def->body.iseq.iseqptr) {
357 rb_gc_mark_and_move_ptr(&def->body.iseq.iseqptr);
358 }
359 rb_gc_mark_and_move_ptr(&def->body.iseq.cref);
360
361 if (!reference_updating) {
362 if (def->iseq_overload && ment->defined_class) {
363 // it can be a key of "overloaded_cme" table
364 // so it should be pinned.
365 rb_gc_mark((VALUE)ment);
366 }
367 }
368 break;
369 case VM_METHOD_TYPE_ATTRSET:
370 case VM_METHOD_TYPE_IVAR:
371 rb_gc_mark_and_move(&def->body.attr.location);
372 break;
373 case VM_METHOD_TYPE_BMETHOD:
374 rb_gc_mark_and_move(&def->body.bmethod.proc);
375 break;
376 case VM_METHOD_TYPE_ALIAS:
377 rb_gc_mark_and_move_ptr(&def->body.alias.original_me);
378 return;
379 case VM_METHOD_TYPE_REFINED:
380 rb_gc_mark_and_move_ptr(&def->body.refined.orig_me);
381 break;
382 case VM_METHOD_TYPE_CFUNC:
383 case VM_METHOD_TYPE_ZSUPER:
384 case VM_METHOD_TYPE_MISSING:
385 case VM_METHOD_TYPE_OPTIMIZED:
386 case VM_METHOD_TYPE_UNDEF:
387 case VM_METHOD_TYPE_NOTIMPLEMENTED:
388 break;
389 }
390 }
391}
392
393void
394rb_imemo_mark_and_move(VALUE obj, bool reference_updating)
395{
396 switch (imemo_type(obj)) {
397 case imemo_callcache: {
398 /* cc is callcache.
399 *
400 * cc->klass (klass) should not be marked because if the klass is
401 * free'ed, the cc->klass will be cleared by `vm_cc_invalidate()`.
402 *
403 * For "normal" CCs cc->cme (cme) should not be marked because the cc is
404 * invalidated through the klass when the cme is free'd.
405 * - klass marks cme if klass uses cme.
406 * - caller class's ccs->cme marks cc->cme.
407 * - if cc is invalidated (klass doesn't refer the cc), cc is
408 * invalidated by `vm_cc_invalidate()` after which cc->cme must not
409 * be accessed.
410 * - With multi-Ractors, cme will be collected with global GC
411 * so that it is safe if GC is not interleaving while accessing
412 * cc and cme.
413 *
414 * However cc_type_super and cc_type_refinement are not chained
415 * from ccs so cc->cme should be marked as long as the cc is valid;
416 * the cme might be reachable only through cc in these cases.
417 */
418 struct rb_callcache *cc = (struct rb_callcache *)obj;
419 if (UNDEF_P(cc->klass)) {
420 /* If it's invalidated, we must not mark anything.
421 * All fields should are considered invalid
422 */
423 }
424 else if (reference_updating) {
425 *((VALUE *)&cc->klass) = rb_gc_location(cc->klass);
426 *((struct rb_callable_method_entry_struct **)&cc->cme_) =
427 (struct rb_callable_method_entry_struct *)rb_gc_location((VALUE)cc->cme_);
428
429 RUBY_ASSERT(RB_TYPE_P(cc->klass, T_CLASS) || RB_TYPE_P(cc->klass, T_ICLASS));
430 RUBY_ASSERT(IMEMO_TYPE_P((VALUE)cc->cme_, imemo_ment));
431 }
432 else {
433 RUBY_ASSERT(RB_TYPE_P(cc->klass, T_CLASS) || RB_TYPE_P(cc->klass, T_ICLASS));
434 RUBY_ASSERT(IMEMO_TYPE_P((VALUE)cc->cme_, imemo_ment));
435
436 if ((vm_cc_super_p(cc) || vm_cc_refinement_p(cc))) {
437 rb_gc_mark_movable((VALUE)cc->cme_);
438 }
439 }
440
441 break;
442 }
443 case imemo_callinfo:
444 break;
445 case imemo_constcache: {
447
448 rb_gc_mark_and_move(&ice->value);
449
450 break;
451 }
452 case imemo_cref: {
453 rb_cref_t *cref = (rb_cref_t *)obj;
454
455 if (!rb_gc_checking_shareable()) {
456 // cref->klass_or_self can be unshareable, but no way to access it from other ractors
457 rb_gc_mark_and_move(&cref->klass_or_self);
458 }
459
460 rb_gc_mark_and_move_ptr(&cref->next);
461
462 // TODO: Ractor and refeinements are not resolved yet
463 if (!rb_gc_checking_shareable()) {
464 rb_gc_mark_and_move(&cref->refinements);
465 }
466
467 break;
468 }
469 case imemo_env: {
470 rb_env_t *env = (rb_env_t *)obj;
471
472 if (LIKELY(env->ep)) {
473 // just after newobj() can be NULL here.
474 RUBY_ASSERT(rb_gc_location(env->ep[VM_ENV_DATA_INDEX_ENV]) == rb_gc_location(obj));
475 RUBY_ASSERT(reference_updating || VM_ENV_ESCAPED_P(env->ep));
476
477 for (unsigned int i = 0; i < env->env_size; i++) {
478 rb_gc_mark_and_move((VALUE *)&env->env[i]);
479 }
480
481 rb_gc_mark_and_move_ptr(&env->iseq);
482
483 if (VM_ENV_LOCAL_P(env->ep) && VM_ENV_BOXED_P(env->ep)) {
484 const rb_box_t *box = VM_ENV_BOX(env->ep);
485 if (BOX_USER_P(box)) {
486 rb_gc_mark_and_move((VALUE *)&box->box_object);
487 }
488 }
489
490 if (reference_updating) {
491 ((VALUE *)env->ep)[VM_ENV_DATA_INDEX_ENV] = rb_gc_location(env->ep[VM_ENV_DATA_INDEX_ENV]);
492 }
493 else {
494 if (!VM_ENV_FLAGS(env->ep, VM_ENV_FLAG_WB_REQUIRED)) {
495 VM_ENV_FLAGS_SET(env->ep, VM_ENV_FLAG_WB_REQUIRED);
496 }
497 rb_gc_mark_movable( (VALUE)rb_vm_env_prev_env(env));
498 }
499 }
500
501 break;
502 }
503 case imemo_ifunc: {
504 struct vm_ifunc *ifunc = (struct vm_ifunc *)obj;
505
506 if (!reference_updating) {
507 rb_gc_mark_maybe((VALUE)ifunc->data);
508 }
509
510 break;
511 }
512 case imemo_iseq:
513 rb_iseq_mark_and_move((rb_iseq_t *)obj, reference_updating);
514 break;
515 case imemo_memo: {
516 struct MEMO *memo = (struct MEMO *)obj;
517
518 rb_gc_mark_and_move((VALUE *)&memo->v1);
519 rb_gc_mark_and_move((VALUE *)&memo->v2);
520 if (FL_TEST_RAW(obj, MEMO_U3_IS_VALUE)) {
521 rb_gc_mark_and_move((VALUE *)&memo->u3.value);
522 }
523
524 break;
525 }
526 case imemo_ment:
527 mark_and_move_method_entry((rb_method_entry_t *)obj, reference_updating);
528 break;
529 case imemo_svar: {
530 struct vm_svar *svar = (struct vm_svar *)obj;
531
532 rb_gc_mark_and_move((VALUE *)&svar->cref_or_me);
533 rb_gc_mark_and_move((VALUE *)&svar->lastline);
534 rb_gc_mark_and_move((VALUE *)&svar->backref);
535 rb_gc_mark_and_move((VALUE *)&svar->others);
536
537 break;
538 }
539 case imemo_throw_data: {
540 struct vm_throw_data *throw_data = (struct vm_throw_data *)obj;
541
542 rb_gc_mark_and_move((VALUE *)&throw_data->throw_obj);
543
544 break;
545 }
546 case imemo_tmpbuf: {
547 const rb_imemo_tmpbuf_t *m = (const rb_imemo_tmpbuf_t *)obj;
548
549 if (m->marked && !reference_updating) {
550 rb_gc_mark_locations(m->ptr, m->ptr + (m->size / sizeof(VALUE)));
551 }
552
553 break;
554 }
555 case imemo_cvar_entry: {
556 struct rb_cvar_class_tbl_entry *ent = (struct rb_cvar_class_tbl_entry *)obj;
557 rb_gc_mark_and_move(&ent->class_value);
558 rb_gc_mark_and_move((VALUE *)&ent->cref);
559 break;
560 }
561 case imemo_subclasses: {
562 if (reference_updating) {
563 struct rb_subclasses *subs = (struct rb_subclasses *)obj;
564 VALUE *entries = rb_imemo_subclasses_entries(obj);
565 for (uint32_t i = 0; i < subs->count; i++) {
566 if (entries[i]) {
567 entries[i] = rb_gc_location(entries[i]);
568 }
569 }
570 }
571 break;
572 }
573 case imemo_fields: {
574 rb_gc_mark_and_move((VALUE *)&RBASIC(obj)->klass);
575
576 /* A shareable imemo_fields (a class/module's fields) can reference unshareable values
577 * too. The write barrier records those as shrefs, so the shareable constraint check
578 * walks here. */
579 if (rb_obj_shape_complex_p(obj)) {
580 st_table *tbl = rb_imemo_fields_complex_tbl(obj);
581 if (reference_updating) {
582 rb_gc_ref_update_table_values_only(tbl);
583 }
584 else {
585 rb_mark_tbl_no_pin(tbl);
586 }
587 }
588 else {
589 VALUE *fields = rb_imemo_fields_ptr(obj);
590 attr_index_t len = RSHAPE_LEN(RBASIC_SHAPE_ID(obj));
591 for (attr_index_t i = 0; i < len; i++) {
592 rb_gc_mark_and_move(&fields[i]);
593 }
594 }
595 break;
596 }
597 case imemo_cdhash: {
598 st_table *tbl = rb_imemo_cdhash_tbl(obj);
599 if (reference_updating) {
600 rb_gc_update_set_refs(tbl);
601 }
602 else {
603 rb_gc_mark_set_no_pin(tbl);
604 }
605 break;
606 }
607 default:
608 rb_bug("unreachable");
609 }
610}
611
612/* =========================================================================
613 * free
614 * ========================================================================= */
615
616static enum rb_id_table_iterator_result
617free_const_entry_i(VALUE value, void *data)
618{
619 rb_const_entry_t *ce = (rb_const_entry_t *)value;
620 SIZED_FREE(ce);
621 return ID_TABLE_CONTINUE;
622}
623
624void
625rb_free_const_table(struct rb_id_table *tbl)
626{
627 rb_id_table_foreach_values(tbl, free_const_entry_i, 0);
628 rb_id_table_free(tbl);
629}
630
631static inline void
632imemo_fields_free(struct rb_fields *fields)
633{
634 if (rb_obj_shape_complex_p((VALUE)fields)) {
635 st_free_embedded_table(&fields->as.complex.table);
636 }
637}
638
639void
640rb_imemo_free(VALUE obj)
641{
642 switch (imemo_type(obj)) {
643 case imemo_callcache:
644 RB_DEBUG_COUNTER_INC(obj_imemo_callcache);
645
646 break;
647 case imemo_callinfo:{
648 const struct rb_callinfo *ci = ((const struct rb_callinfo *)obj);
649
650 rb_callinfo_kwarg_release((struct rb_callinfo_kwarg *)ci->kwarg);
651 RB_DEBUG_COUNTER_INC(obj_imemo_callinfo);
652
653 break;
654 }
655 case imemo_constcache:
656 RB_DEBUG_COUNTER_INC(obj_imemo_constcache);
657
658 break;
659 case imemo_cref:
660 RB_DEBUG_COUNTER_INC(obj_imemo_cref);
661
662 break;
663 case imemo_env: {
664 rb_env_t *env = (rb_env_t *)obj;
665
666 RUBY_ASSERT(VM_ENV_ESCAPED_P(env->ep));
667 SIZED_FREE_N(env->env, env->env_size);
668 RB_DEBUG_COUNTER_INC(obj_imemo_env);
669
670 break;
671 }
672 case imemo_ifunc:
673 RB_DEBUG_COUNTER_INC(obj_imemo_ifunc);
674 break;
675 case imemo_iseq:
676 rb_iseq_free((rb_iseq_t *)obj);
677 RB_DEBUG_COUNTER_INC(obj_imemo_iseq);
678
679 break;
680 case imemo_memo:
681 RB_DEBUG_COUNTER_INC(obj_imemo_memo);
682
683 break;
684 case imemo_ment:
685 rb_free_method_entry((rb_method_entry_t *)obj);
686 RB_DEBUG_COUNTER_INC(obj_imemo_ment);
687
688 break;
689 case imemo_svar:
690 RB_DEBUG_COUNTER_INC(obj_imemo_svar);
691
692 break;
693 case imemo_throw_data:
694 RB_DEBUG_COUNTER_INC(obj_imemo_throw_data);
695
696 break;
697 case imemo_tmpbuf:
698 ruby_xfree_sized(((rb_imemo_tmpbuf_t *)obj)->ptr, ((rb_imemo_tmpbuf_t *)obj)->size);
699 RB_DEBUG_COUNTER_INC(obj_imemo_tmpbuf);
700
701 break;
702 case imemo_cvar_entry:
703 RB_DEBUG_COUNTER_INC(obj_imemo_cvar_entry);
704
705 break;
706 case imemo_fields:
707 imemo_fields_free(IMEMO_OBJ_FIELDS(obj));
708 RB_DEBUG_COUNTER_INC(obj_imemo_fields);
709
710 break;
711 case imemo_subclasses: {
712 if (FL_TEST_RAW(obj, IMEMO_SUBCLASSES_HEAP)) {
713 struct rb_subclasses *subs = (struct rb_subclasses *)obj;
714 SIZED_FREE_N(subs->as.external, subs->capacity);
715 }
716 RB_DEBUG_COUNTER_INC(obj_imemo_subclasses);
717 break;
718 }
719 case imemo_cdhash:
720 st_free_embedded_table(rb_imemo_cdhash_tbl(obj));
721 RB_DEBUG_COUNTER_INC(obj_imemo_cdhash);
722
723 break;
724 default:
725 rb_bug("unreachable");
726 }
727}
#define RUBY_ASSERT(...)
Asserts that the given expression is truthy if and only if RUBY_DEBUG is truthy.
Definition assert.h:219
#define Qundef
Old name of RUBY_Qundef.
#define T_IMEMO
Old name of RUBY_T_IMEMO.
Definition value_type.h:67
#define FL_SHAREABLE
Old name of RUBY_FL_SHAREABLE.
Definition fl_type.h:62
#define ZALLOC_N
Old name of RB_ZALLOC_N.
Definition memory.h:401
#define T_ICLASS
Old name of RUBY_T_ICLASS.
Definition value_type.h:66
#define FL_TEST_RAW
Old name of RB_FL_TEST_RAW.
Definition fl_type.h:128
#define T_CLASS
Old name of RUBY_T_CLASS.
Definition value_type.h:58
#define FL_USHIFT
Old name of RUBY_FL_USHIFT.
Definition fl_type.h:67
#define FL_SET_RAW
Old name of RB_FL_SET_RAW.
Definition fl_type.h:126
#define RB_OBJ_WRITTEN(old, oldv, young)
Identical to RB_OBJ_WRITE(), except it doesn't write any values, but only a WB declaration.
Definition gc.h:468
int capa
Designed capacity of the buffer.
Definition io.h:11
int len
Length of the buffer.
Definition io.h:8
#define MEMCPY(p1, p2, type, n)
Handy macro to call memcpy.
Definition memory.h:372
VALUE type(ANYARGS)
ANYARGS-ed function type.
#define RBASIC(obj)
Convenient casting macro.
Definition rbasic.h:40
MEMO.
Definition imemo.h:116
Definition vm_core.h:261
Internal header for Ruby Box.
Definition box.h:14
Definition method.h:63
Definition constant.h:33
CREF (Class REFerence)
Definition method.h:45
Internal header for Class.
Definition class.h:30
Definition method.h:55
rb_cref_t * cref
class reference, should be marked
Definition method.h:144
const rb_iseq_t * iseqptr
iseq pointer, should be separated from iseqval
Definition method.h:143
Definition st.h:79
IFUNC (Internal FUNCtion)
Definition imemo.h:87
SVAR (Special VARiable)
Definition imemo.h:52
const VALUE cref_or_me
class reference or rb_method_entry_t
Definition imemo.h:54
THROW_DATA.
Definition imemo.h:61
uintptr_t ID
Type that represents a Ruby identifier such as a variable name.
Definition value.h:52
uintptr_t VALUE
Type that represents a Ruby object.
Definition value.h:40
static bool RB_TYPE_P(VALUE obj, enum ruby_value_type t)
Queries if the given object is of given type.
Definition value_type.h:376