ruby-changes:58032
From: =E5=8D=9C=E9=83=A8=E6=98=8C=E5=B9=B3 <ko1@a...>
Date: Mon, 30 Sep 2019 10:27:04 +0900 (JST)
Subject: [ruby-changes:58032] cf33608203 (master): refactor constify most of rb_method_definition_t
https://git.ruby-lang.org/ruby.git/commit/?id=cf33608203 From cf336082039ae84b5001908f6bb7e04bdda8893e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=9C=E9=83=A8=E6=98=8C=E5=B9=B3?= <shyouhei@r...> Date: Fri, 20 Sep 2019 14:12:51 +0900 Subject: refactor constify most of rb_method_definition_t Most (if not all) of the fields of rb_method_definition_t are never meant to be modified once after they are stored. Marking them const makes it possible for compilers to warn on unintended modifications. diff --git a/gc.c b/gc.c index c9f26cc..0caee4c 100644 --- a/gc.c +++ b/gc.c @@ -7831,7 +7831,7 @@ void rb_update_st_references(struct st_table *ht) https://github.com/ruby/ruby/blob/trunk/gc.c#L7831 static void gc_ref_update_method_entry(rb_objspace_t *objspace, rb_method_entry_t *me) { - rb_method_definition_t *def = me->def; + const rb_method_definition_t *def = me->def; UPDATE_IF_MOVED(objspace, me->owner); UPDATE_IF_MOVED(objspace, me->defined_class); diff --git a/method.h b/method.h index b26f678..1ce5d4c 100644 --- a/method.h +++ b/method.h @@ -122,32 +122,32 @@ typedef struct rb_iseq_struct rb_iseq_t; https://github.com/ruby/ruby/blob/trunk/method.h#L122 #endif typedef struct rb_method_iseq_struct { - rb_iseq_t * iseqptr; /*!< iseq pointer, should be separated from iseqval */ - rb_cref_t * cref; /*!< class reference, should be marked */ -} rb_method_iseq_t; /* check rb_add_method_iseq() when modify the fields */ + const rb_iseq_t *const iseqptr; /*!< iseq pointer, should be separated from iseqval */ + rb_cref_t *const cref; /*!< class reference, should be marked */ +} rb_method_iseq_t; typedef struct rb_method_cfunc_struct { - VALUE (*func)(ANYARGS); - VALUE (*invoker)(VALUE recv, int argc, const VALUE *argv, VALUE (*func)(ANYARGS)); - int argc; + VALUE (*const func)(ANYARGS); + VALUE (*const invoker)(VALUE recv, int argc, const VALUE *argv, VALUE (*func)(ANYARGS)); + const int argc; } rb_method_cfunc_t; typedef struct rb_method_attr_struct { - ID id; - VALUE location; /* should be marked */ + const ID id; + const VALUE location; /* should be marked */ } rb_method_attr_t; typedef struct rb_method_alias_struct { - struct rb_method_entry_struct * original_me; /* original_me->klass is original owner */ + const struct rb_method_entry_struct *const original_me; /* original_me->klass is original owner */ } rb_method_alias_t; typedef struct rb_method_refined_struct { - struct rb_method_entry_struct * orig_me; - VALUE owner; + const struct rb_method_entry_struct *const orig_me; + const VALUE owner; } rb_method_refined_t; typedef struct rb_method_bmethod_struct { - VALUE proc; /* should be marked */ + const VALUE proc; /* should be marked */ struct rb_hook_list_struct *hooks; } rb_method_bmethod_t; @@ -159,22 +159,22 @@ enum method_optimized_type { https://github.com/ruby/ruby/blob/trunk/method.h#L159 }; struct rb_method_definition_struct { - BITFIELD(rb_method_type_t, type, VM_METHOD_TYPE_MINIMUM_BITS); + BITFIELD(rb_method_type_t, const type, VM_METHOD_TYPE_MINIMUM_BITS); int alias_count : 28; int complemented_count : 28; union { - rb_method_iseq_t iseq; - rb_method_cfunc_t cfunc; - rb_method_attr_t attr; - rb_method_alias_t alias; - rb_method_refined_t refined; + const rb_method_iseq_t iseq; + const rb_method_cfunc_t cfunc; + const rb_method_attr_t attr; + const rb_method_alias_t alias; + const rb_method_refined_t refined; rb_method_bmethod_t bmethod; - enum method_optimized_type optimize_type; + const enum method_optimized_type optimize_type; } body; - ID original_id; + const ID original_id; }; typedef struct rb_method_definition_struct rb_method_definition_t; diff --git a/proc.c b/proc.c index 667b86a..496baa4 100644 --- a/proc.c +++ b/proc.c @@ -15,6 +15,8 @@ https://github.com/ruby/ruby/blob/trunk/proc.c#L15 #include "vm_core.h" #include "iseq.h" +extern const rb_method_definition_t *rb_method_definition_create(rb_method_type_t type, ID mid); + /* Proc.new with no block will raise an exception in the future * versions */ #define PROC_NEW_REQUIRES_BLOCK 0 @@ -1475,15 +1477,12 @@ mnew_missing(VALUE klass, VALUE obj, ID id, VALUE mclass) https://github.com/ruby/ruby/blob/trunk/proc.c#L1477 struct METHOD *data; VALUE method = TypedData_Make_Struct(mclass, struct METHOD, &method_data_type, data); rb_method_entry_t *me; - rb_method_definition_t *def; + const rb_method_definition_t *def; RB_OBJ_WRITE(method, &data->recv, obj); RB_OBJ_WRITE(method, &data->klass, klass); - def = ZALLOC(rb_method_definition_t); - def->type = VM_METHOD_TYPE_MISSING; - def->original_id = id; - + def = rb_method_definition_create(VM_METHOD_TYPE_MISSING, id); me = rb_method_entry_create(id, klass, METHOD_VISI_UNDEF, def); RB_OBJ_WRITE(method, &data->me, me); diff --git a/vm_core.h b/vm_core.h index 8eb1555..192165b 100644 --- a/vm_core.h +++ b/vm_core.h @@ -491,7 +491,7 @@ rb_iseq_check(const rb_iseq_t *iseq) https://github.com/ruby/ruby/blob/trunk/vm_core.h#L491 } static inline const rb_iseq_t * -def_iseq_ptr(rb_method_definition_t *def) +def_iseq_ptr(const rb_method_definition_t *def) { #if VM_CHECK_MODE > 0 if (def->type != VM_METHOD_TYPE_ISEQ) rb_bug("def_iseq_ptr: not iseq (%d)", def->type); diff --git a/vm_insnhelper.c b/vm_insnhelper.c index 54142b8..7db8630 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -19,7 +19,7 @@ https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L19 #include "ruby/config.h" #include "debug_counter.h" -extern rb_method_definition_t *rb_method_definition_create(rb_method_type_t type, ID mid); +extern const rb_method_definition_t *rb_method_definition_create(rb_method_type_t type, ID mid); extern void rb_method_definition_set(const rb_method_entry_t *me, rb_method_definition_t *def, void *opts); extern int rb_method_definition_eq(const rb_method_definition_t *d1, const rb_method_definition_t *d2); extern VALUE rb_make_no_method_exception(VALUE exc, VALUE format, VALUE obj, @@ -2589,9 +2589,9 @@ aliased_callable_method_entry(const rb_callable_method_entry_t *me) https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L2589 RB_OBJ_WRITE(me, &me->def->body.alias.original_me, cme); } else { - rb_method_definition_t *def = + const rb_method_definition_t *def = rb_method_definition_create(VM_METHOD_TYPE_ALIAS, me->def->original_id); - rb_method_definition_set((rb_method_entry_t *)me, def, (void *)cme); + rb_method_definition_set((rb_method_entry_t *)me, (void *)def, (void *)cme); } } else { diff --git a/vm_method.c b/vm_method.c index 241bb30..4abefd5 100644 --- a/vm_method.c +++ b/vm_method.c @@ -132,9 +132,7 @@ rb_add_method_cfunc(VALUE klass, ID mid, VALUE (*func)(ANYARGS), int argc, rb_me https://github.com/ruby/ruby/blob/trunk/vm_method.c#L132 { if (argc < -2 || 15 < argc) rb_raise(rb_eArgError, "arity out of range: %d for -2..15", argc); if (func != rb_f_notimplement) { - rb_method_cfunc_t opt; - opt.func = func; - opt.argc = argc; + rb_method_cfunc_t opt = { func, 0, argc, }; rb_add_method(klass, mid, VM_METHOD_TYPE_CFUNC, &opt, visi); } else { @@ -213,14 +211,6 @@ static VALUE https://github.com/ruby/ruby/blob/trunk/vm_method.c#L211 } } -static void -setup_method_cfunc_struct(rb_method_cfunc_t *cfunc, VALUE (*func)(), int argc) -{ - cfunc->func = func; - cfunc->argc = argc; - cfunc->invoker = call_cfunc_invoker_func(argc); -} - MJIT_FUNC_EXPORTED void rb_method_definition_set(const rb_method_entry_t *me, rb_method_definition_t *def, void *opts) { @@ -250,8 +240,13 @@ rb_method_definition_set(const rb_method_entry_t *me, rb_method_definition_t *de https://github.com/ruby/ruby/blob/trunk/vm_method.c#L240 } case VM_METHOD_TYPE_CFUNC: { - rb_method_cfunc_t *cfunc = (rb_method_cfunc_t *)opts; - setup_method_cfunc_struct(UNALIGNED_MEMBER_PTR(def, body.cfunc), cfunc->func, cfunc->argc); + const rb_method_cfunc_t *p = (const rb_method_cfunc_t *)opts; + rb_method_cfunc_t c = { + p->func, + call_cfunc_invoker_func(p->argc), + p->argc, + }; + memcpy((void *)&def->body.cfunc, &c, sizeof c); return; } case VM_METHOD_TYPE_ATTRSET: @@ -261,7 +256,7 @@ rb_method_definition_set(const rb_method_entry_t *me, rb_method_definition_t *de https://github.com/ruby/ruby/blob/trunk/vm_method.c#L256 rb_control_frame_t *cfp; int line; - def->body.attr.id = (ID)(VALUE)opts; + memcpy((void *)&def->body.attr, &(rb_method_attr_t) { (ID)(VALUE)opts }, sizeof(rb_method_attr_t)); cfp = rb_vm_get_ruby_level_next_cfp(ec, ec->cfp); @@ -275,14 +270,21 @@ rb_method_definition_set(const rb_method_entry_t *me, rb_method_definition_t *de https://github.com/ruby/ruby/blob/trunk/vm_method.c#L270 return; } case VM_METHOD_TYPE_BMETHOD: - RB_OBJ_WRITE(me, &def->body.bmethod.proc, (VALUE)opts); + memcpy((void *)&def->body.bmethod, &(rb_method_bmethod_t) { (VALUE)opts }, sizeof(rb_method_bmethod_t)); + RB_OBJ_WRITTEN(me, &def->body.bmethod.proc, (VALUE)opts); return; case VM_METHOD_TYPE_NOTIMPLEMENTED: - setup_method_cfunc_struct(UNALIGNED_MEMBER_PTR(def, body.cfunc), rb_f_notimplement, -1); - return; + { + rb_method_cfunc_t f = { rb_f_notimplement, call_cfunc_m1, -1, }; + memcpy((void *)&def->body.cfunc, &f, sizeof f); + return; + } case VM_METHOD_TYPE_OPTIMIZED: - def->body.optimize_type = (enum method_optimized_type)opts; - return; + { + enum method_optimized_type t = (enum method_optimized_type)opts; + memcpy((void *)&def->body (... truncated) -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/