Ruby 4.1.0dev (2026-03-01 revision d68e4be1873e364c5ee24ed112bce4bc86e3a406)
imemo.h
1#ifndef INTERNAL_IMEMO_H /*-*-C-*-vi:se ft=c:*/
2#define INTERNAL_IMEMO_H
11#include "ruby/internal/config.h"
12#include <stddef.h> /* for size_t */
13#include "id_table.h"
14#include "internal/array.h" /* for rb_ary_hidden_new_fill */
15#include "ruby/internal/stdbool.h" /* for bool */
16#include "ruby/ruby.h" /* for rb_block_call_func_t */
17
18#define IMEMO_MASK 0x0f
19
20/* FL_USER0 to FL_USER3 is for type */
21#define IMEMO_FL_USHIFT (FL_USHIFT + 4)
22#define IMEMO_FL_USER0 FL_USER4
23#define IMEMO_FL_USER1 FL_USER5
24#define IMEMO_FL_USER2 FL_USER6
25#define IMEMO_FL_USER3 FL_USER7
26#define IMEMO_FL_USER4 FL_USER8
27#define IMEMO_FL_USER5 FL_USER9
28#define IMEMO_FL_USER6 FL_USER10
29
30enum imemo_type {
31 imemo_env = 0,
32 imemo_cref = 1,
33 imemo_svar = 2,
34 imemo_throw_data = 3,
35 imemo_ifunc = 4,
36 imemo_memo = 5,
37 imemo_ment = 6,
38 imemo_iseq = 7,
39 imemo_tmpbuf = 8,
40 imemo_callinfo = 10,
41 imemo_callcache = 11,
42 imemo_constcache = 12,
43 imemo_fields = 13,
44};
45
46/* CREF (Class REFerence) is defined in method.h */
47
49struct vm_svar {
50 VALUE flags;
52 const VALUE lastline;
53 const VALUE backref;
54 const VALUE others;
55};
56
59 VALUE flags;
60 const VALUE throw_obj;
61 const struct rb_control_frame_struct *catch_frame;
62 int throw_state;
63};
64
65#define THROW_DATA_CONSUMED IMEMO_FL_USER0
66
67/* IFUNC (Internal FUNCtion) */
68
70#if SIZEOF_INT * 2 > SIZEOF_VALUE
71 signed int min: (SIZEOF_VALUE * CHAR_BIT) / 2;
72 signed int max: (SIZEOF_VALUE * CHAR_BIT) / 2;
73#else
74 int min, max;
75#endif
76};
77
84struct vm_ifunc {
85 VALUE flags;
86 VALUE *svar_lep;
88 const void *data;
89 struct vm_ifunc_argc argc;
90};
91#define IFUNC_YIELD_OPTIMIZABLE IMEMO_FL_USER0
92
94 VALUE flags;
95 VALUE *ptr; /* malloc'ed buffer */
96 size_t size; /* buffer size in bytes */
97};
98
103struct MEMO {
104 VALUE flags;
105 const VALUE v1;
106 const VALUE v2;
107 union {
108 long cnt;
109 long state;
110 const VALUE value;
111 void (*func)(void);
112 } u3;
113};
114
115#define IMEMO_NEW(T, type, v0) ((T *)rb_imemo_new((type), (v0), sizeof(T), false))
116#define SHAREABLE_IMEMO_NEW(T, type, v0) ((T *)rb_imemo_new((type), (v0), sizeof(T), true))
117
118/* ment is in method.h */
119
120#define THROW_DATA_P(err) imemo_throw_data_p((VALUE)err)
121#define MEMO_CAST(m) ((struct MEMO *)(m))
122#define MEMO_FOR(type, value) ((type *)RARRAY_PTR(value))
123#define NEW_MEMO_FOR(type, value) \
124 ((value) = rb_ary_hidden_new_fill(type_roomof(type, VALUE)), MEMO_FOR(type, value))
125#define NEW_PARTIAL_MEMO_FOR(type, value, member) \
126 ((value) = rb_ary_hidden_new_fill(type_roomof(type, VALUE)), \
127 rb_ary_set_len((value), offsetof(type, member) / sizeof(VALUE)), \
128 MEMO_FOR(type, value))
129
130#ifndef RUBY_RUBYPARSER_H
132#endif
133VALUE rb_imemo_new(enum imemo_type type, VALUE v0, size_t size, bool is_shareable);
134VALUE rb_imemo_tmpbuf_new(void);
135struct MEMO *rb_imemo_memo_new(VALUE a, VALUE b, VALUE c);
136struct vm_ifunc *rb_vm_ifunc_new(rb_block_call_func_t func, const void *data, int min_argc, int max_argc);
137static inline enum imemo_type imemo_type(VALUE imemo);
138static inline int imemo_type_p(VALUE imemo, enum imemo_type imemo_type);
139static inline bool imemo_throw_data_p(VALUE imemo);
140static inline struct vm_ifunc *rb_vm_ifunc_proc_new(rb_block_call_func_t func, const void *data);
141static inline void *RB_IMEMO_TMPBUF_PTR(VALUE v);
142static inline void MEMO_V1_SET(struct MEMO *m, VALUE v);
143static inline void MEMO_V2_SET(struct MEMO *m, VALUE v);
144
145size_t rb_imemo_memsize(VALUE obj);
146void rb_imemo_mark_and_move(VALUE obj, bool reference_updating);
147void rb_imemo_free(VALUE obj);
148
149RUBY_SYMBOL_EXPORT_BEGIN
150const char *rb_imemo_name(enum imemo_type type);
151RUBY_SYMBOL_EXPORT_END
152
153static inline enum imemo_type
154imemo_type(VALUE imemo)
155{
156 return (RBASIC(imemo)->flags >> FL_USHIFT) & IMEMO_MASK;
157}
158
159static inline int
160imemo_type_p(VALUE imemo, enum imemo_type imemo_type)
161{
162 if (LIKELY(!RB_SPECIAL_CONST_P(imemo))) {
163 /* fixed at compile time if imemo_type is given. */
164 const VALUE mask = (IMEMO_MASK << FL_USHIFT) | RUBY_T_MASK;
165 const VALUE expected_type = (imemo_type << FL_USHIFT) | T_IMEMO;
166 /* fixed at runtime. */
167 return expected_type == (RBASIC(imemo)->flags & mask);
168 }
169 else {
170 return 0;
171 }
172}
173
174#define IMEMO_TYPE_P(v, t) imemo_type_p((VALUE)(v), t)
175
176static inline bool
177imemo_throw_data_p(VALUE imemo)
178{
179 return RB_TYPE_P(imemo, T_IMEMO);
180}
181
182static inline struct vm_ifunc *
183rb_vm_ifunc_proc_new(rb_block_call_func_t func, const void *data)
184{
185 return rb_vm_ifunc_new(func, data, 0, UNLIMITED_ARGUMENTS);
186}
187
188static inline void *
189RB_IMEMO_TMPBUF_PTR(VALUE v)
190{
191 const struct rb_imemo_tmpbuf_struct *p = (const void *)v;
192 return p->ptr;
193}
194
195static inline VALUE
196rb_imemo_tmpbuf_new_from_an_RString(VALUE str)
197{
198 VALUE imemo;
199 size_t len;
200
201 StringValue(str);
202 len = RSTRING_LEN(str);
203 rb_alloc_tmp_buffer(&imemo, len);
204 memcpy(RB_IMEMO_TMPBUF_PTR(imemo), RSTRING_PTR(str), len);
205 return imemo;
206}
207
208static inline void
209MEMO_V1_SET(struct MEMO *m, VALUE v)
210{
211 RB_OBJ_WRITE(m, &m->v1, v);
212}
213
214static inline void
215MEMO_V2_SET(struct MEMO *m, VALUE v)
216{
217 RB_OBJ_WRITE(m, &m->v2, v);
218}
219
220struct rb_fields {
221 struct RBasic basic;
222 union {
223 struct {
224 VALUE fields[1];
225 } embed;
226 struct {
227 VALUE *ptr;
228 } external;
229 struct {
230 // Note: the st_table could be embedded, but complex T_CLASS should be rare to
231 // non-existent, so not really worth the trouble.
232 st_table *table;
233 } complex;
234 } as;
235};
236
237// IMEMO/fields and T_OBJECT have exactly the same layout.
238// This is useful for JIT and common codepaths.
239#define OBJ_FIELD_HEAP ROBJECT_HEAP
240STATIC_ASSERT(imemo_fields_flags, OBJ_FIELD_HEAP == IMEMO_FL_USER0);
241STATIC_ASSERT(imemo_fields_embed_offset, offsetof(struct RObject, as.ary) == offsetof(struct rb_fields, as.embed.fields));
242STATIC_ASSERT(imemo_fields_external_offset, offsetof(struct RObject, as.heap.fields) == offsetof(struct rb_fields, as.external.ptr));
243STATIC_ASSERT(imemo_fields_complex_offset, offsetof(struct RObject, as.heap.fields) == offsetof(struct rb_fields, as.complex.table));
244
245#define IMEMO_OBJ_FIELDS(fields) ((struct rb_fields *)fields)
246
247VALUE rb_imemo_fields_new(VALUE owner, size_t capa, bool shareable);
248VALUE rb_imemo_fields_new_complex(VALUE owner, size_t capa, bool shareable);
249VALUE rb_imemo_fields_new_complex_tbl(VALUE owner, st_table *tbl, bool shareable);
250VALUE rb_imemo_fields_clone(VALUE fields_obj);
251void rb_imemo_fields_clear(VALUE fields_obj);
252
253static inline VALUE
254rb_imemo_fields_owner(VALUE fields_obj)
255{
256 RUBY_ASSERT(IMEMO_TYPE_P(fields_obj, imemo_fields));
257
258 return CLASS_OF(fields_obj);
259}
260
261static inline VALUE *
262rb_imemo_fields_ptr(VALUE fields_obj)
263{
264 if (!fields_obj) {
265 return NULL;
266 }
267
268 RUBY_ASSERT(IMEMO_TYPE_P(fields_obj, imemo_fields) || RB_TYPE_P(fields_obj, T_OBJECT));
269
270 if (UNLIKELY(FL_TEST_RAW(fields_obj, OBJ_FIELD_HEAP))) {
271 return IMEMO_OBJ_FIELDS(fields_obj)->as.external.ptr;
272 }
273 else {
274 return IMEMO_OBJ_FIELDS(fields_obj)->as.embed.fields;
275 }
276}
277
278static inline st_table *
279rb_imemo_fields_complex_tbl(VALUE fields_obj)
280{
281 if (!fields_obj) {
282 return NULL;
283 }
284
285 RUBY_ASSERT(IMEMO_TYPE_P(fields_obj, imemo_fields) || RB_TYPE_P(fields_obj, T_OBJECT));
286 RUBY_ASSERT(FL_TEST_RAW(fields_obj, OBJ_FIELD_HEAP));
287
288 // Some codepaths unconditionally access the fields_ptr, and assume it can be used as st_table if the
289 // shape is too_complex.
290 RUBY_ASSERT((st_table *)rb_imemo_fields_ptr(fields_obj) == IMEMO_OBJ_FIELDS(fields_obj)->as.complex.table);
291
292 return IMEMO_OBJ_FIELDS(fields_obj)->as.complex.table;
293}
294
295#endif /* INTERNAL_IMEMO_H */
#define RUBY_ASSERT(...)
Asserts that the given expression is truthy if and only if RUBY_DEBUG is truthy.
Definition assert.h:219
#define T_IMEMO
Old name of RUBY_T_IMEMO.
Definition value_type.h:67
#define CLASS_OF
Old name of rb_class_of.
Definition globals.h:205
#define FL_TEST_RAW
Old name of RB_FL_TEST_RAW.
Definition fl_type.h:128
#define T_OBJECT
Old name of RUBY_T_OBJECT.
Definition value_type.h:75
#define FL_USHIFT
Old name of RUBY_FL_USHIFT.
Definition fl_type.h:67
#define RB_OBJ_WRITE(old, slot, young)
Declaration of a "back" pointer.
Definition gc.h:603
#define UNLIMITED_ARGUMENTS
This macro is used in conjunction with rb_check_arity().
Definition error.h:35
int capa
Designed capacity of the buffer.
Definition io.h:11
int len
Length of the buffer.
Definition io.h:8
rb_block_call_func * rb_block_call_func_t
Shorthand type that represents an iterator-written-in-C function pointer.
Definition iterator.h:88
VALUE type(ANYARGS)
ANYARGS-ed function type.
#define RBASIC(obj)
Convenient casting macro.
Definition rbasic.h:40
#define StringValue(v)
Ensures that the parameter object is a String.
Definition rstring.h:66
static bool RB_SPECIAL_CONST_P(VALUE obj)
Checks if the given object is of enum ruby_special_consts.
C99 shim for <stdbool.h>
MEMO.
Definition imemo.h:103
Ruby object's base components.
Definition rbasic.h:69
Ruby's ordinal objects.
Definition robject.h:85
VALUE * fields
Pointer to a C array that holds instance variables.
Definition robject.h:99
struct RObject::@50::@51 heap
Object that use separated memory region for instance variables use this pattern.
Definition st.h:79
IFUNC (Internal FUNCtion)
Definition imemo.h:84
SVAR (Special VARiable)
Definition imemo.h:49
const VALUE cref_or_me
class reference or rb_method_entry_t
Definition imemo.h:51
THROW_DATA.
Definition imemo.h:58
#define SIZEOF_VALUE
Identical to sizeof(VALUE), except it is a macro that can also be used inside of preprocessor directi...
Definition value.h:69
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
@ RUBY_T_MASK
Bitmask of ruby_value_type.
Definition value_type.h:145