Enable redefinition check for rbinc methods

This commit is contained in:
Nobuyoshi Nakada 2023-10-18 17:47:48 +09:00 committed by Aaron Patterson
parent 1395838e18
commit 84d8dbe7a5
3 changed files with 78 additions and 7 deletions

5
ruby.c
View File

@ -1787,7 +1787,12 @@ ruby_opt_init(ruby_cmdline_options_t *opt)
Init_ext(); /* load statically linked extensions before rubygems */
Init_extra_exts();
GET_VM()->running = 0;
rb_call_builtin_inits();
GET_VM()->running = 1;
memset(ruby_vm_redefined_flag, 0, sizeof(ruby_vm_redefined_flag));
ruby_init_prelude();
// Initialize JITs after prelude because JITing prelude is typically not optimal.

78
vm.c
View File

@ -514,6 +514,8 @@ jit_exec_exception(rb_execution_context_t *ec)
# define jit_exec_exception(ec) Qundef
#endif
static void add_opt_method_entry(const rb_method_entry_t *me);
#include "vm_insnhelper.c"
#include "vm_exec.c"
@ -2104,6 +2106,8 @@ vm_redefinition_check_method_type(const rb_method_entry_t *me)
return FALSE;
}
if (METHOD_ENTRY_BASIC(me)) return TRUE;
const rb_method_definition_t *def = me->def;
switch (def->type) {
case VM_METHOD_TYPE_CFUNC:
@ -2154,27 +2158,44 @@ rb_vm_check_redefinition_by_prepend(VALUE klass)
}
static void
add_opt_method(VALUE klass, ID mid, VALUE bop)
add_opt_method_entry_bop(const rb_method_entry_t *me, ID mid, enum ruby_basic_operators bop)
{
st_insert(vm_opt_method_def_table, (st_data_t)me->def, (st_data_t)bop);
st_insert(vm_opt_mid_table, (st_data_t)mid, (st_data_t)Qtrue);
}
static void
add_opt_method(VALUE klass, ID mid, enum ruby_basic_operators bop)
{
const rb_method_entry_t *me = rb_method_entry_at(klass, mid);
if (me && vm_redefinition_check_method_type(me)) {
st_insert(vm_opt_method_def_table, (st_data_t)me->def, (st_data_t)bop);
st_insert(vm_opt_mid_table, (st_data_t)mid, (st_data_t)Qtrue);
add_opt_method_entry_bop(me, mid, bop);
}
else {
rb_bug("undefined optimized method: %s", rb_id2name(mid));
}
}
static enum ruby_basic_operators vm_redefinition_bop_for_id(ID mid);
static void
add_opt_method_entry(const rb_method_entry_t *me)
{
if (me && vm_redefinition_check_method_type(me)) {
ID mid = me->called_id;
enum ruby_basic_operators bop = vm_redefinition_bop_for_id(mid);
if ((int)bop >= 0) {
add_opt_method_entry_bop(me, mid, bop);
}
}
}
static void
vm_init_redefined_flag(void)
{
ID mid;
VALUE bop;
vm_opt_method_def_table = st_init_numtable();
vm_opt_mid_table = st_init_numtable();
enum ruby_basic_operators bop;
#define OP(mid_, bop_) (mid = id##mid_, bop = BOP_##bop_, ruby_vm_redefined_flag[bop] = 0)
#define C(k) add_opt_method(rb_c##k, mid, bop)
@ -2213,6 +2234,46 @@ vm_init_redefined_flag(void)
#undef OP
}
static enum ruby_basic_operators
vm_redefinition_bop_for_id(ID mid)
{
switch (mid) {
#define OP(mid_, bop_) case id##mid_: return BOP_##bop_
OP(PLUS, PLUS);
OP(MINUS, MINUS);
OP(MULT, MULT);
OP(DIV, DIV);
OP(MOD, MOD);
OP(Eq, EQ);
OP(Eqq, EQQ);
OP(LT, LT);
OP(LE, LE);
OP(GT, GT);
OP(GE, GE);
OP(LTLT, LTLT);
OP(AREF, AREF);
OP(ASET, ASET);
OP(Length, LENGTH);
OP(Size, SIZE);
OP(EmptyP, EMPTY_P);
OP(Succ, SUCC);
OP(EqTilde, MATCH);
OP(Freeze, FREEZE);
OP(UMinus, UMINUS);
OP(Max, MAX);
OP(Min, MIN);
OP(Hash, HASH);
OP(Call, CALL);
OP(And, AND);
OP(Or, OR);
OP(NilP, NIL_P);
OP(Cmp, CMP);
OP(Default, DEFAULT);
#undef OP
}
return -1;
}
/* for vm development */
#if VMDEBUG
@ -4213,6 +4274,9 @@ Init_BareVM(void)
rb_native_mutex_initialize(&vm->ractor.sync.lock);
rb_native_cond_initialize(&vm->ractor.sync.terminate_cond);
vm_opt_method_def_table = st_init_numtable();
vm_opt_mid_table = st_init_numtable();
#ifdef RUBY_THREAD_WIN32_H
rb_native_cond_initialize(&vm->ractor.sync.barrier_cond);
#endif

View File

@ -522,6 +522,8 @@ rb_method_definition_set(const rb_method_entry_t *me, rb_method_definition_t *de
rb_method_definition_release(me->def);
*(rb_method_definition_t **)&me->def = method_definition_addref(def, METHOD_ENTRY_COMPLEMENTED(me));
if (!ruby_running) add_opt_method_entry(me);
if (opts != NULL) {
switch (def->type) {
case VM_METHOD_TYPE_ISEQ: