Add IMEMO_NEW

Rather than exposing that an imemo has a flag and four fields, this
changes the implementation to only expose one field (the klass) and
fills the rest with 0. The type will have to fill in the values themselves.
This commit is contained in:
Peter Zhu 2024-02-20 15:58:10 -05:00
parent 2e6f8554f8
commit 330830dd1a
12 changed files with 69 additions and 33 deletions

8
gc.c
View File

@ -3013,11 +3013,11 @@ rb_imemo_name(enum imemo_type type)
#undef rb_imemo_new
VALUE
rb_imemo_new(enum imemo_type type, VALUE v1, VALUE v2, VALUE v3, VALUE v0)
rb_imemo_new(enum imemo_type type, VALUE v0)
{
size_t size = RVALUE_SIZE;
VALUE flags = T_IMEMO | (type << FL_USHIFT);
return newobj_of(GET_RACTOR(), v0, flags, v1, v2, v3, TRUE, size);
return newobj_of(GET_RACTOR(), v0, flags, 0, 0, 0, TRUE, size);
}
static VALUE
@ -3079,9 +3079,9 @@ imemo_memsize(VALUE obj)
#if IMEMO_DEBUG
VALUE
rb_imemo_new_debug(enum imemo_type type, VALUE v1, VALUE v2, VALUE v3, VALUE v0, const char *file, int line)
rb_imemo_new_debug(enum imemo_type type, VALUE v0, const char *file, int line)
{
VALUE memo = rb_imemo_new(type, v1, v2, v3, v0);
VALUE memo = rb_imemo_new(type, v0);
fprintf(stderr, "memo %p (type: %d) @ %s:%d\n", (void *)memo, imemo_type(memo), file, line);
return memo;
}

View File

