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:
parent
4dd0652561
commit
87a120fbdc
9 changed files with 96 additions and 30 deletions
19
ChangeLog
19
ChangeLog
|
@ -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
35
class.c
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
6
method.h
6
method.h
|
@ -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,
|
||||
|
|
2
object.c
2
object.c
|
@ -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;
|
||||
}
|
||||
|
|
36
variable.c
36
variable.c
|
@ -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;
|
||||
}
|
||||
|
|
15
vm_method.c
15
vm_method.c
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue