summaryrefslogtreecommitdiff
path: root/vm.c
diff options
context:
space:
mode:
Diffstat (limited to 'vm.c')
-rw-r--r--vm.c56
1 files changed, 50 insertions, 6 deletions
diff --git a/vm.c b/vm.c
index 81de1a21e3..929144d6a8 100644
--- a/vm.c
+++ b/vm.c
@@ -86,25 +86,69 @@ rb_vm_control_frame_block_ptr(const rb_control_frame_t *cfp)
}
static rb_cref_t *
-vm_cref_new(VALUE klass, rb_method_visibility_t visi, const rb_cref_t *prev_cref)
+vm_cref_new0(VALUE klass, rb_method_visibility_t visi, int module_func, rb_cref_t *prev_cref, int pushed_by_eval, int use_prev_prev)
{
+ VALUE refinements = Qnil;
+ int omod_shared = FALSE;
+ rb_cref_t *cref;
+
+ /* scope */
union {
rb_scope_visibility_t visi;
VALUE value;
} scope_visi;
+
scope_visi.visi.method_visi = visi;
- scope_visi.visi.module_func = 0;
+ scope_visi.visi.module_func = module_func;
+
+ /* refinements */
+ if (prev_cref != NULL && prev_cref != (void *)1 /* TODO: why CREF_NEXT(cref) is 1? */) {
+ refinements = CREF_REFINEMENTS(prev_cref);
+
+ if (!NIL_P(refinements)) {
+ omod_shared = TRUE;
+ CREF_OMOD_SHARED_SET(prev_cref);
+ }
+ }
+
+ cref = (rb_cref_t *)rb_imemo_new(imemo_cref, klass, (VALUE)(use_prev_prev ? CREF_NEXT(prev_cref) : prev_cref), scope_visi.value, refinements);
+
+ if (pushed_by_eval) CREF_PUSHED_BY_EVAL_SET(cref);
+ if (omod_shared) CREF_OMOD_SHARED_SET(cref);
+
+ return cref;
+}
+
+static rb_cref_t *
+vm_cref_new(VALUE klass, rb_method_visibility_t visi, int module_func, rb_cref_t *prev_cref, int pushed_by_eval)
+{
+ return vm_cref_new0(klass, visi, module_func, prev_cref, pushed_by_eval, FALSE);
+}
+
+static rb_cref_t *
+vm_cref_new_use_prev(VALUE klass, rb_method_visibility_t visi, int module_func, rb_cref_t *prev_cref, int pushed_by_eval)
+{
+ return vm_cref_new0(klass, visi, module_func, prev_cref, pushed_by_eval, TRUE);
+}
+
+static rb_cref_t *
+vm_cref_dup(const rb_cref_t *cref)
+{
+ VALUE klass = CREF_CLASS(cref);
+ const rb_scope_visibility_t *visi = CREF_SCOPE_VISI(cref);
+ rb_cref_t *next_cref = CREF_NEXT(cref);
+ int pushed_by_eval = CREF_PUSHED_BY_EVAL(cref);
- return (rb_cref_t *)rb_imemo_new(imemo_cref, klass, (VALUE)prev_cref, scope_visi.value, Qnil);
+ return vm_cref_new(klass, visi->method_visi, visi->module_func, next_cref, pushed_by_eval);
}
static rb_cref_t *
vm_cref_new_toplevel(rb_thread_t *th)
{
- rb_cref_t *cref = vm_cref_new(rb_cObject, METHOD_VISI_PRIVATE /* toplevel visibility is private */, NULL);
+ rb_cref_t *cref = vm_cref_new(rb_cObject, METHOD_VISI_PRIVATE /* toplevel visibility is private */, FALSE, NULL, FALSE);
if (th->top_wrapper) {
- cref = vm_cref_new(th->top_wrapper, METHOD_VISI_PRIVATE, cref);
+ cref = vm_cref_new(th->top_wrapper, METHOD_VISI_PRIVATE, FALSE, cref, FALSE);
}
return cref;
@@ -2844,7 +2888,7 @@ Init_VM(void)
th->cfp->pc = iseq->body->iseq_encoded;
th->cfp->self = th->top_self;
- th->cfp->ep[-1] = (VALUE)vm_cref_new(rb_cObject, METHOD_VISI_PRIVATE, NULL);
+ th->cfp->ep[-1] = (VALUE)vm_cref_new(rb_cObject, METHOD_VISI_PRIVATE, FALSE, NULL, FALSE);
/*
* The Binding of the top level scope