diff options
| author | dearblue <[email protected]> | 2021-04-04 15:44:19 +0900 |
|---|---|---|
| committer | dearblue <[email protected]> | 2021-04-04 15:44:19 +0900 |
| commit | caeacea86ea1bb76dfc709359031a44f7528cb3a (patch) | |
| tree | 538d68ee91676e60df410de94197c151c457190e /src | |
| parent | fb8e12f37c86cfbdc6a8c4fa3b327bae24a8ce27 (diff) | |
| download | mruby-caeacea86ea1bb76dfc709359031a44f7528cb3a.tar.gz mruby-caeacea86ea1bb76dfc709359031a44f7528cb3a.zip | |
Making a proc object static for a method with static irep
The following methods will be made static.
- `Class#new`
- `Proc#call`
- `Kernel#catch`
Previously, static const RProc could not be registered as a method, but this has been changed to allow it.
Diffstat (limited to 'src')
| -rw-r--r-- | src/class.c | 27 | ||||
| -rw-r--r-- | src/proc.c | 19 |
2 files changed, 33 insertions, 13 deletions
diff --git a/src/class.c b/src/class.c index 09e52d24a..33a65f7d6 100644 --- a/src/class.c +++ b/src/class.c @@ -736,11 +736,17 @@ mrb_define_method_raw(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_method_ ptr.proc = p; if (p) { - p->flags |= MRB_PROC_SCOPE; - p->c = NULL; - mrb_field_write_barrier(mrb, (struct RBasic*)c, (struct RBasic*)p); - if (!MRB_PROC_ENV_P(p)) { - MRB_PROC_SET_TARGET_CLASS(p, c); + if (p->color != 7 /* GC_RED */) { + p->flags |= MRB_PROC_SCOPE; + p->c = NULL; + mrb_field_write_barrier(mrb, (struct RBasic*)c, (struct RBasic*)p); + if (!MRB_PROC_ENV_P(p)) { + MRB_PROC_SET_TARGET_CLASS(p, c); + } + } + else { + mrb_assert(MRB_FROZEN_P(p) && MRB_PROC_SCOPE_P(p)); + mrb_assert(p->c == NULL && p->upper == NULL && p->e.target_class == NULL); } } } @@ -2199,7 +2205,7 @@ mrb_alias_method(mrb_state *mrb, struct RClass *c, mrb_sym a, mrb_sym b) if (MRB_PROC_ENV_P(p)) { MRB_PROC_ENV(p)->mid = b; } - else { + else if (p->color != 7 /* GC_RED */) { struct RClass *tc = MRB_PROC_TARGET_CLASS(p); struct REnv *e = (struct REnv*)mrb_obj_alloc(mrb, MRB_TT_ENV, NULL); @@ -2812,15 +2818,18 @@ static const mrb_irep new_irep = { sizeof(new_iseq), 0, 2, 0, 0, }; +static const struct RProc new_proc = { + NULL, NULL, MRB_TT_PROC, 7 /* GC_RED */, MRB_FL_OBJ_IS_FROZEN | MRB_PROC_SCOPE | MRB_PROC_STRICT, + { &new_irep }, NULL, { NULL } +}; + static void init_class_new(mrb_state *mrb, struct RClass *cls) { - struct RProc *p; mrb_method_t m; MRB_PRESYM_INIT_SYMBOLS(mrb, new_syms); - p = mrb_proc_new(mrb, &new_irep); - MRB_METHOD_FROM_PROC(m, p); + MRB_METHOD_FROM_PROC(m, &new_proc); mrb_define_method_raw(mrb, cls, MRB_SYM(new), m); } diff --git a/src/proc.c b/src/proc.c index 4a202525c..5419ac002 100644 --- a/src/proc.c +++ b/src/proc.c @@ -35,6 +35,11 @@ static const mrb_irep call_irep = { 0, /* refcnt */ }; +static const struct RProc call_proc = { + NULL, NULL, MRB_TT_PROC, 7 /* GC_RED */, MRB_FL_OBJ_IS_FROZEN | MRB_PROC_SCOPE | MRB_PROC_STRICT, + { &call_irep }, NULL, { NULL } +}; + struct RProc* mrb_proc_new(mrb_state *mrb, const mrb_irep *irep) { @@ -46,7 +51,15 @@ mrb_proc_new(mrb_state *mrb, const mrb_irep *irep) struct RClass *tc = NULL; if (ci->proc) { - tc = MRB_PROC_TARGET_CLASS(ci->proc); + if (ci->proc->color != 7 /* GC_RED */) { + tc = MRB_PROC_TARGET_CLASS(ci->proc); + } + else { + tc = mrb_vm_ci_target_class(ci); + if (tc && tc->tt == MRB_TT_ICLASS) { + tc = tc->c; + } + } } if (tc == NULL) { tc = mrb_vm_ci_target_class(ci); @@ -413,15 +426,13 @@ mrb_proc_merge_lvar(mrb_state *mrb, mrb_irep *irep, struct REnv *env, int num, c void mrb_init_proc(mrb_state *mrb) { - struct RProc *p; mrb_method_t m; mrb_define_class_method(mrb, mrb->proc_class, "new", mrb_proc_s_new, MRB_ARGS_NONE()|MRB_ARGS_BLOCK()); mrb_define_method(mrb, mrb->proc_class, "initialize_copy", mrb_proc_init_copy, MRB_ARGS_REQ(1)); mrb_define_method(mrb, mrb->proc_class, "arity", proc_arity, MRB_ARGS_NONE()); - p = mrb_proc_new(mrb, &call_irep); - MRB_METHOD_FROM_PROC(m, p); + MRB_METHOD_FROM_PROC(m, &call_proc); mrb_define_method_raw(mrb, mrb->proc_class, MRB_SYM(call), m); mrb_define_method_raw(mrb, mrb->proc_class, MRB_OPSYM(aref), m); |
