summaryrefslogtreecommitdiff
path: root/variable.c
diff options
context:
space:
mode:
authornormal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2015-05-30 00:20:15 (GMT)
committernormal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2015-05-30 00:20:15 (GMT)
commitf6cd582505429fa95a4cf697507d8f39959f48d1 (patch)
treef4d574df20393cb170fa9cd37c0b4160d3246f73 /variable.c
parentc7ddf9d5165ff3fd739f1b3f54837899c185a0be (diff)
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
Diffstat (limited to 'variable.c')
-rw-r--r--variable.c63
1 files changed, 63 insertions, 0 deletions
diff --git a/variable.c b/variable.c
index 0efabbd..a5f6579 100644
--- a/variable.c
+++ b/variable.c
@@ -1013,6 +1013,27 @@ rb_generic_ivar_table(VALUE obj)
}
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)
{
struct gen_ivtbl *ivtbl;
@@ -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)
{