summaryrefslogtreecommitdiff
path: root/vm_insnhelper.c
diff options
context:
space:
mode:
authorko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2019-04-05 08:15:11 +0000
committerko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2019-04-05 08:15:11 +0000
commit2b5bb8a0875b75f18e628c8b2df22760536bdad9 (patch)
treeed4f1e080d81f7f5b47c8a10ce6c33285220bed5 /vm_insnhelper.c
parent7fe64d17d3cd455a3f014d6f756cb201320f7f9a (diff)
add definemethod/definesmethod insn.
* insns.def: add definemethod and definesmethod (singleton method) instructions. Old YARV contains these instructions, but it is moved to methods of FrozenCore class because remove number of instructions can improve performance for some techniques (static stack caching and so on). However, we don't employ these technique and it is hard to optimize/analysis definition sequence. So I decide to introduce them (and remove definition methods). `putiseq` insn is also removed. * vm_method.c (rb_scope_visibility_get): renamed to `vm_scope_visibility_get()` and make it accept `ec`. Same for `vm_scope_module_func_check()`. These fixes are result of refactoring `vm_define_method`. * vm_insnhelper.c (rb_vm_get_cref): renamed to `vm_get_cref` because of consistency with other functions. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67442 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'vm_insnhelper.c')
-rw-r--r--vm_insnhelper.c84
1 files changed, 74 insertions, 10 deletions
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index f509ca9236..662e827c15 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -764,9 +764,8 @@ vm_cref_replace_with_duplicated_cref(const VALUE *ep)
}
}
-
static rb_cref_t *
-rb_vm_get_cref(const VALUE *ep)
+vm_get_cref(const VALUE *ep)
{
rb_cref_t *cref = vm_env_cref(ep);
@@ -774,14 +773,25 @@ rb_vm_get_cref(const VALUE *ep)
return cref;
}
else {
- rb_bug("rb_vm_get_cref: unreachable");
+ rb_bug("vm_get_cref: unreachable");
+ }
+}
+
+static rb_cref_t *
+vm_ec_cref(const rb_execution_context_t *ec)
+{
+ const rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(ec, ec->cfp);
+
+ if (cfp == NULL) {
+ return NULL;
}
+ return vm_get_cref(cfp->ep);
}
static const rb_cref_t *
vm_get_const_key_cref(const VALUE *ep)
{
- const rb_cref_t *cref = rb_vm_get_cref(ep);
+ const rb_cref_t *cref = vm_get_cref(ep);
const rb_cref_t *key_cref = cref;
while (cref) {
@@ -836,7 +846,7 @@ vm_cref_push(const rb_execution_context_t *ec, VALUE klass, const VALUE *ep, int
static inline VALUE
vm_get_cbase(const VALUE *ep)
{
- const rb_cref_t *cref = rb_vm_get_cref(ep);
+ const rb_cref_t *cref = vm_get_cref(ep);
VALUE klass = Qundef;
while (cref) {
@@ -852,7 +862,7 @@ vm_get_cbase(const VALUE *ep)
static inline VALUE
vm_get_const_base(const VALUE *ep)
{
- const rb_cref_t *cref = rb_vm_get_cref(ep);
+ const rb_cref_t *cref = vm_get_cref(ep);
VALUE klass = Qundef;
while (cref) {
@@ -896,7 +906,7 @@ vm_get_ev_const(rb_execution_context_t *ec, VALUE orig_klass, ID id, int is_defi
if (orig_klass == Qnil) {
/* in current lexical scope */
- const rb_cref_t *root_cref = rb_vm_get_cref(ec->cfp->ep);
+ const rb_cref_t *root_cref = vm_get_cref(ec->cfp->ep);
const rb_cref_t *cref;
VALUE klass = Qnil;
@@ -2600,7 +2610,7 @@ vm_call_method_each_type(rb_execution_context_t *ec, rb_control_frame_t *cfp, st
return vm_call_zsuper(ec, cfp, calling, ci, cc, RCLASS_ORIGIN(cc->me->defined_class));
case VM_METHOD_TYPE_REFINED: {
- const rb_cref_t *cref = rb_vm_get_cref(cfp->ep);
+ const rb_cref_t *cref = vm_get_cref(cfp->ep);
VALUE refinements = cref ? CREF_REFINEMENTS(cref) : Qnil;
VALUE refinement;
const rb_callable_method_entry_t *ref_me;
@@ -3131,7 +3141,7 @@ vm_defined(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, rb_num_t op_
}
break;
case DEFINED_CVAR: {
- const rb_cref_t *cref = rb_vm_get_cref(GET_EP());
+ const rb_cref_t *cref = vm_get_cref(GET_EP());
klass = vm_get_cvar_base(cref, GET_CFP());
if (rb_cvar_defined(klass, SYM2ID(obj))) {
expr_type = DEFINED_CVAR;
@@ -3494,6 +3504,60 @@ vm_find_or_create_class_by_id(ID id,
}
}
+static rb_method_visibility_t
+vm_scope_visibility_get(const rb_execution_context_t *ec)
+{
+ const rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(ec, ec->cfp);
+
+ if (!vm_env_cref_by_cref(cfp->ep)) {
+ return METHOD_VISI_PUBLIC;
+ }
+ else {
+ return CREF_SCOPE_VISI(vm_ec_cref(ec))->method_visi;
+ }
+}
+
+static int
+vm_scope_module_func_check(const rb_execution_context_t *ec)
+{
+ const rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(ec, ec->cfp);
+
+ if (!vm_env_cref_by_cref(cfp->ep)) {
+ return FALSE;
+ }
+ else {
+ return CREF_SCOPE_VISI(vm_ec_cref(ec))->module_func;
+ }
+}
+
+static void
+vm_define_method(const rb_execution_context_t *ec, VALUE obj, ID id, VALUE iseqval, int is_singleton)
+{
+ VALUE klass;
+ rb_method_visibility_t visi;
+ rb_cref_t *cref = vm_ec_cref(ec);
+
+ if (!is_singleton) {
+ klass = CREF_CLASS(cref);
+ visi = vm_scope_visibility_get(ec);
+ }
+ else { /* singleton */
+ klass = rb_singleton_class(obj); /* class and frozen checked in this API */
+ visi = METHOD_VISI_PUBLIC;
+ }
+
+ if (NIL_P(klass)) {
+ rb_raise(rb_eTypeError, "no class/module to add method");
+ }
+
+ rb_add_method_iseq(klass, id, (const rb_iseq_t *)iseqval, cref, visi);
+
+ if (!is_singleton && vm_scope_module_func_check(ec)) {
+ klass = rb_singleton_class(klass);
+ rb_add_method_iseq(klass, id, (const rb_iseq_t *)iseqval, cref, METHOD_VISI_PUBLIC);
+ }
+}
+
static void
vm_search_method_wrap(
const struct rb_control_frame_struct *reg_cfp,
@@ -3663,7 +3727,7 @@ static int
vm_ic_hit_p(IC ic, const VALUE *reg_ep)
{
if (ic->ic_serial == GET_GLOBAL_CONSTANT_STATE()) {
- return (ic->ic_cref == NULL || ic->ic_cref == rb_vm_get_cref(reg_ep));
+ return (ic->ic_cref == NULL || ic->ic_cref == vm_get_cref(reg_ep));
}
return FALSE;
}