summaryrefslogtreecommitdiffhomepage
path: root/src/kernel.c
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2017-09-04 06:51:31 +0900
committerYukihiro "Matz" Matsumoto <[email protected]>2017-09-04 06:51:31 +0900
commit3acaa44a70a44a816076dee65310f0f2487aeebd (patch)
treedb7b29708bd51a1521d2695d0debdf562101d99a /src/kernel.c
parent8a5d783f2ee5ddccdb2b8de2edf5dc6b5ba1c3fc (diff)
downloadmruby-3acaa44a70a44a816076dee65310f0f2487aeebd.tar.gz
mruby-3acaa44a70a44a816076dee65310f0f2487aeebd.zip
Restructure `irep->outer` chain; fix #3804
Instead of `irep -> proc` chain, we use `irep -> irep` chain to avoid GC bugs like #3804. We added `target_class` reference to `mrb_irep` struct. That means one more word consumption per `irep`.
Diffstat (limited to 'src/kernel.c')
-rw-r--r--src/kernel.c10
1 files changed, 4 insertions, 6 deletions
diff --git a/src/kernel.c b/src/kernel.c
index 9fcee2413..4e95ab24b 100644
--- a/src/kernel.c
+++ b/src/kernel.c
@@ -1151,8 +1151,8 @@ static mrb_value
mrb_local_variables(mrb_state *mrb, mrb_value self)
{
struct RProc *proc;
+ mrb_irep *irep;
mrb_value vars;
- struct mrb_irep *irep;
size_t i;
proc = mrb->c->ci[-1].proc;
@@ -1161,18 +1161,16 @@ mrb_local_variables(mrb_state *mrb, mrb_value self)
return mrb_ary_new(mrb);
}
vars = mrb_hash_new(mrb);
- while (proc) {
- if (MRB_PROC_CFUNC_P(proc)) break;
- irep = proc->body.irep;
+ irep = proc->body.irep;
+ while (irep) {
if (!irep->lv) break;
for (i = 0; i + 1 < irep->nlocals; ++i) {
if (irep->lv[i].name) {
mrb_hash_set(mrb, vars, mrb_symbol_value(irep->lv[i].name), mrb_true_value());
}
}
- if (MRB_PROC_CLASS_P(proc)) break;
if (!proc->env) break;
- proc = proc->body.irep->outer;
+ irep = irep->outer;
}
return mrb_hash_keys(mrb, vars);