From 330830dd1a44b6e497250a14d93efae6fa363f82 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Tue, 20 Feb 2024 15:58:10 -0500 Subject: [PATCH] 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. --- gc.c | 8 ++++---- internal/imemo.h | 20 ++++++++++++++++---- iseq.h | 2 +- node.c | 3 +-- proc.c | 9 +++++++-- ruby_parser.c | 3 +-- vm.c | 8 +++++--- vm_callinfo.h | 5 ++++- vm_core.h | 12 +++++++++--- vm_insnhelper.c | 9 +++++++-- vm_insnhelper.h | 5 ++++- vm_method.c | 18 ++++++++++-------- 12 files changed, 69 insertions(+), 33 deletions(-) diff --git a/gc.c b/gc.c index 89c474f730..08d54d5fdc 100644 --- a/gc.c +++ b/gc.c @@ -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; } diff --git a/internal/imemo.h b/internal/imemo.h index f52b60e016..5b54629c99 100644 --- a/internal/imemo.h +++ b/internal/imemo.h @@ -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 * diff --git a/iseq.h b/iseq.h index 099e6a5711..ec5b145f43 100644 --- a/iseq.h +++ b/iseq.h @@ -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); diff --git a/node.c b/node.c index 2828af26fc..8011d61255 100644 --- a/node.c +++ b/node.c @@ -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 diff --git a/proc.c b/proc.c index 6ff152fdb9..bb09f92ae9 100644 --- a/proc.c +++ b/proc.c @@ -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 diff --git a/ruby_parser.c b/ruby_parser.c index 7b6f0dfbc3..c4b4ffc1a3 100644 --- a/ruby_parser.c +++ b/ruby_parser.c @@ -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 diff --git a/vm.c b/vm.c index 9c112d039b..3ceaef1a4b 100644 --- a/vm.c +++ b/vm.c @@ -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); diff --git a/vm_callinfo.h b/vm_callinfo.h index 8b45d7fdf3..21e0755aa8 100644 --- a/vm_callinfo.h +++ b/vm_callinfo.h @@ -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: diff --git a/vm_core.h b/vm_core.h index 8889ed7c31..d6c045af0c 100644 --- a/vm_core.h +++ b/vm_core.h @@ -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; diff --git a/vm_insnhelper.c b/vm_insnhelper.c index 63a88aea00..d38c7e9a24 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -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; diff --git a/vm_insnhelper.h b/vm_insnhelper.h index e4a6c5b492..286bc1f671 100644 --- a/vm_insnhelper.h +++ b/vm_insnhelper.h @@ -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; } diff --git a/vm_method.c b/vm_method.c index bd43d7ea4d..0f69bc00fc 100644 --- a/vm_method.c +++ b/vm_method.c @@ -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; }