Ruby 4.1.0dev (2026-09-27 revision f6ff9e7d02e46360f8930b280a3dd921cccbda29)
imemo.c (f6ff9e7d02e46360f8930b280a3dd921cccbda29)
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#if 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 rb_gc_update_moved((VALUE *)&cc->klass);
426 rb_gc_update_moved_ptr((struct rb_callable_method_entry_struct **)&cc->cme_);
427
428 RUBY_ASSERT(RB_TYPE_P(cc->klass, T_CLASS) || RB_TYPE_P(cc->klass, T_ICLASS));
429 RUBY_ASSERT(IMEMO_TYPE_P((VALUE)cc->cme_, imemo_ment));
430 }
431 else {
432 RUBY_ASSERT(RB_TYPE_P(cc->klass, T_CLASS) || RB_TYPE_P(cc->klass, T_ICLASS));
433 RUBY_ASSERT(IMEMO_TYPE_P((VALUE)cc->cme_, imemo_ment));
434
435 if ((vm_cc_super_p(cc) || vm_cc_refinement_p(cc))) {
436 rb_gc_mark_movable((VALUE)cc->cme_);
437 }
438 }
439
440 break;
441 }
442 case imemo_callinfo:
443 break;
444 case imemo_constcache: {
446
447 rb_gc_mark_and_move(&ice->value);
448
449 break;
450 }
451 case imemo_cref: {
452 rb_cref_t *cref = (rb_cref_t *)obj;
453
454 if (!rb_gc_checking_shareable()) {
455 // cref->klass_or_self can be unshareable, but no way to access it from other ractors
456 rb_gc_mark_and_move(&cref->klass_or_self);
457 }
458
459 rb_gc_mark_and_move_ptr(&cref->next);
460
461 // TODO: Ractor and refeinements are not resolved yet
462 if (!rb_gc_checking_shareable()) {
463 rb_gc_mark_and_move(&cref->refinements);
464 }
465
466 break;
467 }
468 case imemo_env: {
469 rb_env_t *env = (rb_env_t *)obj;
470
471 if (LIKELY(env->ep)) {
472 // just after newobj() can be NULL here.
473 RUBY_ASSERT(rb_gc_location(env->ep[VM_ENV_DATA_INDEX_ENV]) == rb_gc_location(obj));
474 RUBY_ASSERT(reference_updating || VM_ENV_ESCAPED_P(env->ep));
475
476 for (unsigned int i = 0; i < env->env_size; i++) {
477 rb_gc_mark_and_move((VALUE *)&env->env[i]);
478 }
479
480 rb_gc_mark_and_move_ptr(&env->iseq);
481
482 if (VM_ENV_LOCAL_P(env->ep) && VM_ENV_BOXED_P(env->ep)) {
483 const rb_box_t *box = VM_ENV_BOX(env->ep);
484 if (BOX_USER_P(box)) {
485 rb_gc_mark_and_move((VALUE *)&box->box_object);
486 }
487 }
488
489 if (reference_updating) {
490 rb_gc_update_moved(&((VALUE *)env->ep)[VM_ENV_DATA_INDEX_ENV]);
491 }
492 else {
493 if (!VM_ENV_FLAGS(env->ep, VM_ENV_FLAG_WB_REQUIRED)) {
494 VM_ENV_FLAGS_SET(env->ep, VM_ENV_FLAG_WB_REQUIRED);
495 }
496 rb_gc_mark_movable( (VALUE)rb_vm_env_prev_env(env));
497 }
498 }
499
500 break;
501 }
502 case imemo_ifunc: {
503 struct vm_ifunc *ifunc = (struct vm_ifunc *)obj;
504
505 if (!reference_updating) {
506 rb_gc_mark_maybe((VALUE)ifunc->data);
507 }
508
509 break;
510 }
511 case imemo_iseq:
512 rb_iseq_mark_and_move((rb_iseq_t *)obj, reference_updating);
513 break;
514 case imemo_memo: {
515 struct MEMO *memo = (struct MEMO *)obj;
516
517 rb_gc_mark_and_move((VALUE *)&memo->v1);
518 rb_gc_mark_and_move((VALUE *)&memo->v2);
519 if (FL_TEST_RAW(obj, MEMO_U3_IS_VALUE)) {
520 rb_gc_mark_and_move((VALUE *)&memo->u3.value);
521 }
522
523 break;
524 }
525 case imemo_ment:
526 mark_and_move_method_entry((rb_method_entry_t *)obj, reference_updating);
527 break;
528 case imemo_svar: {
529 struct vm_svar *svar = (struct vm_svar *)obj;
530
531 rb_gc_mark_and_move((VALUE *)&svar->cref_or_me);
532 rb_gc_mark_and_move((VALUE *)&svar->lastline);
533 rb_gc_mark_and_move((VALUE *)&svar->backref);
534 rb_gc_mark_and_move((VALUE *)&svar->others);
535
536 break;
537 }
538 case imemo_throw_data: {
539 struct vm_throw_data *throw_data = (struct vm_throw_data *)obj;
540
541 rb_gc_mark_and_move((VALUE *)&throw_data->throw_obj);
542
543 break;
544 }
545 case imemo_tmpbuf: {
546 const rb_imemo_tmpbuf_t *m = (const rb_imemo_tmpbuf_t *)obj;
547
548 if (m->marked && !reference_updating) {
549 rb_gc_mark_locations(m->ptr, m->ptr + (m->size / sizeof(VALUE)));
550 }
551
552 break;
553 }
554 case imemo_cvar_entry: {
555 struct rb_cvar_class_tbl_entry *ent = (struct rb_cvar_class_tbl_entry *)obj;
556 rb_gc_mark_and_move(&ent->class_value);
557 rb_gc_mark_and_move((VALUE *)&ent->cref);
558 break;
559 }
560 case imemo_subclasses: {
561 if (reference_updating) {
562 struct rb_subclasses *subs = (struct rb_subclasses *)obj;
563 VALUE *entries = rb_imemo_subclasses_entries(obj);
564 for (uint32_t i = 0; i < subs->count; i++) {
565 if (entries[i]) {
566 rb_gc_update_moved(&entries[i]);
567 }
568 }
569 }
570 break;
571 }
572 case imemo_fields: {
573 rb_gc_mark_and_move((VALUE *)&RBASIC(obj)->klass);
574
575 /* A shareable imemo_fields (a class/module's fields) can reference unshareable values
576 * too. The write barrier records those as shrefs, so the shareable constraint check
577 * walks here. */
578 if (rb_obj_shape_complex_p(obj)) {
579 st_table *tbl = rb_imemo_fields_complex_tbl(obj);
580 if (reference_updating) {
581 rb_gc_ref_update_table_values_only(tbl);
582 }
583 else {
584 rb_mark_tbl_no_pin(tbl);
585 }
586 }
587 else {
588 VALUE *fields = rb_imemo_fields_ptr(obj);
589 attr_index_t len = RSHAPE_LEN(RBASIC_SHAPE_ID(obj));
590 for (attr_index_t i = 0; i < len; i++) {
591 rb_gc_mark_and_move(&fields[i]);
592 }
593 }
594 break;
595 }
596 case imemo_cdhash: {
597 st_table *tbl = rb_imemo_cdhash_tbl(obj);
598 if (reference_updating) {
599 rb_gc_update_set_refs(tbl);
600 }
601 else {
602 rb_gc_mark_set_no_pin(tbl);
603 }
604 break;
605 }
606 default:
607 rb_bug("unreachable");
608 }
609}
610
611/* =========================================================================
612 * free
613 * ========================================================================= */
614
615static enum rb_id_table_iterator_result
616free_const_entry_i(VALUE value, void *data)
617{
618 rb_const_entry_t *ce = (rb_const_entry_t *)value;
619 SIZED_FREE(ce);
620 return ID_TABLE_CONTINUE;
621}
622
623void
624rb_free_const_table(struct rb_id_table *tbl)
625{
626 rb_id_table_foreach_values(tbl, free_const_entry_i, 0);
627 rb_id_table_free(tbl);
628}
629
630static inline void
631imemo_fields_free(struct rb_fields *fields)
632{
633 if (rb_obj_shape_complex_p((VALUE)fields)) {
634 st_free_embedded_table(&fields->as.complex.table);
635 }
636}
637
638void
639rb_imemo_free(VALUE obj)
640{
641 switch (imemo_type(obj)) {
642 case imemo_callcache:
643 RB_DEBUG_COUNTER_INC(obj_imemo_callcache);
644
645 break;
646 case imemo_callinfo:{
647 const struct rb_callinfo *ci = ((const struct rb_callinfo *)obj);
648
649 rb_callinfo_kwarg_release((struct rb_callinfo_kwarg *)ci->kwarg);
650 RB_DEBUG_COUNTER_INC(obj_imemo_callinfo);
651
652 break;
653 }
654 case imemo_constcache:
655 RB_DEBUG_COUNTER_INC(obj_imemo_constcache);
656
657 break;
658 case imemo_cref:
659 RB_DEBUG_COUNTER_INC(obj_imemo_cref);
660
661 break;
662 case imemo_env: {
663 rb_env_t *env = (rb_env_t *)obj;
664
665 RUBY_ASSERT(VM_ENV_ESCAPED_P(env->ep));
666 SIZED_FREE_N(env->env, env->env_size);
667 RB_DEBUG_COUNTER_INC(obj_imemo_env);
668
669 break;
670 }
671 case imemo_ifunc:
672 RB_DEBUG_COUNTER_INC(obj_imemo_ifunc);
673 break;
674 case imemo_iseq:
675 rb_iseq_free((rb_iseq_t *)obj);
676 RB_DEBUG_COUNTER_INC(obj_imemo_iseq);
677
678 break;
679 case imemo_memo:
680 RB_DEBUG_COUNTER_INC(obj_imemo_memo);
681
682 break;
683 case imemo_ment:
684 rb_free_method_entry((rb_method_entry_t *)obj);
685 RB_DEBUG_COUNTER_INC(obj_imemo_ment);
686
687 break;
688 case imemo_svar:
689 RB_DEBUG_COUNTER_INC(obj_imemo_svar);
690
691 break;
692 case imemo_throw_data:
693 RB_DEBUG_COUNTER_INC(obj_imemo_throw_data);
694
695 break;
696 case imemo_tmpbuf:
697 ruby_xfree_sized(((rb_imemo_tmpbuf_t *)obj)->ptr, ((rb_imemo_tmpbuf_t *)obj)->size);
698 RB_DEBUG_COUNTER_INC(obj_imemo_tmpbuf);
699
700 break;
701 case imemo_cvar_entry:
702 RB_DEBUG_COUNTER_INC(obj_imemo_cvar_entry);
703
704 break;
705 case imemo_fields:
706 imemo_fields_free(IMEMO_OBJ_FIELDS(obj));
707 RB_DEBUG_COUNTER_INC(obj_imemo_fields);
708
709 break;
710 case imemo_subclasses: {
711 if (FL_TEST_RAW(obj, IMEMO_SUBCLASSES_HEAP)) {
712 struct rb_subclasses *subs = (struct rb_subclasses *)obj;
713 SIZED_FREE_N(subs->as.external, subs->capacity);
714 }
715 RB_DEBUG_COUNTER_INC(obj_imemo_subclasses);
716 break;
717 }
718 case imemo_cdhash:
719 st_free_embedded_table(rb_imemo_cdhash_tbl(obj));
720 RB_DEBUG_COUNTER_INC(obj_imemo_cdhash);
721
722 break;
723 default:
724 rb_bug("unreachable");
725 }
726}
#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:504
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:260
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:31
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