1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

* 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.



git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@41299 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
ko1 2013-06-14 09:23:54 +00:00
parent 4dd0652561
commit 87a120fbdc
9 changed files with 96 additions and 30 deletions

View file

@ -1,3 +1,22 @@
Fri Jun 14 18:18:07 2013 Koichi Sasada <ko1@atdot.net>
* 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@ruby-lang.org>
* NEWS: add a note for Module#using.

35
class.c
View file

@ -49,7 +49,7 @@ extern st_table *rb_class_tbl;
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 value, st_data_t data)
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)
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)
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(VALUE obj, VALUE attach)
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(VALUE obj, VALUE attach)
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, VALUE obj)
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);
}
}

View file

@ -18,8 +18,8 @@ typedef enum {
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;

View file

@ -700,17 +700,18 @@ VALUE rb_obj_setup(VALUE obj, VALUE klass, VALUE type);
#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 {
#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);

View file

@ -473,6 +473,9 @@ void rb_gc_mark_global_tbl(void);
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();

View file

@ -68,7 +68,7 @@ typedef struct rb_method_cfunc_struct {
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_struct {
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,

View file

@ -295,7 +295,7 @@ init_copy(VALUE dest, VALUE obj)
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;
}

View file

@ -143,7 +143,8 @@ find_class_path(VALUE klass, ID preferred)
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)
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 val)
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 val)
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, VALUE val)
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;
}

View file

@ -411,9 +411,12 @@ rb_add_method(VALUE klass, ID mid, rb_method_type_t type, void *opts, rb_method_
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_method_type_t type, void *opts, rb_method_
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);