Ruby 3.5.0dev (2025-06-27 revision 64a52c25fef8e156630fea559ced7286fe5c3beb)
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_ast = 9, // Obsolete due to the universal parser
41 imemo_parser_strterm = 10,
42 imemo_callinfo = 11,
43 imemo_callcache = 12,
44 imemo_constcache = 13,
45 imemo_fields = 14,
46};
47
48/* CREF (Class REFerence) is defined in method.h */
49
51struct vm_svar {
52 VALUE flags;
54 const VALUE lastline;
55 const VALUE backref;
56 const VALUE others;
57};
58
61 VALUE flags;
62 VALUE reserved;
63 const VALUE throw_obj;
64 const struct rb_control_frame_struct *catch_frame;
65 int throw_state;
66};
67
68#define THROW_DATA_CONSUMED IMEMO_FL_USER0
69
70/* IFUNC (Internal FUNCtion) */
71
73#if SIZEOF_INT * 2 > SIZEOF_VALUE
74 signed int min: (SIZEOF_VALUE * CHAR_BIT) / 2;
75 signed int max: (SIZEOF_VALUE * CHAR_BIT) / 2;
76#else
77 int min, max;
78#endif
79};
80
87struct vm_ifunc {
88 VALUE flags;
89 VALUE *svar_lep;
91 const void *data;
92 struct vm_ifunc_argc argc;
93};
94#define IFUNC_YIELD_OPTIMIZABLE IMEMO_FL_USER0
95
97 VALUE flags;
98 VALUE reserved;
99 VALUE *ptr; /* malloc'ed buffer */
100 struct rb_imemo_tmpbuf_struct *next; /* next imemo */
101 size_t cnt; /* buffer size in VALUE */
102};
103
108struct MEMO {
109 VALUE flags;
110 VALUE reserved;
111 const VALUE v1;
112 const VALUE v2;
113 union {
114 long cnt;
115 long state;
116 const VALUE value;
117 void (*func)(void);
118 } u3;
119};
120
121#define IMEMO_NEW(T, type, v0) ((T *)rb_imemo_new((type), (v0), sizeof(T)))
122
123/* ment is in method.h */
124
125#define THROW_DATA_P(err) imemo_throw_data_p((VALUE)err)
126#define MEMO_CAST(m) ((struct MEMO *)(m))
127#define MEMO_FOR(type, value) ((type *)RARRAY_PTR(value))
128#define NEW_MEMO_FOR(type, value) \
129 ((value) = rb_ary_hidden_new_fill(type_roomof(type, VALUE)), MEMO_FOR(type, value))
130#define NEW_PARTIAL_MEMO_FOR(type, value, member) \
131 ((value) = rb_ary_hidden_new_fill(type_roomof(type, VALUE)), \
132 rb_ary_set_len((value), offsetof(type, member) / sizeof(VALUE)), \
133 MEMO_FOR(type, value))
134
135#ifndef RUBY_RUBYPARSER_H
137#endif
138rb_imemo_tmpbuf_t *rb_imemo_tmpbuf_parser_heap(void *buf, rb_imemo_tmpbuf_t *old_heap, size_t cnt);
139struct vm_ifunc *rb_vm_ifunc_new(rb_block_call_func_t func, const void *data, int min_argc, int max_argc);
140static inline enum imemo_type imemo_type(VALUE imemo);
141static inline int imemo_type_p(VALUE imemo, enum imemo_type imemo_type);
142static inline bool imemo_throw_data_p(VALUE imemo);
143static inline struct vm_ifunc *rb_vm_ifunc_proc_new(rb_block_call_func_t func, const void *data);
144static inline VALUE rb_imemo_tmpbuf_auto_free_pointer(void);
145static inline void *RB_IMEMO_TMPBUF_PTR(VALUE v);
146static inline void *rb_imemo_tmpbuf_set_ptr(VALUE v, void *ptr);
147static inline VALUE rb_imemo_tmpbuf_auto_free_pointer_new_from_an_RString(VALUE str);
148static inline void MEMO_V1_SET(struct MEMO *m, VALUE v);
149static inline void MEMO_V2_SET(struct MEMO *m, VALUE v);
150
151size_t rb_imemo_memsize(VALUE obj);
152void rb_cc_table_mark(VALUE klass);
153void rb_imemo_mark_and_move(VALUE obj, bool reference_updating);
154void rb_cc_table_free(VALUE klass);
155void rb_cc_tbl_free(struct rb_id_table *cc_tbl, VALUE klass);
156void rb_imemo_free(VALUE obj);
157
158RUBY_SYMBOL_EXPORT_BEGIN
159VALUE rb_imemo_new(enum imemo_type type, VALUE v0, size_t size);
160const char *rb_imemo_name(enum imemo_type type);
161RUBY_SYMBOL_EXPORT_END
162
163static inline struct MEMO *
164MEMO_NEW(VALUE a, VALUE b, VALUE c)
165{
166 struct MEMO *memo = IMEMO_NEW(struct MEMO, imemo_memo, 0);
167 *((VALUE *)&memo->v1) = a;
168 *((VALUE *)&memo->v2) = b;
169 *((VALUE *)&memo->u3.value) = c;
170
171 return memo;
172}
173
174static inline enum imemo_type
175imemo_type(VALUE imemo)
176{
177 return (RBASIC(imemo)->flags >> FL_USHIFT) & IMEMO_MASK;
178}
179
180static inline int
181imemo_type_p(VALUE imemo, enum imemo_type imemo_type)
182{
183 if (LIKELY(!RB_SPECIAL_CONST_P(imemo))) {
184 /* fixed at compile time if imemo_type is given. */
185 const VALUE mask = (IMEMO_MASK << FL_USHIFT) | RUBY_T_MASK;
186 const VALUE expected_type = (imemo_type << FL_USHIFT) | T_IMEMO;
187 /* fixed at runtime. */
188 return expected_type == (RBASIC(imemo)->flags & mask);
189 }
190 else {
191 return 0;
192 }
193}
194
195#define IMEMO_TYPE_P(v, t) imemo_type_p((VALUE)(v), t)
196
197static inline bool
198imemo_throw_data_p(VALUE imemo)
199{
200 return RB_TYPE_P(imemo, T_IMEMO);
201}
202
203static inline struct vm_ifunc *
204rb_vm_ifunc_proc_new(rb_block_call_func_t func, const void *data)
205{
206 return rb_vm_ifunc_new(func, data, 0, UNLIMITED_ARGUMENTS);
207}
208
209static inline VALUE
210rb_imemo_tmpbuf_auto_free_pointer(void)
211{
212 return rb_imemo_new(imemo_tmpbuf, 0, sizeof(rb_imemo_tmpbuf_t));
213}
214
215static inline void *
216RB_IMEMO_TMPBUF_PTR(VALUE v)
217{
218 const struct rb_imemo_tmpbuf_struct *p = (const void *)v;
219 return p->ptr;
220}
221
222static inline void *
223rb_imemo_tmpbuf_set_ptr(VALUE v, void *ptr)
224{
225 return ((rb_imemo_tmpbuf_t *)v)->ptr = ptr;
226}
227
228static inline VALUE
229rb_imemo_tmpbuf_auto_free_pointer_new_from_an_RString(VALUE str)
230{
231 const void *src;
232 VALUE imemo;
233 rb_imemo_tmpbuf_t *tmpbuf;
234 void *dst;
235 size_t len;
236
237 StringValue(str);
238 /* create tmpbuf to keep the pointer before xmalloc */
239 imemo = rb_imemo_tmpbuf_auto_free_pointer();
240 tmpbuf = (rb_imemo_tmpbuf_t *)imemo;
241 len = RSTRING_LEN(str);
242 src = RSTRING_PTR(str);
243 dst = ruby_xmalloc(len);
244 memcpy(dst, src, len);
245 tmpbuf->ptr = dst;
246 return imemo;
247}
248
249static inline void
250MEMO_V1_SET(struct MEMO *m, VALUE v)
251{
252 RB_OBJ_WRITE(m, &m->v1, v);
253}
254
255static inline void
256MEMO_V2_SET(struct MEMO *m, VALUE v)
257{
258 RB_OBJ_WRITE(m, &m->v2, v);
259}
260
261struct rb_fields {
262 struct RBasic basic;
263 union {
264 struct {
265 VALUE fields[1];
266 } embed;
267 struct {
268 VALUE *ptr;
269 } external;
270 struct {
271 // Note: the st_table could be embedded, but complex T_CLASS should be rare to
272 // non-existent, so not really worth the trouble.
273 st_table *table;
274 } complex;
275 } as;
276};
277
278#define OBJ_FIELD_EXTERNAL IMEMO_FL_USER0
279#define IMEMO_OBJ_FIELDS(fields) ((struct rb_fields *)fields)
280
281VALUE rb_imemo_fields_new(VALUE klass, size_t capa);
282VALUE rb_imemo_fields_new_complex(VALUE klass, size_t capa);
283VALUE rb_imemo_fields_new_complex_tbl(VALUE klass, st_table *tbl);
284VALUE rb_imemo_fields_clone(VALUE fields_obj);
285void rb_imemo_fields_clear(VALUE fields_obj);
286
287static inline VALUE *
288rb_imemo_fields_ptr(VALUE obj_fields)
289{
290 if (!obj_fields) {
291 return NULL;
292 }
293
294 RUBY_ASSERT(IMEMO_TYPE_P(obj_fields, imemo_fields));
295
296 if (RB_UNLIKELY(FL_TEST_RAW(obj_fields, OBJ_FIELD_EXTERNAL))) {
297 return IMEMO_OBJ_FIELDS(obj_fields)->as.external.ptr;
298 }
299 else {
300 return IMEMO_OBJ_FIELDS(obj_fields)->as.embed.fields;
301 }
302}
303
304static inline st_table *
305rb_imemo_fields_complex_tbl(VALUE obj_fields)
306{
307 if (!obj_fields) {
308 return NULL;
309 }
310
311 RUBY_ASSERT(IMEMO_TYPE_P(obj_fields, imemo_fields));
312
313 return IMEMO_OBJ_FIELDS(obj_fields)->as.complex.table;
314}
315
316#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 FL_TEST_RAW
Old name of RB_FL_TEST_RAW.
Definition fl_type.h:131
#define FL_USHIFT
Old name of RUBY_FL_USHIFT.
Definition fl_type.h:68
#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:108
Ruby object's base components.
Definition rbasic.h:69
Definition st.h:79
IFUNC (Internal FUNCtion)
Definition imemo.h:87
SVAR (Special VARiable)
Definition imemo.h:51
const VALUE cref_or_me
class reference or rb_method_entry_t
Definition imemo.h:53
THROW_DATA.
Definition imemo.h:60
#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