summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog19
-rw-r--r--class.c35
-rw-r--r--constant.h4
-rw-r--r--include/ruby/ruby.h6
-rw-r--r--internal.h3
-rw-r--r--method.h6
-rw-r--r--object.c2
-rw-r--r--variable.c36
-rw-r--r--vm_method.c15
9 files changed, 96 insertions, 30 deletions
diff --git a/ChangeLog b/ChangeLog
index d88f996..34bcd23 100644
--- a/ChangeLog
+++ b/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.
diff --git a/class.c b/class.c
index 8ab8d05..c72bd81 100644
--- a/class.c
+++ b/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);
}
}
diff --git a/constant.h b/constant.h
index 9354241..3dc9b8d 100644
--- a/constant.h
+++ b/constant.h
@@ -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;
diff --git a/include/ruby/ruby.h b/include/ruby/ruby.h
index 1891915..ac11850 100644
--- a/include/ruby/ruby.h
+++ b/include/ruby/ruby.h
@@ -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);
diff --git a/internal.h b/internal.h
index c6a895a..970c115 100644
--- a/internal.h
+++ b/internal.h
@@ -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();
diff --git a/method.h b/method.h
index e92fe3a..f02925e 100644
--- a/method.h
+++ b/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,
diff --git a/object.c b/object.c
index 683c893..d226dbf 100644
--- a/object.c
+++ b/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;
}
diff --git a/variable.c b/variable.c
index 8f21847..749d928 100644
--- a/variable.c
+++ b/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;
+}
diff --git a/vm_method.c b/vm_method.c
index 70fda7b..e4e8c01 100644
--- a/vm_method.c
+++ b/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);