@ -113,11 +113,12 @@ struct MEMO {
} u3;
};
#define IMEMO_NEW(T, type, v0) ((T *)rb_imemo_new((type), (v0)))
/* ment is in method.h */
#define THROW_DATA_P(err) imemo_throw_data_p((VALUE)err)
#define MEMO_CAST(m) ((struct MEMO *)(m))
#define MEMO_NEW(a, b, c) ((struct MEMO *)rb_imemo_new(imemo_memo, (VALUE)(a), (VALUE)(b), (VALUE)(c), 0))
#define MEMO_FOR(type, value) ((type *)RARRAY_PTR(value))
#define NEW_MEMO_FOR(type, value) \
((value) = rb_ary_hidden_new_fill(type_roomof(type, VALUE)), MEMO_FOR(type, value))
@ -144,14 +145,25 @@ static inline void MEMO_V2_SET(struct MEMO *m, VALUE v);
RUBY_SYMBOL_EXPORT_BEGIN
#if IMEMO_DEBUG
VALUE rb_imemo_new_debug(enum imemo_type type, VALUE v1, VALUE v2, VALUE v3, VALUE v0, const char *file, int line);
VALUE rb_imemo_new_debug(enum imemo_type type, VALUE v0, const char *file, int line);
#define rb_imemo_new(type, v1, v2, v3, v0) rb_imemo_new_debug(type, v1, v2, v3, v0, __FILE__, __LINE__)
#else
VALUE rb_imemo_new(enum imemo_type type, VALUE v1, VALUE v2, VALUE v3, VALUE v0);
VALUE rb_imemo_new(enum imemo_type type, VALUE v0);
#endif
const char *rb_imemo_name(enum imemo_type type);
RUBY_SYMBOL_EXPORT_END
static inline struct MEMO *
MEMO_NEW(VALUE a, VALUE b, VALUE c)
{
struct MEMO *memo = IMEMO_NEW(struct MEMO, imemo_memo, 0);
*((VALUE *)&memo->v1) = a;
*((VALUE *)&memo->v2) = b;
*((VALUE *)&memo->u3.value) = c;
return memo;
}
static inline enum imemo_type
imemo_type(VALUE imemo)
{
@ -190,7 +202,7 @@ rb_vm_ifunc_proc_new(rb_block_call_func_t func, const void *data)
static inline VALUE
rb_imemo_tmpbuf_auto_free_pointer(void)
{
return rb_imemo_new(imemo_tmpbuf, 0, 0, 0, 0);
return rb_imemo_new(imemo_tmpbuf, 0);
}
static inline void *

2
iseq.h
View File

@ -160,7 +160,7 @@ ISEQ_COMPILE_DATA_CLEAR(rb_iseq_t *iseq)
static inline rb_iseq_t *
iseq_imemo_alloc(void)
{
return (rb_iseq_t *)rb_imemo_new(imemo_iseq, 0, 0, 0, 0);
return IMEMO_NEW(rb_iseq_t, imemo_iseq, 0);
}
VALUE rb_iseq_ibf_dump(const rb_iseq_t *iseq, VALUE opt);

3
node.c
View File

@ -344,8 +344,7 @@ rb_ast_t *
rb_ast_new(void)
{
node_buffer_t *nb = rb_node_buffer_new();
rb_ast_t *ast = (rb_ast_t *)rb_imemo_new(imemo_ast, 0, 0, 0, (VALUE)nb);
return ast;
return IMEMO_NEW(rb_ast_t, imemo_ast, (VALUE)nb);
}
#endif

9
proc.c
View File

@ -719,8 +719,13 @@ rb_vm_ifunc_new(rb_block_call_func_t func, const void *data, int min_argc, int m
arity.argc.min = min_argc;
arity.argc.max = max_argc;
rb_execution_context_t *ec = GET_EC();
VALUE ret = rb_imemo_new(imemo_ifunc, (VALUE)func, (VALUE)data, arity.packed, (VALUE)rb_vm_svar_lep(ec, ec->cfp));
return (struct vm_ifunc *)ret;
struct vm_ifunc *ifunc = IMEMO_NEW(struct vm_ifunc, imemo_ifunc, (VALUE)rb_vm_svar_lep(ec, ec->cfp));
ifunc->func = func;
ifunc->data = data;
ifunc->argc = arity.argc;
return ifunc;
}
VALUE

View File

@ -446,8 +446,7 @@ ruby_vm_frozen_core(void)
static rb_ast_t *
ast_new(VALUE nb)
{
rb_ast_t *ast = (rb_ast_t *)rb_imemo_new(imemo_ast, 0, 0, 0, nb);
return ast;
return IMEMO_NEW(rb_ast_t, imemo_ast, nb);
}
static VALUE

8
vm.c
View File

@ -228,7 +228,6 @@ vm_cref_new0(VALUE klass, rb_method_visibility_t visi, int module_func, rb_cref_
{
VALUE refinements = Qnil;
int omod_shared = FALSE;
rb_cref_t *cref;
/* scope */
union {
@ -251,7 +250,10 @@ vm_cref_new0(VALUE klass, rb_method_visibility_t visi, int module_func, rb_cref_
VM_ASSERT(singleton || klass);
cref = (rb_cref_t *)rb_imemo_new(imemo_cref, klass, (VALUE)(use_prev_prev ? CREF_NEXT(prev_cref) : prev_cref), scope_visi.value, refinements);
rb_cref_t *cref = IMEMO_NEW(rb_cref_t, imemo_cref, refinements);
cref->klass_or_self = klass;
cref->next = use_prev_prev ? CREF_NEXT(prev_cref) : prev_cref;
*((rb_scope_visibility_t *)&cref->scope_visi) = scope_visi.visi;
if (pushed_by_eval) CREF_PUSHED_BY_EVAL_SET(cref);
if (omod_shared) CREF_OMOD_SHARED_SET(cref);
@ -979,7 +981,7 @@ vm_make_env_each(const rb_execution_context_t * const ec, rb_control_frame_t *co
// Careful with order in the following sequence. Each allocation can move objects.
env_body = ALLOC_N(VALUE, env_size);
rb_env_t *env = (rb_env_t *)rb_imemo_new(imemo_env, 0, 0, 0, 0);
rb_env_t *env = IMEMO_NEW(rb_env_t, imemo_env, 0);
// Set up env without WB since it's brand new (similar to newobj_init(), newobj_fill())
MEMCPY(env_body, ep - (local_size - 1 /* specval */), VALUE, local_size);

View File

@ -215,6 +215,7 @@ vm_ci_new_(ID mid, unsigned int flag, unsigned int argc, const struct rb_callinf
if (debug) ruby_debug_printf("%s:%d ", file, line);
const struct rb_callinfo *ci = rb_vm_ci_lookup(mid, flag, argc, kwarg);
if (debug) rp(ci);
if (kwarg) {
RB_DEBUG_COUNTER_INC(ci_kw);
@ -328,7 +329,9 @@ vm_cc_new(VALUE klass,
vm_call_handler call,
enum vm_cc_type type)
{
const struct rb_callcache *cc = (const struct rb_callcache *)rb_imemo_new(imemo_callcache, (VALUE)cme, (VALUE)call, 0, klass);
struct rb_callcache *cc = IMEMO_NEW(struct rb_callcache, imemo_callcache, klass);
*((struct rb_callable_method_entry_struct **)&cc->cme_) = (struct rb_callable_method_entry_struct *)cme;
*((vm_call_handler *)&cc->call_) = call;
switch (type) {
case cc_type_normal:

View File

@ -1208,8 +1208,12 @@ static inline struct rb_iseq_new_with_callback_callback_func *
rb_iseq_new_with_callback_new_callback(
void (*func)(rb_iseq_t *, struct iseq_link_anchor *, const void *), const void *ptr)
{
VALUE memo = rb_imemo_new(imemo_ifunc, (VALUE)func, (VALUE)ptr, Qundef, Qfalse);
return (struct rb_iseq_new_with_callback_callback_func *)memo;
struct rb_iseq_new_with_callback_callback_func *memo =
IMEMO_NEW(struct rb_iseq_new_with_callback_callback_func, imemo_ifunc, Qfalse);
memo->func = func;
memo->data = ptr;
return memo;
}
rb_iseq_t *rb_iseq_new_with_callback(const struct rb_iseq_new_with_callback_callback_func * ifunc,
VALUE name, VALUE path, VALUE realpath, int first_lineno,
@ -1506,7 +1510,9 @@ VM_ENV_ENVVAL_PTR(const VALUE *ep)
static inline const rb_env_t *
vm_env_new(VALUE *env_ep, VALUE *env_body, unsigned int env_size, const rb_iseq_t *iseq)
{
rb_env_t *env = (rb_env_t *)rb_imemo_new(imemo_env, (VALUE)env_ep, (VALUE)env_body, 0, (VALUE)iseq);
rb_env_t *env = IMEMO_NEW(rb_env_t, imemo_env, (VALUE)iseq);
env->ep = env_ep;
env->env = env_body;
env->env_size = env_size;
env_ep[VM_ENV_DATA_INDEX_ENV] = (VALUE)env;
return env;

View File

@ -623,7 +623,12 @@ lep_svar_get(const rb_execution_context_t *ec, const VALUE *lep, rb_num_t key)
static struct vm_svar *
svar_new(VALUE obj)
{
return (struct vm_svar *)rb_imemo_new(imemo_svar, Qnil, Qnil, Qnil, obj);
struct vm_svar *svar = IMEMO_NEW(struct vm_svar, imemo_svar, obj);
*((VALUE *)&svar->lastline) = Qnil;
*((VALUE *)&svar->backref) = Qnil;
*((VALUE *)&svar->others) = Qnil;
return svar;
}
static void
@ -5895,7 +5900,7 @@ vm_ic_update(const rb_iseq_t *iseq, IC ic, VALUE val, const VALUE *reg_ep, const
return;
}
struct iseq_inline_constant_cache_entry *ice = (struct iseq_inline_constant_cache_entry *)rb_imemo_new(imemo_constcache, 0, 0, 0, 0);
struct iseq_inline_constant_cache_entry *ice = IMEMO_NEW(struct iseq_inline_constant_cache_entry, imemo_constcache, 0);
RB_OBJ_WRITE(ice, &ice->value, val);
ice->ic_cref = vm_get_const_key_cref(reg_ep);
if (rb_ractor_shareable_p(val)) ice->flags |= IMEMO_CONST_CACHE_SHAREABLE;

View File

@ -182,8 +182,11 @@ CC_SET_FASTPATH(const struct rb_callcache *cc, vm_call_handler func, bool enable
static inline struct vm_throw_data *
THROW_DATA_NEW(VALUE val, const rb_control_frame_t *cf, int st)
{
struct vm_throw_data *obj = (struct vm_throw_data *)rb_imemo_new(imemo_throw_data, val, (VALUE)cf, 0, 0);
struct vm_throw_data *obj = IMEMO_NEW(struct vm_throw_data, imemo_throw_data, 0);
*((VALUE *)&obj->throw_obj) = val;
*((struct rb_control_frame_struct **)&obj->catch_frame) = (struct rb_control_frame_struct *)cf;
obj->throw_state = st;
return obj;
}

View File

@ -409,13 +409,11 @@ rb_vm_ci_lookup(ID mid, unsigned int flag, unsigned int argc, const struct rb_ca
if (kwarg) {
((struct rb_callinfo_kwarg *)kwarg)->references++;
}
const struct rb_callinfo *new_ci = (const struct rb_callinfo *)
rb_imemo_new(
imemo_callinfo,
(VALUE)mid,
(VALUE)flag,
(VALUE)argc,
(VALUE)kwarg);
struct rb_callinfo *new_ci = IMEMO_NEW(struct rb_callinfo, imemo_callinfo, (VALUE)kwarg);
new_ci->mid = mid;
new_ci->flag = flag;
new_ci->argc = argc;
RB_VM_LOCK_ENTER();
{
@ -764,7 +762,11 @@ static rb_method_entry_t *
rb_method_entry_alloc(ID called_id, VALUE owner, VALUE defined_class, rb_method_definition_t *def, bool complement)
{
if (def) method_definition_addref(def, complement);
rb_method_entry_t *me = (rb_method_entry_t *)rb_imemo_new(imemo_ment, (VALUE)def, (VALUE)called_id, owner, defined_class);
rb_method_entry_t *me = IMEMO_NEW(rb_method_entry_t, imemo_ment, defined_class);
*((rb_method_definition_t **)&me->def) = def;
me->called_id = called_id;
me->owner = owner;
return me;
}