ruby-changes:29247
From: ko1 <ko1@a...>
Date: Fri, 14 Jun 2013 18:24:34 +0900 (JST)
Subject: [ruby-changes:29247] ko1:r41299 (trunk): * class.c, include/ruby/ruby.h: add write barriers for T_CLASS,
ko1 2013-06-14 18:23:54 +0900 (Fri, 14 Jun 2013) New Revision: 41299 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=41299 Log: * class.c, include/ruby/ruby.h: add write barriers for T_CLASS, T_MODULE, T_ICLASS. * constant.h: constify rb_const_entry_t::value and file to detect assignment. * variable.c, internal.h (rb_st_insert_id_and_value, rb_st_copy): added. update table with write barrier. * method.h: constify some variables to detect assignment. * object.c (init_copy): add WBs. * variable.c: ditto. * vm_method.c (rb_add_method): ditto. Modified files: trunk/ChangeLog trunk/class.c trunk/constant.h trunk/include/ruby/ruby.h trunk/internal.h trunk/method.h trunk/object.c trunk/variable.c trunk/vm_method.c Index: method.h =================================================================== --- method.h (revision 41298) +++ method.h (revision 41299) @@ -68,7 +68,7 @@ typedef struct rb_method_cfunc_struct { https://github.com/ruby/ruby/blob/trunk/method.h#L68 typedef struct rb_method_attr_struct { ID id; - VALUE location; + const VALUE location; } rb_method_attr_t; typedef struct rb_iseq_struct rb_iseq_t; @@ -77,10 +77,10 @@ typedef struct rb_method_definition_stru https://github.com/ruby/ruby/blob/trunk/method.h#L77 rb_method_type_t type; /* method type */ ID original_id; union { - rb_iseq_t *iseq; /* should be mark */ + rb_iseq_t * const iseq; /* should be mark */ rb_method_cfunc_t cfunc; rb_method_attr_t attr; - VALUE proc; /* should be mark */ + const VALUE proc; /* should be mark */ enum method_optimized_type { OPTIMIZED_METHOD_TYPE_SEND, OPTIMIZED_METHOD_TYPE_CALL, Index: include/ruby/ruby.h =================================================================== --- include/ruby/ruby.h (revision 41298) +++ include/ruby/ruby.h (revision 41299) @@ -700,17 +700,18 @@ VALUE rb_obj_setup(VALUE obj, VALUE klas https://github.com/ruby/ruby/blob/trunk/include/ruby/ruby.h#L700 #ifndef RGENGC_WB_PROTECTED_ARRAY #define RGENGC_WB_PROTECTED_ARRAY 1 #endif - #ifndef RGENGC_WB_PROTECTED_HASH #define RGENGC_WB_PROTECTED_HASH 1 #endif - #ifndef RGENGC_WB_PROTECTED_STRING #define RGENGC_WB_PROTECTED_STRING 1 #endif #ifndef RGENGC_WB_PROTECTED_OBJECT #define RGENGC_WB_PROTECTED_OBJECT 1 #endif +#ifndef RGENGC_WB_PROTECTED_CLASS +#define RGENGC_WB_PROTECTED_CLASS 1 +#endif #ifndef RGENGC_WB_PROTECTED_FLOAT #define RGENGC_WB_PROTECTED_FLOAT 1 #endif @@ -1228,6 +1229,7 @@ struct RBignum { https://github.com/ruby/ruby/blob/trunk/include/ruby/ruby.h#L1229 #define OBJ_PROMOTED(x) (SPECIAL_CONST_P(x) ? 0 : FL_TEST_RAW((x), FL_OLDGEN)) #define OBJ_WB_PROTECTED(x) (SPECIAL_CONST_P(x) ? 1 : FL_TEST_RAW((x), FL_WB_PROTECTED)) #define OBJ_WB_GIVEUP(x) rb_obj_wb_giveup(x, __FILE__, __LINE__) +#define OBJ_WB_ void rb_gc_writebarrier(VALUE a, VALUE b); void rb_gc_giveup_promoted_writebarrier(VALUE obj); Index: ChangeLog =================================================================== --- ChangeLog (revision 41298) +++ ChangeLog (revision 41299) @@ -1,3 +1,22 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Fri Jun 14 18:18:07 2013 Koichi Sasada <ko1@a...> + + * class.c, include/ruby/ruby.h: add write barriers for T_CLASS, + T_MODULE, T_ICLASS. + + * constant.h: constify rb_const_entry_t::value and file to detect + assignment. + + * variable.c, internal.h (rb_st_insert_id_and_value, rb_st_copy): + added. update table with write barrier. + + * method.h: constify some variables to detect assignment. + + * object.c (init_copy): add WBs. + + * variable.c: ditto. + + * vm_method.c (rb_add_method): ditto. + Fri Jun 14 14:33:47 2013 Shugo Maeda <shugo@r...> * NEWS: add a note for Module#using. Index: variable.c =================================================================== --- variable.c (revision 41298) +++ variable.c (revision 41299) @@ -143,7 +143,8 @@ find_class_path(VALUE klass, ID preferre https://github.com/ruby/ruby/blob/trunk/variable.c#L143 if (!RCLASS_IV_TBL(klass)) { RCLASS_IV_TBL(klass) = st_init_numtable(); } - st_insert(RCLASS_IV_TBL(klass), (st_data_t)classpath, arg.path); + rb_st_insert_id_and_value(klass, RCLASS_IV_TBL(klass), (st_data_t)classpath, arg.path); + st_delete(RCLASS_IV_TBL(klass), &tmp, 0); return arg.path; } @@ -1184,8 +1185,7 @@ rb_ivar_set(VALUE obj, ID id, VALUE val) https://github.com/ruby/ruby/blob/trunk/variable.c#L1185 case T_CLASS: case T_MODULE: if (!RCLASS_IV_TBL(obj)) RCLASS_IV_TBL(obj) = st_init_numtable(); - st_insert(RCLASS_IV_TBL(obj), (st_data_t)id, val); - OBJ_WRITTEN(obj, Qundef, val); + rb_st_insert_id_and_value(obj, RCLASS_IV_TBL(obj), (st_data_t)id, val); break; default: generic: @@ -2180,8 +2180,8 @@ rb_const_set(VALUE klass, ID id, VALUE v https://github.com/ruby/ruby/blob/trunk/variable.c#L2180 ce = ALLOC(rb_const_entry_t); ce->flag = visibility; - ce->value = val; - ce->file = rb_sourcefilename(); + OBJ_WRITE(klass, (VALUE *)&ce->value, val); + OBJ_WRITE(klass, (VALUE *)&ce->file, rb_sourcefilename()); ce->line = rb_sourceline(); st_insert(RCLASS_CONST_TBL(klass), (st_data_t)id, (st_data_t)ce); @@ -2339,7 +2339,7 @@ rb_cvar_set(VALUE klass, ID id, VALUE va https://github.com/ruby/ruby/blob/trunk/variable.c#L2339 RCLASS_IV_TBL(target) = st_init_numtable(); } - st_insert(RCLASS_IV_TBL(target), (st_data_t)id, (st_data_t)val); + rb_st_insert_id_and_value(target, RCLASS_IV_TBL(target), (st_data_t)id, (st_data_t)val); } VALUE @@ -2576,3 +2576,27 @@ rb_iv_set(VALUE obj, const char *name, V https://github.com/ruby/ruby/blob/trunk/variable.c#L2576 return rb_ivar_set(obj, id, val); } + +/* tbl = xx(obj); tbl[key] = value; */ +int +rb_st_insert_id_and_value(VALUE obj, st_table *tbl, ID key, VALUE value) +{ + int result = st_insert(tbl, (st_data_t)key, (st_data_t)value); + OBJ_WRITTEN(obj, Qundef, value); + return result; +} + +static int +tbl_copy_i(st_data_t key, st_data_t value, st_data_t data) +{ + OBJ_WRITTEN((VALUE)data, Qundef, (VALUE)value); + return ST_CONTINUE; +} + +st_table * +rb_st_copy(VALUE obj, struct st_table *orig_tbl) +{ + st_table *new_tbl = st_copy(orig_tbl); + st_foreach(new_tbl, tbl_copy_i, (st_data_t)obj); + return new_tbl; +} Index: object.c =================================================================== --- object.c (revision 41298) +++ object.c (revision 41299) @@ -295,7 +295,7 @@ init_copy(VALUE dest, VALUE obj) https://github.com/ruby/ruby/blob/trunk/object.c#L295 RCLASS_CONST_TBL(dest) = 0; } if (RCLASS_IV_TBL(obj)) { - RCLASS_IV_TBL(dest) = st_copy(RCLASS_IV_TBL(obj)); + RCLASS_IV_TBL(dest) = rb_st_copy(dest, RCLASS_IV_TBL(obj)); } break; } Index: vm_method.c =================================================================== --- vm_method.c (revision 41298) +++ vm_method.c (revision 41299) @@ -411,9 +411,12 @@ rb_add_method(VALUE klass, ID mid, rb_me https://github.com/ruby/ruby/blob/trunk/vm_method.c#L411 def->original_id = mid; def->alias_count = 0; switch (type) { - case VM_METHOD_TYPE_ISEQ: - def->body.iseq = (rb_iseq_t *)opts; - break; + case VM_METHOD_TYPE_ISEQ: { + rb_iseq_t *iseq = (rb_iseq_t *)opts; + *(rb_iseq_t **)&def->body.iseq = iseq; + OBJ_WRITTEN(klass, Qundef, iseq->self); + break; + } case VM_METHOD_TYPE_CFUNC: { rb_method_cfunc_t *cfunc = (rb_method_cfunc_t *)opts; @@ -423,16 +426,16 @@ rb_add_method(VALUE klass, ID mid, rb_me https://github.com/ruby/ruby/blob/trunk/vm_method.c#L426 case VM_METHOD_TYPE_ATTRSET: case VM_METHOD_TYPE_IVAR: def->body.attr.id = (ID)opts; - def->body.attr.location = Qfalse; + OBJ_WRITE(klass, (VALUE *)&def->body.attr.location, Qfalse); th = GET_THREAD(); cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp); if (cfp && (line = rb_vm_get_sourceline(cfp))) { VALUE location = rb_ary_new3(2, cfp->iseq->location.path, INT2FIX(line)); - def->body.attr.location = rb_ary_freeze(location); + OBJ_WRITE(klass, (VALUE *)&def->body.attr.location, rb_ary_freeze(location)); } break; case VM_METHOD_TYPE_BMETHOD: - def->body.proc = (VALUE)opts; + OBJ_WRITE(klass, (VALUE *)&def->body.proc, (VALUE)opts); break; case VM_METHOD_TYPE_NOTIMPLEMENTED: setup_method_cfunc_struct(&def->body.cfunc, rb_f_notimplement, -1); Index: class.c =================================================================== --- class.c (revision 41298) +++ class.c (revision 41299) @@ -49,7 +49,7 @@ extern st_table *rb_class_tbl; https://github.com/ruby/ruby/blob/trunk/class.c#L49 static VALUE class_alloc(VALUE flags, VALUE klass) { - NEWOBJ_OF(obj, struct RClass, klass, flags); + NEWOBJ_OF(obj, struct RClass, klass, (flags & T_MASK) | (RGENGC_WB_PROTECTED_CLASS ? FL_WB_PROTECTED : 0)); obj->ptr = ALLOC(rb_classext_t); RCLASS_IV_TBL(obj) = 0; RCLASS_CONST_TBL(obj) = 0; @@ -162,19 +162,27 @@ clone_method_i(st_data_t key, st_data_t https://github.com/ruby/ruby/blob/trunk/class.c#L162 return ST_CONTINUE; } +struct clone_const_arg { + VALUE klass; + st_table *tbl; +}; + static int -clone_const(ID key, const rb_const_entry_t *ce, st_table *tbl) +clone_const(ID key, const rb_const_entry_t *ce, struct clone_const_arg *arg) { rb_const_entry_t *nce = ALLOC(rb_const_entry_t); - *nce = *ce; - st_insert(tbl, key, (st_data_t)nce); + MEMCPY(nce, ce, rb_const_entry_t, 1); + OBJ_WRITTEN(arg->klass, Qundef, ce->value); + OBJ_WRITTEN(arg->klass, Qundef, ce->file); + + st_insert(arg->tbl, key, (st_data_t)nce); return ST_CONTINUE; } static int clone_const_i(st_data_t key, st_data_t value, st_data_t data) { - return clone_const((ID)key, (const rb_const_entry_t *)value, (st_table *)data); + return clone_const((ID)key, (const rb_const_entry_t *)value, (struct clone_const_arg *)data); } static void @@ -211,7 +219,7 @@ rb_mod_init_copy(VALUE clone, VALUE orig https://github.com/ruby/ruby/blob/trunk/class.c#L219 if (RCLASS_IV_TBL(clone)) { st_free_table(RCLASS_IV_TBL(clone)); } - RCLASS_IV_TBL(clone) = st_copy(RCLASS_IV_TBL(orig)); + RCLASS_IV_TBL(clone) = rb_st_copy(clone, RCLASS_IV_TBL(orig)); CONST_ID(id, "__tmp_classpath__"); st_delete(RCLASS_IV_TBL(clone), &id, 0); CONST_ID(id, "__classpath__"); @@ -220,11 +228,14 @@ rb_mod_init_copy(VALUE clone, VALUE orig https://github.com/ruby/ruby/blob/trunk/class.c#L228 st_delete(RCLASS_IV_TBL(clone), &id, 0); } if (RCLASS_CONST_TBL(orig)) { + struct clone_const_arg arg; if (RCLASS_CONST_TBL(clone)) { rb_free_const_table(RCLASS_CONST_TBL(clone)); } RCLASS_CONST_TBL(clone) = st_init_numtable(); - st_foreach(RCLASS_CONST_TBL(orig), clone_const_i, (st_data_t)RCLASS_CONST_TBL(clone)); + arg.klass = clone; + arg.tbl = RCLASS_CONST_TBL(clone); + st_foreach(RCLASS_CONST_TBL(orig), clone_const_i, (st_data_t)&arg); } if (RCLASS_M_TBL(orig)) { if (RCLASS_M_TBL(clone)) { @@ -264,11 +275,14 @@ rb_singleton_class_clone_and_attach(VALU https://github.com/ruby/ruby/blob/trunk/class.c#L275 RCLASS_SET_SUPER(clone, RCLASS_SUPER(klass)); RCLASS_EXT(clone)->allocator = RCLASS_EXT(klass)->allocator; if (RCLASS_IV_TBL(klass)) { - RCLASS_IV_TBL(clone) = st_copy(RCLASS_IV_TBL(klass)); + RCLASS_IV_TBL(clone) = rb_st_copy(clone, RCLASS_IV_TBL(klass)); } if (RCLASS_CONST_TBL(klass)) { + struct clone_const_arg arg; RCLASS_CONST_TBL(clone) = st_init_numtable(); - st_foreach(RCLASS_CONST_TBL(klass), clone_const_i, (st_data_t)RCLASS_CONST_TBL(clone)); + arg.klass = clone; + arg.tbl = RCLASS_CONST_TBL(clone); + st_foreach(RCLASS_CONST_TBL(klass), clone_const_i, (st_data_t)&arg); } if (attach != Qundef) { rb_singleton_class_attached(clone, attach); @@ -277,6 +291,7 @@ rb_singleton_class_clone_and_attach(VALU https://github.com/ruby/ruby/blob/trunk/class.c#L291 st_foreach(RCLASS_M_TBL(klass), clone_method_i, (st_data_t)clone); rb_singleton_class_attached(RBASIC(clone)->klass, clone); FL_SET(clone, FL_SINGLETON); + return clone; } } @@ -292,7 +307,7 @@ rb_singleton_class_attached(VALUE klass, https://github.com/ruby/ruby/blob/trunk/class.c#L307 if (!RCLASS_IV_TBL(klass)) { RCLASS_IV_TBL(klass) = st_init_numtable(); } - st_insert(RCLASS_IV_TBL(klass), id_attached, obj); + rb_st_insert_id_and_value(klass, RCLASS_IV_TBL(klass), id_attached, obj); } } Index: internal.h =================================================================== --- internal.h (revision 41298) +++ internal.h (revision 41299) @@ -473,6 +473,9 @@ void rb_gc_mark_global_tbl(void); https://github.com/ruby/ruby/blob/trunk/internal.h#L473 void rb_mark_generic_ivar(VALUE); void rb_mark_generic_ivar_tbl(void); +int rb_st_insert_id_and_value(VALUE obj, st_table *tbl, ID key, VALUE value); +st_table *rb_st_copy(VALUE obj, struct st_table *orig_tbl); + /* gc.c */ size_t rb_gc_count(); Index: constant.h =================================================================== --- constant.h (revision 41298) +++ constant.h (revision 41299) @@ -18,8 +18,8 @@ typedef enum { https://github.com/ruby/ruby/blob/trunk/constant.h#L18 typedef struct rb_const_entry_struct { rb_const_flag_t flag; - VALUE value; /* should be mark */ - VALUE file; + const VALUE value; /* should be mark */ + const VALUE file; /* should be mark */ int line; } rb_const_entry_t; -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/