Ruby: internal/imemo.h Source File

Ruby 4.0.6p0 (2026-07-14 revision 03b6d3f8898a28604fe6cb00eae3226b821168f4)

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_cvar_entry = 9,
41 imemo_callinfo = 10,
42 imemo_callcache = 11,
43 imemo_constcache = 12,
44 imemo_fields = 13,
45};
46
47/* CREF (Class REFerence) is defined in method.h */
48
50 struct vm_svar {
51 VALUE flags;
52 const VALUE cref_or_me;
53 const VALUE lastline;
54 const VALUE backref;
55 const VALUE others;
56};
57
59 struct vm_throw_data {
60 VALUE flags;
61 VALUE reserved;
62 const VALUE throw_obj;
63 const struct rb_control_frame_struct *catch_frame;
64 int throw_state;
65};
66
67#define THROW_DATA_CONSUMED IMEMO_FL_USER0
68
69/* IFUNC (Internal FUNCtion) */
70
71 struct vm_ifunc_argc {
72#if SIZEOF_INT * 2 > SIZEOF_VALUE
73 signed int min: (SIZEOF_VALUE * CHAR_BIT) / 2;
74 signed int max: (SIZEOF_VALUE * CHAR_BIT) / 2;
75#else
76 int min, max;
77#endif
78};
79
86 struct vm_ifunc {
87 VALUE flags;
88 VALUE *svar_lep;
89 rb_block_call_func_t func;
90 const void *data;
91 struct vm_ifunc_argc argc;
92};
93#define IFUNC_YIELD_OPTIMIZABLE IMEMO_FL_USER0
94
95 struct rb_imemo_tmpbuf_struct {
96 VALUE flags;
97 VALUE *ptr; /* malloc'ed buffer */
98 size_t cnt; /* buffer size in VALUE */
99};
100
105 struct MEMO {
106 VALUE flags;
107 VALUE reserved;
108 const VALUE v1;
109 const VALUE v2;
110 union {
111 long cnt;
112 long state;
113 const VALUE value;
114 void (*func)(void);
115 } u3;
116};
117
118#define IMEMO_NEW(T, type, v0) ((T *)rb_imemo_new((type), (v0), sizeof(T), false))
119#define SHAREABLE_IMEMO_NEW(T, type, v0) ((T *)rb_imemo_new((type), (v0), sizeof(T), true))
120
121/* ment is in method.h */
122
123#define THROW_DATA_P(err) imemo_throw_data_p((VALUE)err)
124#define MEMO_CAST(m) ((struct MEMO *)(m))
125#define MEMO_FOR(type, value) ((type *)RARRAY_PTR(value))
126#define NEW_MEMO_FOR(type, value) \
127 ((value) = rb_ary_hidden_new_fill(type_roomof(type, VALUE)), MEMO_FOR(type, value))
128#define NEW_PARTIAL_MEMO_FOR(type, value, member) \
129 ((value) = rb_ary_hidden_new_fill(type_roomof(type, VALUE)), \
130 rb_ary_set_len((value), offsetof(type, member) / sizeof(VALUE)), \
131 MEMO_FOR(type, value))
132
133#ifndef RUBY_RUBYPARSER_H
134typedef struct rb_imemo_tmpbuf_struct rb_imemo_tmpbuf_t;
135#endif
136 VALUE rb_imemo_new(enum imemo_type type, VALUE v0, size_t size, bool is_shareable);
137 VALUE rb_imemo_tmpbuf_new(void);
138struct vm_ifunc *rb_vm_ifunc_new(rb_block_call_func_t func, const void *data, int min_argc, int max_argc);
139static inline enum imemo_type imemo_type(VALUE imemo);
140static inline int imemo_type_p(VALUE imemo, enum imemo_type imemo_type);
141static inline bool imemo_throw_data_p(VALUE imemo);
142static inline struct vm_ifunc *rb_vm_ifunc_proc_new(rb_block_call_func_t func, const void *data);
143static inline void *RB_IMEMO_TMPBUF_PTR(VALUE v);
144static inline void *rb_imemo_tmpbuf_set_ptr(VALUE v, void *ptr);
145static inline void MEMO_V1_SET(struct MEMO *m, VALUE v);
146static inline void MEMO_V2_SET(struct MEMO *m, VALUE v);
147
148size_t rb_imemo_memsize(VALUE obj);
149void rb_imemo_mark_and_move(VALUE obj, bool reference_updating);
150void rb_imemo_free(VALUE obj);
151
152RUBY_SYMBOL_EXPORT_BEGIN
153const char *rb_imemo_name(enum imemo_type type);
154RUBY_SYMBOL_EXPORT_END
155
156static inline struct MEMO *
157MEMO_NEW(VALUE a, VALUE b, VALUE c)
158{
159 struct MEMO *memo = IMEMO_NEW(struct MEMO, imemo_memo, 0);
160 *((VALUE *)&memo->v1) = a;
161 *((VALUE *)&memo->v2) = b;
162 *((VALUE *)&memo->u3.value) = c;
163
164 return memo;
165}
166
167static inline enum imemo_type
168imemo_type(VALUE imemo)
169{
170 return (RBASIC(imemo)->flags >> FL_USHIFT) & IMEMO_MASK;
171}
172
173static inline int
174imemo_type_p(VALUE imemo, enum imemo_type imemo_type)
175{
176 if (LIKELY(!RB_SPECIAL_CONST_P(imemo))) {
177 /* fixed at compile time if imemo_type is given. */
178 const VALUE mask = (IMEMO_MASK << FL_USHIFT) | RUBY_T_MASK;
179 const VALUE expected_type = (imemo_type << FL_USHIFT) | T_IMEMO;
180 /* fixed at runtime. */
181 return expected_type == (RBASIC(imemo)->flags & mask);
182 }
183 else {
184 return 0;
185 }
186}
187
188#define IMEMO_TYPE_P(v, t) imemo_type_p((VALUE)(v), t)
189
190static inline bool
191imemo_throw_data_p(VALUE imemo)
192{
193 return RB_TYPE_P(imemo, T_IMEMO);
194}
195
196static inline struct vm_ifunc *
197rb_vm_ifunc_proc_new(rb_block_call_func_t func, const void *data)
198{
199 return rb_vm_ifunc_new(func, data, 0, UNLIMITED_ARGUMENTS);
200}
201
202static inline void *
203RB_IMEMO_TMPBUF_PTR(VALUE v)
204{
205 const struct rb_imemo_tmpbuf_struct *p = (const void *)v;
206 return p->ptr;
207}
208
209static inline void *
210rb_imemo_tmpbuf_set_ptr(VALUE v, void *ptr)
211{
212 return ((rb_imemo_tmpbuf_t *)v)->ptr = ptr;
213}
214
215static inline VALUE
216rb_imemo_tmpbuf_new_from_an_RString(VALUE str)
217{
218 const void *src;
219 VALUE imemo;
220 rb_imemo_tmpbuf_t *tmpbuf;
221 void *dst;
222 size_t len;
223
224 StringValue(str);
225 /* create tmpbuf to keep the pointer before xmalloc */
226 imemo = rb_imemo_tmpbuf_new();
227 tmpbuf = (rb_imemo_tmpbuf_t *)imemo;
228 len = RSTRING_LEN(str);
229 src = RSTRING_PTR(str);
230 dst = ruby_xmalloc(len);
231 memcpy(dst, src, len);
232 tmpbuf->ptr = dst;
233 return imemo;
234}
235
236static inline void
237MEMO_V1_SET(struct MEMO *m, VALUE v)
238{
239 RB_OBJ_WRITE(m, &m->v1, v);
240}
241
242static inline void
243MEMO_V2_SET(struct MEMO *m, VALUE v)
244{
245 RB_OBJ_WRITE(m, &m->v2, v);
246}
247
248 struct rb_fields {
249 struct RBasic basic;
250 union {
251 struct {
252 VALUE fields[1];
253 } embed;
254 struct {
255 VALUE *ptr;
256 } external;
257 struct {
258 // Note: the st_table could be embedded, but complex T_CLASS should be rare to
259 // non-existent, so not really worth the trouble.
260 st_table *table;
261 } complex;
262 } as;
263};
264
265// IMEMO/fields and T_OBJECT have exactly the same layout.
266// This is useful for JIT and common codepaths.
267#define OBJ_FIELD_HEAP ROBJECT_HEAP
268STATIC_ASSERT(imemo_fields_flags, OBJ_FIELD_HEAP == IMEMO_FL_USER0);
269STATIC_ASSERT(imemo_fields_embed_offset, offsetof(struct RObject, as.ary) == offsetof(struct rb_fields, as.embed.fields));
270STATIC_ASSERT(imemo_fields_embed_offset, offsetof(struct RObject, as.heap.fields) == offsetof(struct rb_fields, as.external.ptr));
271STATIC_ASSERT(imemo_fields_embed_offset, offsetof(struct RObject, as.heap.fields) == offsetof(struct rb_fields, as.complex.table));
272
273#define IMEMO_OBJ_FIELDS(fields) ((struct rb_fields *)fields)
274
275 VALUE rb_imemo_fields_new(VALUE owner, size_t capa, bool shareable);
276 VALUE rb_imemo_fields_new_complex(VALUE owner, size_t capa, bool shareable);
277 VALUE rb_imemo_fields_new_complex_tbl(VALUE owner, st_table *tbl, bool shareable);
278 VALUE rb_imemo_fields_clone(VALUE fields_obj);
279void rb_imemo_fields_clear(VALUE fields_obj);
280
281static inline VALUE
282rb_imemo_fields_owner(VALUE fields_obj)
283{
284 RUBY_ASSERT(IMEMO_TYPE_P(fields_obj, imemo_fields));
285
286 return CLASS_OF(fields_obj);
287}
288
289static inline VALUE *
290rb_imemo_fields_ptr(VALUE fields_obj)
291{
292 if (!fields_obj) {
293 return NULL;
294 }
295
296 RUBY_ASSERT(IMEMO_TYPE_P(fields_obj, imemo_fields) || RB_TYPE_P(fields_obj, T_OBJECT));
297
298 if (UNLIKELY(FL_TEST_RAW(fields_obj, OBJ_FIELD_HEAP))) {
299 return IMEMO_OBJ_FIELDS(fields_obj)->as.external.ptr;
300 }
301 else {
302 return IMEMO_OBJ_FIELDS(fields_obj)->as.embed.fields;
303 }
304}
305
306static inline st_table *
307rb_imemo_fields_complex_tbl(VALUE fields_obj)
308{
309 if (!fields_obj) {
310 return NULL;
311 }
312
313 RUBY_ASSERT(IMEMO_TYPE_P(fields_obj, imemo_fields) || RB_TYPE_P(fields_obj, T_OBJECT));
314 RUBY_ASSERT(FL_TEST_RAW(fields_obj, OBJ_FIELD_HEAP));
315
316 // Some codepaths unconditionally access the fields_ptr, and assume it can be used as st_table if the
317 // shape is too_complex.
318 RUBY_ASSERT((st_table *)rb_imemo_fields_ptr(fields_obj) == IMEMO_OBJ_FIELDS(fields_obj)->as.complex.table);
319
320 return IMEMO_OBJ_FIELDS(fields_obj)->as.complex.table;
321}
322
323#endif /* INTERNAL_IMEMO_H */
RUBY_ASSERT
#define RUBY_ASSERT(...)
Asserts that the given expression is truthy if and only if RUBY_DEBUG is truthy.
Definition assert.h:219
T_IMEMO
#define T_IMEMO
Old name of RUBY_T_IMEMO.
Definition value_type.h:67
CLASS_OF
#define CLASS_OF
Old name of rb_class_of.
Definition globals.h:205
FL_TEST_RAW
#define FL_TEST_RAW
Old name of RB_FL_TEST_RAW.
Definition fl_type.h:131
T_OBJECT
#define T_OBJECT
Old name of RUBY_T_OBJECT.
Definition value_type.h:75
FL_USHIFT
#define FL_USHIFT
Old name of RUBY_FL_USHIFT.
Definition fl_type.h:68
RB_OBJ_WRITE
#define RB_OBJ_WRITE(old, slot, young)
Declaration of a "back" pointer.
Definition gc.h:603
UNLIMITED_ARGUMENTS
#define UNLIMITED_ARGUMENTS
This macro is used in conjunction with rb_check_arity().
Definition error.h:35
capa
int capa
Designed capacity of the buffer.
Definition io.h:11
len
int len
Length of the buffer.
Definition io.h:8
rb_block_call_func_t
rb_block_call_func * rb_block_call_func_t
Shorthand type that represents an iterator-written-in-C function pointer.
Definition iterator.h:88
ruby::backward::cxxanyargs::type
VALUE type(ANYARGS)
ANYARGS-ed function type.
Definition cxxanyargs.hpp:56
RBASIC
#define RBASIC(obj)
Convenient casting macro.
Definition rbasic.h:40
StringValue
#define StringValue(v)
Ensures that the parameter object is a String.
Definition rstring.h:66
ruby.h
RB_SPECIAL_CONST_P
static bool RB_SPECIAL_CONST_P(VALUE obj)
Checks if the given object is of enum ruby_special_consts.
Definition special_consts.h:327
stdbool.h
C99 shim for <stdbool.h>.
MEMO
MEMO.
Definition imemo.h:105
RBasic
Ruby object's base components.
Definition rbasic.h:69
RObject
Ruby's ordinal objects.
Definition robject.h:85
RObject::fields
VALUE * fields
Pointer to a C array that holds instance variables.
Definition robject.h:99
RObject::heap
struct RObject::@210145204263252121304200074116325373231002256127::@364327012272247144206277021107154033016101046306 heap
Object that use separated memory region for instance variables use this pattern.
rb_control_frame_struct
Definition vm_core.h:912
rb_fields
Definition imemo.h:248
rb_imemo_tmpbuf_struct
Definition imemo.h:95
st_table
Definition st.h:79
vm_ifunc_argc
Definition imemo.h:71
vm_ifunc
IFUNC (Internal FUNCtion).
Definition imemo.h:86
vm_svar
SVAR (Special VARiable).
Definition imemo.h:50
vm_svar::cref_or_me
const VALUE cref_or_me
class reference or rb_method_entry_t
Definition imemo.h:52
vm_throw_data
THROW_DATA.
Definition imemo.h:59
SIZEOF_VALUE
#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
VALUE
uintptr_t VALUE
Type that represents a Ruby object.
Definition value.h:40
RB_TYPE_P
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
@ RUBY_T_MASK
Bitmask of ruby_value_type.
Definition value_type.h:145