Ruby 4.1.0dev (2026-10-06 revision df0fa43f5343f5ec18c63521592c36cde1092f7a)
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
18struct rb_gc_mark_ctx; /* internal/gc.h */
19
20#define IMEMO_MASK (FL_USER0 | FL_USER1 | FL_USER2 | FL_USER3 | FL_USER4)
21
22/* FL_USER0 to FL_USER4 is for type */
23#define IMEMO_FL_USHIFT (FL_USHIFT + 5)
24#define IMEMO_FL_USER0 FL_USER5
25#define IMEMO_FL_USER1 FL_USER6
26#define IMEMO_FL_USER2 FL_USER7
27#define IMEMO_FL_USER3 FL_USER8
28#define IMEMO_FL_USER4 FL_USER9
29#define IMEMO_FL_USER5 FL_USER10
30#define IMEMO_FL_USER6 FL_USER11
31
32enum imemo_type {
33 imemo_env = 0,
34 imemo_cref = 1,
35 imemo_svar = 2,
36 imemo_throw_data = 3,
37 imemo_ifunc = 4,
38 imemo_memo = 5,
39 imemo_ment = 6,
40 imemo_iseq = 7,
41 imemo_tmpbuf = 8,
42 imemo_cvar_entry = 9,
43 imemo_callinfo = 10,
44 imemo_callcache = 11,
45 imemo_constcache = 12,
46 imemo_fields = 13,
47 imemo_subclasses = 14,
48 imemo_cdhash = 15,
49};
50
51/* CREF (Class REFerence) is defined in method.h */
52
54struct vm_svar {
55 VALUE flags;
57 const VALUE lastline;
58 const VALUE backref;
59 const VALUE others;
60};
61
64 VALUE flags;
65 const VALUE throw_obj;
66 const struct rb_control_frame_struct *catch_frame;
67 int throw_state;
68};
69
70#define THROW_DATA_CONSUMED IMEMO_FL_USER0
71
72/* IFUNC (Internal FUNCtion) */
73
75#if SIZEOF_INT * 2 > SIZEOF_VALUE
76 signed int min: (SIZEOF_VALUE * CHAR_BIT) / 2;
77 signed int max: (SIZEOF_VALUE * CHAR_BIT) / 2;
78#else
79 int min, max;
80#endif
81};
82
89struct vm_ifunc {
90 VALUE flags;
91 VALUE *svar_lep;
93 const void *data;
94 struct vm_ifunc_argc argc;
95};
96#define IFUNC_YIELD_OPTIMIZABLE IMEMO_FL_USER0
97
99 VALUE flags;
100 VALUE *ptr; /* malloc'ed buffer */
101 size_t size; /* buffer size in bytes */
102 bool marked; /* whether the buffer may contain object references */
103};
104
106 VALUE flags;
107 st_table tbl;
108};
109
110/* Set on imemo_memo when u3 holds a VALUE that GC must mark.
111 * When unset, u3 is a non-VALUE (cnt/state). */
112#define MEMO_U3_IS_VALUE IMEMO_FL_USER0
113
118struct MEMO {
119 VALUE flags;
120 const VALUE v1;
121 const VALUE v2;
122 union {
123 long cnt;
124 long state;
125 const VALUE value;
126 } u3;
127};
128
129#define IMEMO_NEW(T, type, v0) ((T *)rb_imemo_new((type), (v0), sizeof(T), false))
130#define SHAREABLE_IMEMO_NEW(T, type, v0) ((T *)rb_imemo_new((type), (v0), sizeof(T), true))
131
132/* ment is in method.h */
133
134#define THROW_DATA_P(err) imemo_throw_data_p((VALUE)err)
135#define MEMO_CAST(m) ((struct MEMO *)(m))
136#define MEMO_FOR(type, value) ((type *)RARRAY_PTR(value))
137#define NEW_MEMO_FOR(type, value) \
138 ((value) = rb_ary_hidden_new_fill(type_roomof(type, VALUE)), MEMO_FOR(type, value))
139#define NEW_PARTIAL_MEMO_FOR(type, value, member) \
140 ((value) = rb_ary_hidden_new_fill(type_roomof(type, VALUE)), \
141 rb_ary_set_len((value), offsetof(type, member) / sizeof(VALUE)), \
142 MEMO_FOR(type, value))
143
144#ifndef RUBY_RUBYPARSER_H
146#endif
147VALUE rb_imemo_new(enum imemo_type type, VALUE v0, size_t size, bool is_shareable);
148struct MEMO *rb_imemo_memo_new(VALUE a, VALUE b, long c);
149struct MEMO *rb_imemo_memo_new_value(VALUE a, VALUE b, VALUE c);
150struct vm_ifunc *rb_vm_ifunc_new(rb_block_call_func_t func, const void *data, int min_argc, int max_argc);
151static inline enum imemo_type imemo_type(VALUE imemo);
152static inline int imemo_type_p(VALUE imemo, enum imemo_type imemo_type);
153static inline bool imemo_throw_data_p(VALUE imemo);
154static inline struct vm_ifunc *rb_vm_ifunc_proc_new(rb_block_call_func_t func, const void *data);
155static inline void *RB_IMEMO_TMPBUF_PTR(VALUE v);
156static inline void MEMO_V1_SET(struct MEMO *m, VALUE v);
157static inline void MEMO_V2_SET(struct MEMO *m, VALUE v);
158
159size_t rb_imemo_memsize(VALUE obj);
160void rb_imemo_mark_and_move(const struct rb_gc_mark_ctx *ctx, VALUE obj, bool reference_updating);
161void rb_imemo_free(VALUE obj);
162
163RUBY_SYMBOL_EXPORT_BEGIN
164const char *rb_imemo_name(enum imemo_type type);
165ID rb_imemo_callinfo_mid(VALUE obj);
167 VALUE klass;
168 ID called_id;
169};
170bool rb_imemo_callcache_get_data(VALUE obj, struct rb_imemo_callcache_data *data);
171RUBY_SYMBOL_EXPORT_END
172
173static inline enum imemo_type
174imemo_type(VALUE imemo)
175{
176 return (RBASIC(imemo)->flags & IMEMO_MASK) >> FL_USHIFT;
177}
178
179static inline int
180imemo_type_p(VALUE imemo, enum imemo_type imemo_type)
181{
182 if (LIKELY(!RB_SPECIAL_CONST_P(imemo))) {
183 /* fixed at compile time if imemo_type is given. */
184 const VALUE mask = IMEMO_MASK | RUBY_T_MASK;
185 const VALUE expected_type = (imemo_type << FL_USHIFT) | T_IMEMO;
186 /* fixed at runtime. */
187 return expected_type == (RBASIC(imemo)->flags & mask);
188 }
189 else {
190 return 0;
191 }
192}
193
194#define IMEMO_TYPE_P(v, t) imemo_type_p((VALUE)(v), t)
195
196static inline bool
197imemo_throw_data_p(VALUE imemo)
198{
199 return RB_TYPE_P(imemo, T_IMEMO);
200}
201
202static inline struct vm_ifunc *
203rb_vm_ifunc_proc_new(rb_block_call_func_t func, const void *data)
204{
205 return rb_vm_ifunc_new(func, data, 0, UNLIMITED_ARGUMENTS);
206}
207
208static inline void *
209RB_IMEMO_TMPBUF_PTR(VALUE v)
210{
211 const struct rb_imemo_tmpbuf_struct *p = (const void *)v;
212 return p->ptr;
213}
214
215static inline VALUE
216rb_imemo_tmpbuf_new_from_an_RString(VALUE str)
217{
218 VALUE imemo;
219 size_t len;
220
221 StringValue(str);
222 len = RSTRING_LEN(str);
223 rb_alloc_tmp_buffer(&imemo, len, false);
224 memcpy(RB_IMEMO_TMPBUF_PTR(imemo), RSTRING_PTR(str), len);
225 return imemo;
226}
227
228static inline void
229MEMO_V1_SET(struct MEMO *m, VALUE v)
230{
231 RB_OBJ_WRITE(m, &m->v1, v);
232}
233
234static inline void
235MEMO_V2_SET(struct MEMO *m, VALUE v)
236{
237 RB_OBJ_WRITE(m, &m->v2, v);
238}
239
240VALUE rb_imemo_cdhash_new(size_t size, const struct st_hash_type *type);
241
242static inline st_table *
243rb_imemo_cdhash_tbl(VALUE obj)
244{
245 RUBY_ASSERT(IMEMO_TYPE_P(obj, imemo_cdhash));
246 return &((struct rb_imemo_cdhash *)obj)->tbl;
247}
248
249struct rb_fields {
250 struct RBasic basic;
251 union {
252 struct {
253 VALUE fields[1];
254 } embed;
255 struct {
256 st_table table;
257 } complex;
258 } as;
259};
260
261// IMEMO/fields and T_OBJECT have exactly the same layout.
262// This is useful for JIT and common codepaths.
263STATIC_ASSERT(imemo_fields_embed_offset, offsetof(struct RObject, as.ary) == offsetof(struct rb_fields, as.embed.fields));
264
265#define IMEMO_OBJ_FIELDS(fields) ((struct rb_fields *)fields)
266
267#define IMEMO_SUBCLASSES_HEAP IMEMO_FL_USER0
268
270 VALUE flags;
271 uint32_t count;
272 uint32_t capacity;
273 union {
274 VALUE *external;
275 VALUE embed[1];
276 } as;
277};
278
279static inline VALUE *
280rb_imemo_subclasses_entries(VALUE v)
281{
282 struct rb_subclasses *s = (struct rb_subclasses *)v;
283 return FL_TEST_RAW(v, IMEMO_SUBCLASSES_HEAP) ? s->as.external : s->as.embed;
284}
285
286VALUE rb_imemo_fields_new(VALUE owner, /* shape_id_t */ uint32_t shape_id, bool shareable);
287VALUE rb_imemo_subclasses_new(uint32_t capacity);
288VALUE rb_imemo_fields_new_complex(VALUE owner, /* shape_id_t */ uint32_t shape_id, size_t capa, bool shareable);
289VALUE rb_imemo_fields_new_complex_empty(VALUE owner);
290VALUE rb_imemo_fields_clone(VALUE fields_obj);
291void rb_imemo_fields_clear(VALUE fields_obj);
292
293static inline VALUE
294rb_imemo_fields_owner(VALUE fields_obj)
295{
296 RUBY_ASSERT(IMEMO_TYPE_P(fields_obj, imemo_fields));
297
298 return CLASS_OF(fields_obj);
299}
300
301#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 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:492
#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:118
Ruby object's base components.
Definition rbasic.h:69
Ruby's ordinal objects.
Definition robject.h:51
Definition st.h:79
IFUNC (Internal FUNCtion)
Definition imemo.h:89
SVAR (Special VARiable)
Definition imemo.h:54
const VALUE cref_or_me
class reference or rb_method_entry_t
Definition imemo.h:56
THROW_DATA.
Definition imemo.h:63
uintptr_t ID
Type that represents a Ruby identifier such as a variable name.
Definition value.h:52
#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