From d0a5e2df608d6b0a074c389913bf5487b9700be8 Mon Sep 17 00:00:00 2001 From: Yusuke Endoh Date: Fri, 17 Sep 2010 22:54:16 +0900 Subject: [PATCH 2/3] use rb_constant_entry_t as entry of RCLASS_CONST_TBL RCLASS_CONST_TBL contained the value of constant directly. Now instead rb_const_entry_t is contained in RCLASS_CONST_TBL, rb_const_entry_t is managed by malloc, and have not only the value itself but also visibility flag. --- class.c | 18 ++++++++++++++---- gc.c | 37 +++++++++++++++++++++++++++++++++++-- method.h | 1 + object.c | 3 ++- variable.c | 40 +++++++++++++++++++++++++++++----------- vm_insnhelper.c | 5 ++++- 6 files changed, 85 insertions(+), 19 deletions(-) diff --git a/class.c b/class.c index 5225ffa..e1b0d02 100644 --- a/class.c +++ b/class.c @@ -26,6 +26,7 @@ #include "ruby/ruby.h" #include "ruby/st.h" #include "method.h" +#include "constant.h" #include "vm_core.h" #include @@ -140,6 +141,14 @@ clone_method(ID mid, const rb_method_entry_t *me, struct clone_method_data *data return ST_CONTINUE; } +static int +clone_const(ID key, const rb_const_entry_t *ce, st_table *tbl) +{ + rb_const_entry_t *nce = ALLOC(rb_const_entry_t); + *nce = *ce; + st_insert(tbl, key, (st_data_t)nce); +} + /* :nodoc: */ VALUE rb_mod_init_copy(VALUE clone, VALUE orig) @@ -164,15 +173,15 @@ rb_mod_init_copy(VALUE clone, VALUE orig) } if (RCLASS_CONST_TBL(orig)) { if (RCLASS_CONST_TBL(clone)) { - st_free_table(RCLASS_CONST_TBL(clone)); + rb_free_const_table(RCLASS_CONST_TBL(clone)); } - RCLASS_CONST_TBL(clone) = st_copy(RCLASS_CONST_TBL(orig)); + RCLASS_CONST_TBL(clone) = st_init_numtable(); + st_foreach(RCLASS_CONST_TBL(orig), clone_const, (st_data_t)RCLASS_CONST_TBL(clone)); } if (RCLASS_M_TBL(orig)) { struct clone_method_data data; if (RCLASS_M_TBL(clone)) { - extern void rb_free_m_table(st_table *tbl); rb_free_m_table(RCLASS_M_TBL(clone)); } data.tbl = RCLASS_M_TBL(clone) = st_init_numtable(); @@ -224,7 +233,8 @@ rb_singleton_class_clone(VALUE obj) RCLASS_IV_TBL(clone) = st_copy(RCLASS_IV_TBL(klass)); } if (RCLASS_CONST_TBL(klass)) { - RCLASS_CONST_TBL(clone) = st_copy(RCLASS_CONST_TBL(klass)); + RCLASS_CONST_TBL(clone) = st_init_numtable(); + st_foreach(RCLASS_CONST_TBL(klass), clone_const, (st_data_t)RCLASS_CONST_TBL(clone)); } RCLASS_M_TBL(clone) = st_init_numtable(); data.tbl = RCLASS_M_TBL(clone); diff --git a/gc.c b/gc.c index ee5b256..85bb696 100644 --- a/gc.c +++ b/gc.c @@ -19,6 +19,7 @@ #include "eval_intern.h" #include "vm_core.h" #include "gc.h" +#include "constant.h" #include #include #include @@ -1503,6 +1504,38 @@ rb_free_m_table(st_table *tbl) st_free_table(tbl); } +static int +mark_const_entry_i(ID key, const rb_const_entry_t *ce, st_data_t data) +{ + struct mark_tbl_arg *arg = (void*)data; + gc_mark(arg->objspace, ce->value, arg->lev); + return ST_CONTINUE; +} + +static void +mark_const_tbl(rb_objspace_t *objspace, st_table *tbl, int lev) +{ + struct mark_tbl_arg arg; + if (!tbl) return; + arg.objspace = objspace; + arg.lev = lev; + st_foreach(tbl, mark_const_entry_i, (st_data_t)&arg); +} + +static int +free_const_entry_i(ID key, rb_const_entry_t *ce, st_data_t data) +{ + xfree(ce); + return ST_CONTINUE; +} + +void +rb_free_const_table(st_table *tbl) +{ + st_foreach(tbl, free_const_entry_i, 0); + st_free_table(tbl); +} + void rb_mark_tbl(st_table *tbl) { @@ -1717,7 +1750,7 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr, int lev) case T_MODULE: mark_m_tbl(objspace, RCLASS_M_TBL(obj), lev); mark_tbl(objspace, RCLASS_IV_TBL(obj), lev); - mark_tbl(objspace, RCLASS_CONST_TBL(obj), lev); + mark_const_tbl(objspace, RCLASS_CONST_TBL(obj), lev); ptr = RCLASS_SUPER(obj); goto again; @@ -2166,7 +2199,7 @@ obj_free(rb_objspace_t *objspace, VALUE obj) st_free_table(RCLASS_IV_TBL(obj)); } if (RCLASS_CONST_TBL(obj)) { - st_free_table(RCLASS_CONST_TBL(obj)); + rb_free_const_table(RCLASS_CONST_TBL(obj)); } if (RCLASS_IV_INDEX_TBL(obj)) { st_free_table(RCLASS_IV_INDEX_TBL(obj)); diff --git a/method.h b/method.h index e03f0d2..3cfe438 100644 --- a/method.h +++ b/method.h @@ -99,5 +99,6 @@ int rb_method_entry_arity(const rb_method_entry_t *me); void rb_mark_method_entry(const rb_method_entry_t *me); void rb_free_method_entry(rb_method_entry_t *me); void rb_sweep_method_entry(void *vm); +void rb_free_m_table(st_table *tbl); #endif /* METHOD_H */ diff --git a/object.c b/object.c index b1bbeb2..2da4b94 100644 --- a/object.c +++ b/object.c @@ -19,6 +19,7 @@ #include #include #include +#include "constant.h" VALUE rb_cBasicObject; VALUE rb_mKernel; @@ -222,7 +223,7 @@ init_copy(VALUE dest, VALUE obj) RCLASS_IV_TBL(dest) = 0; } if (RCLASS_CONST_TBL(dest)) { - st_free_table(RCLASS_CONST_TBL(dest)); + rb_free_const_table(RCLASS_CONST_TBL(dest)); RCLASS_CONST_TBL(dest) = 0; } if (RCLASS_IV_TBL(obj)) { diff --git a/variable.c b/variable.c index ab62deb..fb960f7 100644 --- a/variable.c +++ b/variable.c @@ -16,6 +16,7 @@ #include "ruby/util.h" #include "ruby/encoding.h" #include "node.h" +#include "constant.h" void rb_vm_change_state(void); void rb_vm_inc_const_missing_count(void); @@ -71,8 +72,9 @@ fc_path(struct fc_result *fc, ID name) } static int -fc_i(ID key, VALUE value, struct fc_result *res) +fc_i(ID key, rb_const_entry_t *ce, struct fc_result *res) { + VALUE value = ce->value; if (!rb_is_const_id(key)) return ST_CONTINUE; if (value == res->klass) { @@ -1438,15 +1440,16 @@ rb_autoload(VALUE mod, ID id, const char *file) rb_raise(rb_eArgError, "empty file name"); } - if ((tbl = RCLASS_CONST_TBL(mod)) && st_lookup(tbl, (st_data_t)id, &av) && (VALUE)av != Qundef) + if ((tbl = RCLASS_CONST_TBL(mod)) && st_lookup(tbl, (st_data_t)id, &av) && ((rb_const_entry_t*)av)->value != Qundef) return; rb_const_set(mod, id, Qundef); tbl = RCLASS_IV_TBL(mod); - if (st_lookup(tbl, (st_data_t)autoload, &av)) { + if (tbl && st_lookup(tbl, (st_data_t)autoload, &av)) { tbl = check_autoload_table((VALUE)av); } else { + if (!tbl) tbl = RCLASS_IV_TBL(mod) = st_init_numtable(); av = (st_data_t)TypedData_Wrap_Struct(0, &autoload_data_type, 0); st_add_direct(tbl, (st_data_t)autoload, av); DATA_PTR(av) = tbl = st_init_numtable(); @@ -1461,8 +1464,11 @@ static NODE* autoload_delete(VALUE mod, ID id) { st_data_t val, load = 0, n = id; + rb_const_entry_t *ce; - st_delete(RCLASS_CONST_TBL(mod), &n, 0); + st_delete(RCLASS_CONST_TBL(mod), &n, &val); + ce = (rb_const_entry_t*)val; + if (ce) xfree(ce); if (st_lookup(RCLASS_IV_TBL(mod), (st_data_t)autoload, &val)) { struct st_table *tbl = check_autoload_table((VALUE)val); @@ -1471,6 +1477,8 @@ autoload_delete(VALUE mod, ID id) if (tbl->num_entries == 0) { n = autoload; st_delete(RCLASS_CONST_TBL(mod), &n, &val); + ce = (rb_const_entry_t*)val; + if (ce) xfree(ce); } } @@ -1530,7 +1538,7 @@ autoload_node_id(VALUE mod, ID id) struct st_table *tbl = RCLASS_CONST_TBL(mod); st_data_t val; - if (!tbl || !st_lookup(tbl, (st_data_t)id, &val) || (VALUE)val != Qundef) { + if (!tbl || !st_lookup(tbl, (st_data_t)id, &val) || ((rb_const_entry_t*)val)->value != Qundef) { return 0; } return 1; @@ -1568,6 +1576,7 @@ rb_autoload_p(VALUE mod, ID id) static VALUE rb_const_get_0(VALUE klass, ID id, int exclude, int recurse) { + st_data_t v; VALUE value, tmp; int mod_retry = 0; @@ -1575,7 +1584,8 @@ rb_const_get_0(VALUE klass, ID id, int exclude, int recurse) retry: while (RTEST(tmp)) { VALUE am = 0; - while (RCLASS_CONST_TBL(tmp) && st_lookup(RCLASS_CONST_TBL(tmp), (st_data_t)id, &value)) { + while (RCLASS_CONST_TBL(tmp) && st_lookup(RCLASS_CONST_TBL(tmp), (st_data_t)id, &v)) { + value = ((rb_const_entry_t*)v)->value; if (value == Qundef) { if (am == tmp) break; am = tmp; @@ -1661,16 +1671,17 @@ rb_const_remove(VALUE mod, ID id) rb_vm_change_state(); - val = (VALUE)v; + val = ((rb_const_entry_t*)v)->value; if (val == Qundef) { autoload_delete(mod, id); val = Qnil; } + xfree((rb_const_entry_t*)v); return val; } static int -sv_i(ID key, VALUE value, st_table *tbl) +sv_i(ID key, rb_const_entry_t *ce, st_table *tbl) { if (rb_is_const_id(key)) { if (!st_lookup(tbl, (st_data_t)key, 0)) { @@ -1774,7 +1785,7 @@ rb_const_defined_0(VALUE klass, ID id, int exclude, int recurse) retry: while (tmp) { if (RCLASS_CONST_TBL(tmp) && st_lookup(RCLASS_CONST_TBL(tmp), (st_data_t)id, &value)) { - if ((VALUE)value == Qundef && !autoload_node((VALUE)klass, id, 0)) + if (((rb_const_entry_t*)value)->value == Qundef && !autoload_node((VALUE)klass, id, 0)) return (int)Qfalse; return (int)Qtrue; } @@ -1825,6 +1836,8 @@ check_before_mod_set(VALUE klass, ID id, VALUE val, const char *dest) void rb_const_set(VALUE klass, ID id, VALUE val) { + rb_const_entry_t *ce; + if (NIL_P(klass)) { rb_raise(rb_eTypeError, "no class/module to define constant %s", rb_id2name(id)); @@ -1838,7 +1851,7 @@ rb_const_set(VALUE klass, ID id, VALUE val) st_data_t value; if (st_lookup(RCLASS_CONST_TBL(klass), (st_data_t)id, &value)) { - if ((VALUE)value == Qundef) + if (((rb_const_entry_t*)value)->value == Qundef) autoload_delete(klass, id); else rb_warn("already initialized constant %s", rb_id2name(id)); @@ -1846,7 +1859,12 @@ rb_const_set(VALUE klass, ID id, VALUE val) } rb_vm_change_state(); - st_insert(RCLASS_CONST_TBL(klass), (st_data_t)id, (st_data_t)val); + + ce = ALLOC(rb_const_entry_t); + ce->flag = CONST_PUBLIC; + ce->value = val; + + st_insert(RCLASS_CONST_TBL(klass), (st_data_t)id, (st_data_t)ce); } void diff --git a/vm_insnhelper.c b/vm_insnhelper.c index e6e8db2..3555351 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -11,6 +11,7 @@ /* finish iseq array */ #include "insns.inc" #include +#include "constant.h" /* control stack frame */ @@ -1166,10 +1167,12 @@ vm_get_ev_const(rb_thread_t *th, const rb_iseq_t *iseq, cref = cref->nd_next; if (!NIL_P(klass)) { + st_data_t v; VALUE am = 0; search_continue: if (RCLASS_CONST_TBL(klass) && - st_lookup(RCLASS_CONST_TBL(klass), id, &val)) { + st_lookup(RCLASS_CONST_TBL(klass), id, &v)) { + val = ((rb_const_entry_t*)v)->value; if (val == Qundef) { if (am == klass) break; am = klass; -- 1.7.2.1