From f6cd582505429fa95a4cf697507d8f39959f48d1 Mon Sep 17 00:00:00 2001 From: normal Date: Sat, 30 May 2015 00:20:15 +0000 Subject: variable.c: avoid compatibility table with generic ivars This recovers and improves performance of Marshal.dump/load on Time objects compared to when we implemented generic ivars entirely using st_table. This also recovers some performance on other generic ivar objects, but does not bring bring Marshal.dump/load performance up to previous speeds. benchmark results: minimum results in each 10 measurements. Execution time (sec) name trunk geniv after marshal_dump_flo 0.343 0.334 0.335 marshal_dump_load_geniv 0.487 0.527 0.495 marshal_dump_load_time 1.262 1.401 1.257 Speedup ratio: compare with the result of `trunk' (greater is better) name geniv after marshal_dump_flo 1.026 1.023 marshal_dump_load_geniv 0.925 0.985 marshal_dump_load_time 0.901 1.004 * include/ruby/intern.h (rb_generic_ivar_table): deprecate * internal.h (rb_attr_delete): declare * marshal.c (has_ivars): use rb_ivar_foreach (w_ivar): ditto (w_object): update for new interface * time.c (time_mload): use rb_attr_delete * variable.c (generic_ivar_delete): implement (rb_ivar_delete): ditto (rb_attr_delete): ditto [ruby-core:69323] [Feature #11170] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@50680 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- variable.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) (limited to 'variable.c') diff --git a/variable.c b/variable.c index 0efabbdad9..a5f6579b37 100644 --- a/variable.c +++ b/variable.c @@ -1012,6 +1012,27 @@ rb_generic_ivar_table(VALUE obj) return a.tbl; } +static VALUE +generic_ivar_delete(VALUE obj, ID id, VALUE undef) +{ + struct gen_ivtbl *ivtbl; + + if (gen_ivtbl_get(obj, &ivtbl)) { + st_table *iv_index_tbl = RCLASS_IV_INDEX_TBL(rb_obj_class(obj)); + st_data_t index; + + if (st_lookup(iv_index_tbl, (st_data_t)id, &index)) { + if ((long)index < ivtbl->numiv) { + VALUE ret = ivtbl->ivptr[index]; + + ivtbl->ivptr[index] = Qundef; + return ret == Qundef ? undef : ret; + } + } + } + return undef; +} + static VALUE generic_ivar_get(VALUE obj, ID id, VALUE undef) { @@ -1274,6 +1295,48 @@ rb_attr_get(VALUE obj, ID id) return rb_ivar_lookup(obj, id, Qnil); } +static VALUE +rb_ivar_delete(VALUE obj, ID id, VALUE undef) +{ + VALUE val, *ptr; + struct st_table *iv_index_tbl; + long len; + st_data_t index; + + if (SPECIAL_CONST_P(obj)) goto generic; + switch (BUILTIN_TYPE(obj)) { + case T_OBJECT: + len = ROBJECT_NUMIV(obj); + ptr = ROBJECT_IVPTR(obj); + iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj); + if (!iv_index_tbl) break; + if (!st_lookup(iv_index_tbl, (st_data_t)id, &index)) break; + if (len <= (long)index) break; + val = ptr[index]; + ptr[index] = Qundef; + if (val != Qundef) + return val; + break; + case T_CLASS: + case T_MODULE: + if (RCLASS_IV_TBL(obj) && st_delete(RCLASS_IV_TBL(obj), (st_data_t *)&id, &index)) + return (VALUE)index; + break; + default: + generic: + if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj)) + return generic_ivar_delete(obj, id, undef); + break; + } + return undef; +} + +VALUE +rb_attr_delete(VALUE obj, ID id) +{ + return rb_ivar_delete(obj, id, Qnil); +} + static st_table * iv_index_tbl_make(VALUE obj) { -- cgit v1.2.3