Ruby 4.0.5p0 (2026-05-20 revision 64336ffd0ee9e1f4c05891695a3d7b49cb709721)
imemo.c
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
14const char *
15rb_imemo_name(enum imemo_type type)
16{
17 // put no default case to get a warning if an imemo type is missing
18 switch (type) {
19#define IMEMO_NAME(x) case imemo_##x: return #x;
20 IMEMO_NAME(callcache);
21 IMEMO_NAME(callinfo);
22 IMEMO_NAME(constcache);
23 IMEMO_NAME(cref);
24 IMEMO_NAME(env);
25 IMEMO_NAME(ifunc);
26 IMEMO_NAME(iseq);
27 IMEMO_NAME(memo);
28 IMEMO_NAME(ment);
29 IMEMO_NAME(svar);
30 IMEMO_NAME(throw_data);
31 IMEMO_NAME(tmpbuf);
32 IMEMO_NAME(cvar_entry);
33 IMEMO_NAME(fields);
34#undef IMEMO_NAME
35 }
36 rb_bug("unreachable");
37}
38
39/* =========================================================================
40 * allocation
41 * ========================================================================= */
42
44rb_imemo_new(enum imemo_type type, VALUE v0, size_t size, bool is_shareable)
45{
46 VALUE flags = T_IMEMO | FL_WB_PROTECTED | (type << FL_USHIFT) | (is_shareable ? FL_SHAREABLE : 0);
47 NEWOBJ_OF(obj, void, v0, flags, size, 0);
48
49 return (VALUE)obj;
50}
51
53rb_imemo_tmpbuf_new(void)
54{
55 VALUE flags = T_IMEMO | (imemo_tmpbuf << FL_USHIFT);
56 NEWOBJ_OF(obj, rb_imemo_tmpbuf_t, 0, flags, sizeof(rb_imemo_tmpbuf_t), NULL);
57
58 obj->ptr = NULL;
59 obj->cnt = 0;
60
61 return (VALUE)obj;
62}
63
64void *
65rb_alloc_tmp_buffer_with_count(volatile VALUE *store, size_t size, size_t cnt)
66{
67 /* Keep the order; allocate an empty imemo first then xmalloc, to
68 * get rid of potential memory leak */
69 rb_imemo_tmpbuf_t *tmpbuf = (rb_imemo_tmpbuf_t *)rb_imemo_tmpbuf_new();
70 *store = (VALUE)tmpbuf;
71 void *ptr = ruby_xmalloc(size);
72 tmpbuf->ptr = ptr;
73 tmpbuf->cnt = cnt;
74
75 return ptr;
76}
77
78void *
79rb_alloc_tmp_buffer(volatile VALUE *store, long len)
80{
81 long cnt;
82
83 if (len < 0 || (cnt = (long)roomof(len, sizeof(VALUE))) < 0) {
84 rb_raise(rb_eArgError, "negative buffer size (or size too big)");
85 }
86
87 return rb_alloc_tmp_buffer_with_count(store, len, cnt);
88}
89
90void
91rb_free_tmp_buffer(volatile VALUE *store)
92{
93 rb_imemo_tmpbuf_t *s = (rb_imemo_tmpbuf_t*)ATOMIC_VALUE_EXCHANGE(*store, 0);
94 if (s) {
95 void *ptr = ATOMIC_PTR_EXCHANGE(s->ptr, 0);
96 s->cnt = 0;
97 ruby_xfree(ptr);
98 }
99}
100
101static VALUE
102imemo_fields_new(VALUE owner, size_t capa, bool shareable)
103{
104 size_t embedded_size = offsetof(struct rb_fields, as.embed) + capa * sizeof(VALUE);
105 if (rb_gc_size_allocatable_p(embedded_size)) {
106 VALUE fields = rb_imemo_new(imemo_fields, owner, embedded_size, shareable);
107 RUBY_ASSERT(IMEMO_TYPE_P(fields, imemo_fields));
108 return fields;
109 }
110 else {
111 VALUE fields = rb_imemo_new(imemo_fields, owner, sizeof(struct rb_fields), shareable);
112 IMEMO_OBJ_FIELDS(fields)->as.external.ptr = ALLOC_N(VALUE, capa);
113 FL_SET_RAW(fields, OBJ_FIELD_HEAP);
114 return fields;
115 }
116}
117
118VALUE
119rb_imemo_fields_new(VALUE owner, size_t capa, bool shareable)
120{
121 return imemo_fields_new(owner, capa, shareable);
122}
123
124static VALUE
125imemo_fields_new_complex(VALUE owner, size_t capa, bool shareable)
126{
127 VALUE fields = rb_imemo_new(imemo_fields, owner, sizeof(struct rb_fields), shareable);
128 IMEMO_OBJ_FIELDS(fields)->as.complex.table = st_init_numtable_with_size(capa);
129 FL_SET_RAW(fields, OBJ_FIELD_HEAP);
130 return fields;
131}
132
133VALUE
134rb_imemo_fields_new_complex(VALUE owner, size_t capa, bool shareable)
135{
136 return imemo_fields_new_complex(owner, capa, shareable);
137}
138
139static int
140imemo_fields_trigger_wb_i(st_data_t key, st_data_t value, st_data_t arg)
141{
142 VALUE field_obj = (VALUE)arg;
143 RB_OBJ_WRITTEN(field_obj, Qundef, (VALUE)value);
144 return ST_CONTINUE;
145}
146
147static int
148imemo_fields_complex_wb_i(st_data_t key, st_data_t value, st_data_t arg)
149{
150 RB_OBJ_WRITTEN((VALUE)arg, Qundef, (VALUE)value);
151 return ST_CONTINUE;
152}
153
154VALUE
155rb_imemo_fields_new_complex_tbl(VALUE owner, st_table *tbl, bool shareable)
156{
157 VALUE fields = rb_imemo_new(imemo_fields, owner, sizeof(struct rb_fields), shareable);
158 IMEMO_OBJ_FIELDS(fields)->as.complex.table = tbl;
159 FL_SET_RAW(fields, OBJ_FIELD_HEAP);
160 st_foreach(tbl, imemo_fields_trigger_wb_i, (st_data_t)fields);
161 return fields;
162}
163
164VALUE
165rb_imemo_fields_clone(VALUE fields_obj)
166{
167 shape_id_t shape_id = RBASIC_SHAPE_ID(fields_obj);
168 VALUE clone;
169
170 if (rb_shape_too_complex_p(shape_id)) {
171 st_table *src_table = rb_imemo_fields_complex_tbl(fields_obj);
172
173 st_table *dest_table = xcalloc(1, sizeof(st_table));
174 clone = rb_imemo_fields_new_complex_tbl(rb_imemo_fields_owner(fields_obj), dest_table, false /* TODO: check */);
175
176 st_replace(dest_table, src_table);
177 RBASIC_SET_SHAPE_ID(clone, shape_id);
178
179 st_foreach(dest_table, imemo_fields_complex_wb_i, (st_data_t)clone);
180 }
181 else {
182 clone = imemo_fields_new(rb_imemo_fields_owner(fields_obj), RSHAPE_CAPACITY(shape_id), false /* TODO: check */);
183 RBASIC_SET_SHAPE_ID(clone, shape_id);
184 VALUE *fields = rb_imemo_fields_ptr(clone);
185 attr_index_t fields_count = RSHAPE_LEN(shape_id);
186 MEMCPY(fields, rb_imemo_fields_ptr(fields_obj), VALUE, fields_count);
187 for (attr_index_t i = 0; i < fields_count; i++) {
188 RB_OBJ_WRITTEN(clone, Qundef, fields[i]);
189 }
190 }
191
192 return clone;
193}
194
195void
196rb_imemo_fields_clear(VALUE fields_obj)
197{
198 // When replacing an imemo/fields by another one, we must clear
199 // its shape so that gc.c:obj_free_object_id won't be called.
200 if (rb_shape_obj_too_complex_p(fields_obj)) {
201 RBASIC_SET_SHAPE_ID(fields_obj, ROOT_TOO_COMPLEX_SHAPE_ID);
202 }
203 else {
204 RBASIC_SET_SHAPE_ID(fields_obj, ROOT_SHAPE_ID);
205 }
206 // Invalidate the ec->gen_fields_cache.
207 RBASIC_CLEAR_CLASS(fields_obj);
208}
209
210/* =========================================================================
211 * memsize
212 * ========================================================================= */
213
214size_t
215rb_imemo_memsize(VALUE obj)
216{
217 size_t size = 0;
218 switch (imemo_type(obj)) {
219 case imemo_callcache:
220 break;
221 case imemo_callinfo:
222 break;
223 case imemo_constcache:
224 break;
225 case imemo_cref:
226 break;
227 case imemo_env:
228 size += ((rb_env_t *)obj)->env_size * sizeof(VALUE);
229
230 break;
231 case imemo_ifunc:
232 break;
233 case imemo_iseq:
234 size += rb_iseq_memsize((rb_iseq_t *)obj);
235
236 break;
237 case imemo_memo:
238 break;
239 case imemo_ment:
240 size += sizeof(((rb_method_entry_t *)obj)->def);
241
242 break;
243 case imemo_svar:
244 break;
245 case imemo_throw_data:
246 break;
247 case imemo_tmpbuf:
248 size += ((rb_imemo_tmpbuf_t *)obj)->cnt * sizeof(VALUE);
249
250 break;
251 case imemo_cvar_entry:
252 break;
253 case imemo_fields:
254 if (FL_TEST_RAW(obj, OBJ_FIELD_HEAP)) {
255 if (rb_shape_obj_too_complex_p(obj)) {
256 size += st_memsize(IMEMO_OBJ_FIELDS(obj)->as.complex.table);
257 }
258 else {
259 size += RSHAPE_CAPACITY(RBASIC_SHAPE_ID(obj)) * sizeof(VALUE);
260 }
261 }
262 break;
263 default:
264 rb_bug("unreachable");
265 }
266
267 return size;
268}
269
270/* =========================================================================
271 * mark
272 * ========================================================================= */
273
274static bool
275moved_or_living_object_strictly_p(VALUE obj)
276{
277 return !SPECIAL_CONST_P(obj) && (!rb_objspace_garbage_object_p(obj) || BUILTIN_TYPE(obj) == T_MOVED);
278}
279
280static void
281mark_and_move_method_entry(rb_method_entry_t *ment, bool reference_updating)
282{
283 rb_method_definition_t *def = ment->def;
284
285 rb_gc_mark_and_move(&ment->owner);
286 rb_gc_mark_and_move(&ment->defined_class);
287
288 if (def) {
289 switch (def->type) {
290 case VM_METHOD_TYPE_ISEQ:
291 if (def->body.iseq.iseqptr) {
292 rb_gc_mark_and_move_ptr(&def->body.iseq.iseqptr);
293 }
294 rb_gc_mark_and_move_ptr(&def->body.iseq.cref);
295
296 if (!reference_updating) {
297 if (def->iseq_overload && ment->defined_class) {
298 // it can be a key of "overloaded_cme" table
299 // so it should be pinned.
300 rb_gc_mark((VALUE)ment);
301 }
302 }
303 break;
304 case VM_METHOD_TYPE_ATTRSET:
305 case VM_METHOD_TYPE_IVAR:
306 rb_gc_mark_and_move(&def->body.attr.location);
307 break;
308 case VM_METHOD_TYPE_BMETHOD:
309 if (!rb_gc_checking_shareable()) {
310 rb_gc_mark_and_move(&def->body.bmethod.proc);
311 }
312 break;
313 case VM_METHOD_TYPE_ALIAS:
314 rb_gc_mark_and_move_ptr(&def->body.alias.original_me);
315 return;
316 case VM_METHOD_TYPE_REFINED:
317 rb_gc_mark_and_move_ptr(&def->body.refined.orig_me);
318 break;
319 case VM_METHOD_TYPE_CFUNC:
320 case VM_METHOD_TYPE_ZSUPER:
321 case VM_METHOD_TYPE_MISSING:
322 case VM_METHOD_TYPE_OPTIMIZED:
323 case VM_METHOD_TYPE_UNDEF:
324 case VM_METHOD_TYPE_NOTIMPLEMENTED:
325 break;
326 }
327 }
328}
329
330void
331rb_imemo_mark_and_move(VALUE obj, bool reference_updating)
332{
333 switch (imemo_type(obj)) {
334 case imemo_callcache: {
335 /* cc is callcache.
336 *
337 * cc->klass (klass) should not be marked because if the klass is
338 * free'ed, the cc->klass will be cleared by `vm_cc_invalidate()`.
339 *
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.
342 * - klass marks cme if klass uses cme.
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
348 * so that it is safe if GC is not interleaving while accessing
349 * cc and cme.
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.
354 */
355 struct rb_callcache *cc = (struct rb_callcache *)obj;
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) {
362 if (moved_or_living_object_strictly_p((VALUE)cc->cme_)) {
363 *((VALUE *)&cc->klass) = rb_gc_location(cc->klass);
364 *((struct rb_callable_method_entry_struct **)&cc->cme_) =
365 (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));
369 }
370 else {
371 vm_cc_invalidate(cc);
372 }
373 }
374 else {
375 RUBY_ASSERT(RB_TYPE_P(cc->klass, T_CLASS) || RB_TYPE_P(cc->klass, T_ICLASS));
376 RUBY_ASSERT(IMEMO_TYPE_P((VALUE)cc->cme_, imemo_ment));
377
378 rb_gc_mark_weak((VALUE *)&cc->klass);
379 if ((vm_cc_super_p(cc) || vm_cc_refinement_p(cc))) {
380 rb_gc_mark_movable((VALUE)cc->cme_);
381 }
382 }
383
384 break;
385 }
386 case imemo_callinfo:
387 break;
388 case imemo_constcache: {
390
391 if ((ice->flags & IMEMO_CONST_CACHE_SHAREABLE) ||
392 !rb_gc_checking_shareable()) {
393 rb_gc_mark_and_move(&ice->value);
394 }
395
396 break;
397 }
398 case imemo_cref: {
399 rb_cref_t *cref = (rb_cref_t *)obj;
400
401 if (!rb_gc_checking_shareable()) {
402 // cref->klass_or_self can be unshareable, but no way to access it from other ractors
403 rb_gc_mark_and_move(&cref->klass_or_self);
404 }
405
406 rb_gc_mark_and_move_ptr(&cref->next);
407
408 // TODO: Ractor and refeinements are not resolved yet
409 if (!rb_gc_checking_shareable()) {
410 rb_gc_mark_and_move(&cref->refinements);
411 }
412
413 break;
414 }
415 case imemo_env: {
416 rb_env_t *env = (rb_env_t *)obj;
417
418 if (LIKELY(env->ep)) {
419 // just after newobj() can be NULL here.
420 RUBY_ASSERT(rb_gc_location(env->ep[VM_ENV_DATA_INDEX_ENV]) == rb_gc_location(obj));
421 RUBY_ASSERT(reference_updating || VM_ENV_ESCAPED_P(env->ep));
422
423 for (unsigned int i = 0; i < env->env_size; i++) {
424 rb_gc_mark_and_move((VALUE *)&env->env[i]);
425 }
426
427 rb_gc_mark_and_move_ptr(&env->iseq);
428
429 if (VM_ENV_LOCAL_P(env->ep) && VM_ENV_BOXED_P(env->ep)) {
430 const rb_box_t *box = VM_ENV_BOX(env->ep);
431 if (BOX_USER_P(box)) {
432 rb_gc_mark_and_move((VALUE *)&box->box_object);
433 }
434 }
435
436 if (reference_updating) {
437 ((VALUE *)env->ep)[VM_ENV_DATA_INDEX_ENV] = rb_gc_location(env->ep[VM_ENV_DATA_INDEX_ENV]);
438 }
439 else {
440 if (!VM_ENV_FLAGS(env->ep, VM_ENV_FLAG_WB_REQUIRED)) {
441 VM_ENV_FLAGS_SET(env->ep, VM_ENV_FLAG_WB_REQUIRED);
442 }
443 rb_gc_mark_movable( (VALUE)rb_vm_env_prev_env(env));
444 }
445 }
446
447 break;
448 }
449 case imemo_ifunc: {
450 struct vm_ifunc *ifunc = (struct vm_ifunc *)obj;
451
452 if (!reference_updating) {
453 rb_gc_mark_maybe((VALUE)ifunc->data);
454 }
455
456 break;
457 }
458 case imemo_iseq:
459 rb_iseq_mark_and_move((rb_iseq_t *)obj, reference_updating);
460 break;
461 case imemo_memo: {
462 struct MEMO *memo = (struct MEMO *)obj;
463
464 rb_gc_mark_and_move((VALUE *)&memo->v1);
465 rb_gc_mark_and_move((VALUE *)&memo->v2);
466 if (!reference_updating) {
467 rb_gc_mark_maybe(memo->u3.value);
468 }
469
470 break;
471 }
472 case imemo_ment:
473 mark_and_move_method_entry((rb_method_entry_t *)obj, reference_updating);
474 break;
475 case imemo_svar: {
476 struct vm_svar *svar = (struct vm_svar *)obj;
477
478 rb_gc_mark_and_move((VALUE *)&svar->cref_or_me);
479 rb_gc_mark_and_move((VALUE *)&svar->lastline);
480 rb_gc_mark_and_move((VALUE *)&svar->backref);
481 rb_gc_mark_and_move((VALUE *)&svar->others);
482
483 break;
484 }
485 case imemo_throw_data: {
486 struct vm_throw_data *throw_data = (struct vm_throw_data *)obj;
487
488 rb_gc_mark_and_move((VALUE *)&throw_data->throw_obj);
489
490 break;
491 }
492 case imemo_tmpbuf: {
493 const rb_imemo_tmpbuf_t *m = (const rb_imemo_tmpbuf_t *)obj;
494
495 if (!reference_updating) {
496 rb_gc_mark_locations(m->ptr, m->ptr + m->cnt);
497 }
498
499 break;
500 }
501 case imemo_cvar_entry: {
502 struct rb_cvar_class_tbl_entry *ent = (struct rb_cvar_class_tbl_entry *)obj;
503 rb_gc_mark_and_move(&ent->class_value);
504 rb_gc_mark_and_move((VALUE *)&ent->cref);
505 break;
506 }
507 case imemo_fields: {
508 rb_gc_mark_and_move((VALUE *)&RBASIC(obj)->klass);
509
510 if (!rb_gc_checking_shareable()) {
511 // imemo_fields can refer unshareable objects
512 // even if the imemo_fields is shareable.
513
514 if (rb_shape_obj_too_complex_p(obj)) {
515 st_table *tbl = rb_imemo_fields_complex_tbl(obj);
516 if (reference_updating) {
517 rb_gc_ref_update_table_values_only(tbl);
518 }
519 else {
520 rb_mark_tbl_no_pin(tbl);
521 }
522 }
523 else {
524 VALUE *fields = rb_imemo_fields_ptr(obj);
525 attr_index_t len = RSHAPE_LEN(RBASIC_SHAPE_ID(obj));
526 for (attr_index_t i = 0; i < len; i++) {
527 rb_gc_mark_and_move(&fields[i]);
528 }
529 }
530 }
531 break;
532 }
533 default:
534 rb_bug("unreachable");
535 }
536}
537
538/* =========================================================================
539 * free
540 * ========================================================================= */
541
542static enum rb_id_table_iterator_result
543free_const_entry_i(VALUE value, void *data)
544{
545 rb_const_entry_t *ce = (rb_const_entry_t *)value;
546 xfree(ce);
547 return ID_TABLE_CONTINUE;
548}
549
550void
551rb_free_const_table(struct rb_id_table *tbl)
552{
553 rb_id_table_foreach_values(tbl, free_const_entry_i, 0);
554 rb_id_table_free(tbl);
555}
556
557static inline void
558imemo_fields_free(struct rb_fields *fields)
559{
560 if (FL_TEST_RAW((VALUE)fields, OBJ_FIELD_HEAP)) {
561 if (rb_shape_obj_too_complex_p((VALUE)fields)) {
562 st_free_table(fields->as.complex.table);
563 }
564 else {
565 xfree(fields->as.external.ptr);
566 }
567 }
568}
569
570void
571rb_imemo_free(VALUE obj)
572{
573 switch (imemo_type(obj)) {
574 case imemo_callcache:
575 RB_DEBUG_COUNTER_INC(obj_imemo_callcache);
576
577 break;
578 case imemo_callinfo:{
579 const struct rb_callinfo *ci = ((const struct rb_callinfo *)obj);
580
581 if (ci->kwarg) {
582 ((struct rb_callinfo_kwarg *)ci->kwarg)->references--;
583 if (ci->kwarg->references == 0) xfree((void *)ci->kwarg);
584 }
585 RB_DEBUG_COUNTER_INC(obj_imemo_callinfo);
586
587 break;
588 }
589 case imemo_constcache:
590 RB_DEBUG_COUNTER_INC(obj_imemo_constcache);
591
592 break;
593 case imemo_cref:
594 RB_DEBUG_COUNTER_INC(obj_imemo_cref);
595
596 break;
597 case imemo_env: {
598 rb_env_t *env = (rb_env_t *)obj;
599
600 RUBY_ASSERT(VM_ENV_ESCAPED_P(env->ep));
601 xfree((VALUE *)env->env);
602 RB_DEBUG_COUNTER_INC(obj_imemo_env);
603
604 break;
605 }
606 case imemo_ifunc:
607 RB_DEBUG_COUNTER_INC(obj_imemo_ifunc);
608 break;
609 case imemo_iseq:
610 rb_iseq_free((rb_iseq_t *)obj);
611 RB_DEBUG_COUNTER_INC(obj_imemo_iseq);
612
613 break;
614 case imemo_memo:
615 RB_DEBUG_COUNTER_INC(obj_imemo_memo);
616
617 break;
618 case imemo_ment:
619 rb_free_method_entry((rb_method_entry_t *)obj);
620 RB_DEBUG_COUNTER_INC(obj_imemo_ment);
621
622 break;
623 case imemo_svar:
624 RB_DEBUG_COUNTER_INC(obj_imemo_svar);
625
626 break;
627 case imemo_throw_data:
628 RB_DEBUG_COUNTER_INC(obj_imemo_throw_data);
629
630 break;
631 case imemo_tmpbuf:
632 xfree(((rb_imemo_tmpbuf_t *)obj)->ptr);
633 RB_DEBUG_COUNTER_INC(obj_imemo_tmpbuf);
634
635 break;
636 case imemo_cvar_entry:
637 RB_DEBUG_COUNTER_INC(obj_imemo_cvar_entry);
638
639 break;
640 case imemo_fields:
641 imemo_fields_free(IMEMO_OBJ_FIELDS(obj));
642 RB_DEBUG_COUNTER_INC(obj_imemo_fields);
643 break;
644 default:
645 rb_bug("unreachable");
646 }
647}
#define RUBY_ASSERT(...)
Asserts that the given expression is truthy if and only if RUBY_DEBUG is truthy.
Definition assert.h:219
#define xfree
Old name of ruby_xfree.
Definition xmalloc.h:58
#define Qundef
Old name of RUBY_Qundef.
#define T_IMEMO
Old name of RUBY_T_IMEMO.
Definition value_type.h:67
#define SPECIAL_CONST_P
Old name of RB_SPECIAL_CONST_P.
#define FL_SHAREABLE
Old name of RUBY_FL_SHAREABLE.
Definition fl_type.h:63
#define T_ICLASS
Old name of RUBY_T_ICLASS.
Definition value_type.h:66
#define ALLOC_N
Old name of RB_ALLOC_N.
Definition memory.h:399
#define FL_TEST_RAW
Old name of RB_FL_TEST_RAW.
Definition fl_type.h:131
#define FL_WB_PROTECTED
Old name of RUBY_FL_WB_PROTECTED.
Definition fl_type.h:59
#define T_CLASS
Old name of RUBY_T_CLASS.
Definition value_type.h:58
#define BUILTIN_TYPE
Old name of RB_BUILTIN_TYPE.
Definition value_type.h:85
#define T_MOVED
Old name of RUBY_T_MOVED.
Definition value_type.h:71
#define xcalloc
Old name of ruby_xcalloc.
Definition xmalloc.h:55
#define FL_USHIFT
Old name of RUBY_FL_USHIFT.
Definition fl_type.h:68
#define FL_SET_RAW
Old name of RB_FL_SET_RAW.
Definition fl_type.h:129
#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:615
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.
int st_foreach(st_table *q, int_type *w, st_data_t e)
Iteration over the given table.
#define RBASIC(obj)
Convenient casting macro.
Definition rbasic.h:40
MEMO.
Definition imemo.h:105
Definition vm_core.h:261
Definition method.h:63
Definition class.h:37
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
IFUNC (Internal FUNCtion).
Definition imemo.h:86
SVAR (Special VARiable).
Definition imemo.h:50
const VALUE cref_or_me
class reference or rb_method_entry_t
Definition imemo.h:52
THROW_DATA.
Definition imemo.h:59
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