summaryrefslogtreecommitdiff
path: root/variable.c
diff options
context:
space:
mode:
authorKoichi Sasada <ko1@cookpad.com>2019-01-16 10:48:30 +0000
committerKoichi Sasada <ko1@atdot.net>2019-07-31 09:44:23 +0900
commitebd398ac5a4147a1e652d6943c39a29a62f12e66 (patch)
tree79dba6622c591db987f0a9c065fe37cd09a58e98 /variable.c
parent4afd8975242917d319cfb20c7ed635b979ad48d5 (diff)
remove RHash::iter_lev.
iter_lev is used to detect the hash is iterating or not. Usually, iter_lev should be very small number (1 or 2) so `int` is overkill. This patch introduce iter_lev in flags (7 bits, FL13 to FL19) and if iter_lev exceeds this range, save it in hidden attribute. We can get 1 word in RHash. We can't modify frozen objects. Therefore I added new internal API `rb_ivar_set_internal()` which allows us to set an attribute even if the target object is frozen if the name is hidden ivar (the name without `@` prefix).
Diffstat (limited to 'variable.c')
-rw-r--r--variable.c25
1 files changed, 20 insertions, 5 deletions
diff --git a/variable.c b/variable.c
index 7d6905f390..b839f3067b 100644
--- a/variable.c
+++ b/variable.c
@@ -1340,16 +1340,15 @@ obj_ivar_set(VALUE obj, ID id, VALUE val)
return val;
}
-VALUE
-rb_ivar_set(VALUE obj, ID id, VALUE val)
+static void
+ivar_set(VALUE obj, ID id, VALUE val)
{
RB_DEBUG_COUNTER_INC(ivar_set_base);
- rb_check_frozen(obj);
-
switch (BUILTIN_TYPE(obj)) {
case T_OBJECT:
- return obj_ivar_set(obj, id, val);
+ obj_ivar_set(obj, id, val);
+ break;
case T_CLASS:
case T_MODULE:
if (!RCLASS_IV_TBL(obj)) RCLASS_IV_TBL(obj) = st_init_numtable();
@@ -1359,9 +1358,25 @@ rb_ivar_set(VALUE obj, ID id, VALUE val)
generic_ivar_set(obj, id, val);
break;
}
+}
+
+VALUE
+rb_ivar_set(VALUE obj, ID id, VALUE val)
+{
+ rb_check_frozen(obj);
+ ivar_set(obj, id, val);
return val;
}
+void
+rb_ivar_set_internal(VALUE obj, ID id, VALUE val)
+{
+ // should be internal instance variable name (no @ prefix)
+ VM_ASSERT(!rb_is_instance_id(id));
+
+ ivar_set(obj, id, val);
+}
+
VALUE
rb_ivar_defined(VALUE obj, ID id)
{