mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
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
This commit is contained in:
parent
7fe64d17d3
commit
2b5bb8a087
7 changed files with 131 additions and 155 deletions
56
compile.c
56
compile.c
|
@ -7142,39 +7142,33 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, in
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NODE_DEFN:{
|
case NODE_DEFN:{
|
||||||
|
ID mid = node->nd_mid;
|
||||||
const rb_iseq_t *method_iseq = NEW_ISEQ(node->nd_defn,
|
const rb_iseq_t *method_iseq = NEW_ISEQ(node->nd_defn,
|
||||||
rb_id2str(node->nd_mid),
|
rb_id2str(mid),
|
||||||
ISEQ_TYPE_METHOD, line);
|
ISEQ_TYPE_METHOD, line);
|
||||||
|
|
||||||
debugp_param("defn/iseq", rb_iseqw_new(method_iseq));
|
debugp_param("defn/iseq", rb_iseqw_new(method_iseq));
|
||||||
|
ADD_INSN2(ret, line, definemethod, ID2SYM(mid), method_iseq);
|
||||||
|
|
||||||
ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
|
if (!popped) {
|
||||||
ADD_INSN1(ret, line, putobject, ID2SYM(node->nd_mid));
|
ADD_INSN1(ret, line, putobject, ID2SYM(mid));
|
||||||
ADD_INSN1(ret, line, putiseq, method_iseq);
|
|
||||||
ADD_SEND (ret, line, id_core_define_method, INT2FIX(2));
|
|
||||||
|
|
||||||
if (popped) {
|
|
||||||
ADD_INSN(ret, line, pop);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NODE_DEFS:{
|
case NODE_DEFS:{
|
||||||
const rb_iseq_t * singleton_method = NEW_ISEQ(node->nd_defn,
|
ID mid = node->nd_mid;
|
||||||
rb_id2str(node->nd_mid),
|
const rb_iseq_t * singleton_method_iseq = NEW_ISEQ(node->nd_defn,
|
||||||
ISEQ_TYPE_METHOD, line);
|
rb_id2str(mid),
|
||||||
|
ISEQ_TYPE_METHOD, line);
|
||||||
|
|
||||||
debugp_param("defs/iseq", rb_iseqw_new(singleton_method));
|
debugp_param("defs/iseq", rb_iseqw_new(singleton_method_iseq));
|
||||||
|
CHECK(COMPILE(ret, "defs: recv", node->nd_recv));
|
||||||
|
ADD_INSN2(ret, line, definesmethod, ID2SYM(mid), singleton_method_iseq);
|
||||||
|
|
||||||
ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
|
if (!popped) {
|
||||||
CHECK(COMPILE(ret, "defs: recv", node->nd_recv));
|
ADD_INSN1(ret, line, putobject, ID2SYM(mid));
|
||||||
ADD_INSN1(ret, line, putobject, ID2SYM(node->nd_mid));
|
}
|
||||||
ADD_INSN1(ret, line, putiseq, singleton_method);
|
|
||||||
ADD_SEND (ret, line, id_core_define_singleton_method, INT2FIX(3));
|
|
||||||
|
|
||||||
if (popped) {
|
|
||||||
ADD_INSN(ret, line, pop);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NODE_ALIAS:{
|
case NODE_ALIAS:{
|
||||||
|
@ -8761,7 +8755,7 @@ ibf_load_code(const struct ibf_load *load, const rb_iseq_t *iseq, const struct r
|
||||||
for (code_index=0; code_index<iseq_size;) {
|
for (code_index=0; code_index<iseq_size;) {
|
||||||
const VALUE insn = code[code_index++];
|
const VALUE insn = code[code_index++];
|
||||||
const char *types = insn_op_types(insn);
|
const char *types = insn_op_types(insn);
|
||||||
int op_index;
|
int op_index;
|
||||||
|
|
||||||
for (op_index=0; types[op_index]; op_index++, code_index++) {
|
for (op_index=0; types[op_index]; op_index++, code_index++) {
|
||||||
VALUE op = code[code_index];
|
VALUE op = code[code_index];
|
||||||
|
@ -8779,15 +8773,15 @@ ibf_load_code(const struct ibf_load *load, const rb_iseq_t *iseq, const struct r
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TS_ISEQ:
|
case TS_ISEQ:
|
||||||
{
|
{
|
||||||
VALUE v = (VALUE)ibf_load_iseq(load, (const rb_iseq_t *)op);
|
VALUE v = (VALUE)ibf_load_iseq(load, (const rb_iseq_t *)op);
|
||||||
code[code_index] = v;
|
code[code_index] = v;
|
||||||
if (!SPECIAL_CONST_P(v)) {
|
if (!SPECIAL_CONST_P(v)) {
|
||||||
RB_OBJ_WRITTEN(iseq, Qundef, v);
|
RB_OBJ_WRITTEN(iseq, Qundef, v);
|
||||||
FL_SET(iseq, ISEQ_MARKABLE_ISEQ);
|
FL_SET(iseq, ISEQ_MARKABLE_ISEQ);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TS_ISE:
|
case TS_ISE:
|
||||||
FL_SET(iseq, ISEQ_MARKABLE_ISEQ);
|
FL_SET(iseq, ISEQ_MARKABLE_ISEQ);
|
||||||
case TS_IC:
|
case TS_IC:
|
||||||
|
|
33
insns.def
33
insns.def
|
@ -236,7 +236,7 @@ getclassvariable
|
||||||
/* "class variable access from toplevel" warning can be hooked. */
|
/* "class variable access from toplevel" warning can be hooked. */
|
||||||
// attr bool leaf = false; /* has rb_warning() */
|
// attr bool leaf = false; /* has rb_warning() */
|
||||||
{
|
{
|
||||||
val = rb_cvar_get(vm_get_cvar_base(rb_vm_get_cref(GET_EP()), GET_CFP()), id);
|
val = rb_cvar_get(vm_get_cvar_base(vm_get_cref(GET_EP()), GET_CFP()), id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set value of class variable id of klass as val. */
|
/* Set value of class variable id of klass as val. */
|
||||||
|
@ -249,7 +249,7 @@ setclassvariable
|
||||||
// attr bool leaf = false; /* has rb_warning() */
|
// attr bool leaf = false; /* has rb_warning() */
|
||||||
{
|
{
|
||||||
vm_ensure_not_refinement_module(GET_SELF());
|
vm_ensure_not_refinement_module(GET_SELF());
|
||||||
rb_cvar_set(vm_get_cvar_base(rb_vm_get_cref(GET_EP()), GET_CFP()), id, val);
|
rb_cvar_set(vm_get_cvar_base(vm_get_cref(GET_EP()), GET_CFP()), id, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get constant variable id. If klass is Qnil, constants
|
/* Get constant variable id. If klass is Qnil, constants
|
||||||
|
@ -358,17 +358,6 @@ putspecialobject
|
||||||
val = vm_get_special_object(GET_EP(), type);
|
val = vm_get_special_object(GET_EP(), type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* put iseq value. */
|
|
||||||
DEFINE_INSN
|
|
||||||
putiseq
|
|
||||||
(ISEQ iseq)
|
|
||||||
()
|
|
||||||
(VALUE ret)
|
|
||||||
// attr bool handles_sp = false; /* of course it doesn't */
|
|
||||||
{
|
|
||||||
ret = (VALUE)iseq;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* put string val. string will be copied. */
|
/* put string val. string will be copied. */
|
||||||
DEFINE_INSN
|
DEFINE_INSN
|
||||||
putstring
|
putstring
|
||||||
|
@ -748,6 +737,24 @@ defineclass
|
||||||
NEXT_INSN();
|
NEXT_INSN();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFINE_INSN
|
||||||
|
definemethod
|
||||||
|
(ID id, ISEQ iseq)
|
||||||
|
()
|
||||||
|
()
|
||||||
|
{
|
||||||
|
vm_define_method(ec, Qnil, id, (VALUE)iseq, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_INSN
|
||||||
|
definesmethod
|
||||||
|
(ID id, ISEQ iseq)
|
||||||
|
(VALUE obj)
|
||||||
|
()
|
||||||
|
{
|
||||||
|
vm_define_method(ec, obj, id, (VALUE)iseq, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
/**********************************************************/
|
/**********************************************************/
|
||||||
/* deal with control flow 2: method/iterator */
|
/* deal with control flow 2: method/iterator */
|
||||||
/**********************************************************/
|
/**********************************************************/
|
||||||
|
|
|
@ -183,18 +183,6 @@ class TestJIT < Test::Unit::TestCase
|
||||||
assert_compile_once('2', result_inspect: '2', insns: %i[putobject])
|
assert_compile_once('2', result_inspect: '2', insns: %i[putobject])
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_compile_insn_putspecialobject_putiseq
|
|
||||||
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: 'hellohello', success_count: 2, insns: %i[putspecialobject putiseq])
|
|
||||||
begin;
|
|
||||||
print 2.times.map {
|
|
||||||
def method_definition
|
|
||||||
'hello'
|
|
||||||
end
|
|
||||||
method_definition
|
|
||||||
}.join
|
|
||||||
end;
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_compile_insn_putstring_concatstrings_tostring
|
def test_compile_insn_putstring_concatstrings_tostring
|
||||||
assert_compile_once('"a#{}b" + "c"', result_inspect: '"abc"', insns: %i[putstring concatstrings tostring])
|
assert_compile_once('"a#{}b" + "c"', result_inspect: '"abc"', insns: %i[putstring concatstrings tostring])
|
||||||
end
|
end
|
||||||
|
@ -952,8 +940,10 @@ class TestJIT < Test::Unit::TestCase
|
||||||
insns = []
|
insns = []
|
||||||
RubyVM::InstructionSequence.compile(script).to_a.last.each do |(insn, *args)|
|
RubyVM::InstructionSequence.compile(script).to_a.last.each do |(insn, *args)|
|
||||||
case insn
|
case insn
|
||||||
when :putiseq, :send
|
when :send
|
||||||
insns += collect_insns(args.last)
|
insns += collect_insns(args.last)
|
||||||
|
when :definemethod, :definesmethod
|
||||||
|
insns += collect_insns(args[1])
|
||||||
when :defineclass
|
when :defineclass
|
||||||
insns += collect_insns(args[1])
|
insns += collect_insns(args[1])
|
||||||
end
|
end
|
||||||
|
@ -968,7 +958,8 @@ class TestJIT < Test::Unit::TestCase
|
||||||
insns = iseq_array.last.select { |x| x.is_a?(Array) }.map(&:first)
|
insns = iseq_array.last.select { |x| x.is_a?(Array) }.map(&:first)
|
||||||
iseq_array.last.each do |(insn, *args)|
|
iseq_array.last.each do |(insn, *args)|
|
||||||
case insn
|
case insn
|
||||||
when :putiseq, :send
|
when :definemethod, :definesmethod,
|
||||||
|
:send
|
||||||
insns += collect_insns(args.last)
|
insns += collect_insns(args.last)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
57
vm.c
57
vm.c
|
@ -1368,12 +1368,7 @@ rb_cref_t *
|
||||||
rb_vm_cref(void)
|
rb_vm_cref(void)
|
||||||
{
|
{
|
||||||
const rb_execution_context_t *ec = GET_EC();
|
const rb_execution_context_t *ec = GET_EC();
|
||||||
const rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(ec, ec->cfp);
|
return vm_ec_cref(ec);
|
||||||
|
|
||||||
if (cfp == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return rb_vm_get_cref(cfp->ep);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rb_cref_t *
|
rb_cref_t *
|
||||||
|
@ -1393,7 +1388,7 @@ rb_vm_cref_in_context(VALUE self, VALUE cbase)
|
||||||
const rb_cref_t *cref;
|
const rb_cref_t *cref;
|
||||||
if (cfp->self != self) return NULL;
|
if (cfp->self != self) return NULL;
|
||||||
if (!vm_env_cref_by_cref(cfp->ep)) return NULL;
|
if (!vm_env_cref_by_cref(cfp->ep)) return NULL;
|
||||||
cref = rb_vm_get_cref(cfp->ep);
|
cref = vm_get_cref(cfp->ep);
|
||||||
if (CREF_CLASS(cref) != cbase) return NULL;
|
if (CREF_CLASS(cref) != cbase) return NULL;
|
||||||
return cref;
|
return cref;
|
||||||
}
|
}
|
||||||
|
@ -2678,34 +2673,6 @@ rb_thread_alloc(VALUE klass)
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
vm_define_method(VALUE obj, ID id, VALUE iseqval, int is_singleton)
|
|
||||||
{
|
|
||||||
VALUE klass;
|
|
||||||
rb_method_visibility_t visi;
|
|
||||||
rb_cref_t *cref = rb_vm_cref();
|
|
||||||
|
|
||||||
if (!is_singleton) {
|
|
||||||
klass = CREF_CLASS(cref);
|
|
||||||
visi = rb_scope_visibility_get();
|
|
||||||
}
|
|
||||||
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 && rb_scope_module_func_check()) {
|
|
||||||
klass = rb_singleton_class(klass);
|
|
||||||
rb_add_method_iseq(klass, id, (const rb_iseq_t *)iseqval, cref, METHOD_VISI_PUBLIC);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#define REWIND_CFP(expr) do { \
|
#define REWIND_CFP(expr) do { \
|
||||||
rb_execution_context_t *ec__ = GET_EC(); \
|
rb_execution_context_t *ec__ = GET_EC(); \
|
||||||
VALUE *const curr_sp = (ec__->cfp++)->sp; \
|
VALUE *const curr_sp = (ec__->cfp++)->sp; \
|
||||||
|
@ -2715,24 +2682,6 @@ vm_define_method(VALUE obj, ID id, VALUE iseqval, int is_singleton)
|
||||||
(ec__->cfp--)->sp = saved_sp; \
|
(ec__->cfp--)->sp = saved_sp; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
static VALUE
|
|
||||||
m_core_define_method(VALUE self, VALUE sym, VALUE iseqval)
|
|
||||||
{
|
|
||||||
REWIND_CFP({
|
|
||||||
vm_define_method(Qnil, SYM2ID(sym), iseqval, FALSE);
|
|
||||||
});
|
|
||||||
return sym;
|
|
||||||
}
|
|
||||||
|
|
||||||
static VALUE
|
|
||||||
m_core_define_singleton_method(VALUE self, VALUE cbase, VALUE sym, VALUE iseqval)
|
|
||||||
{
|
|
||||||
REWIND_CFP({
|
|
||||||
vm_define_method(cbase, SYM2ID(sym), iseqval, TRUE);
|
|
||||||
});
|
|
||||||
return sym;
|
|
||||||
}
|
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
m_core_set_method_alias(VALUE self, VALUE cbase, VALUE sym1, VALUE sym2)
|
m_core_set_method_alias(VALUE self, VALUE cbase, VALUE sym1, VALUE sym2)
|
||||||
{
|
{
|
||||||
|
@ -2931,8 +2880,6 @@ Init_VM(void)
|
||||||
rb_define_method_id(klass, id_core_set_method_alias, m_core_set_method_alias, 3);
|
rb_define_method_id(klass, id_core_set_method_alias, m_core_set_method_alias, 3);
|
||||||
rb_define_method_id(klass, id_core_set_variable_alias, m_core_set_variable_alias, 2);
|
rb_define_method_id(klass, id_core_set_variable_alias, m_core_set_variable_alias, 2);
|
||||||
rb_define_method_id(klass, id_core_undef_method, m_core_undef_method, 2);
|
rb_define_method_id(klass, id_core_undef_method, m_core_undef_method, 2);
|
||||||
rb_define_method_id(klass, id_core_define_method, m_core_define_method, 2);
|
|
||||||
rb_define_method_id(klass, id_core_define_singleton_method, m_core_define_singleton_method, 3);
|
|
||||||
rb_define_method_id(klass, id_core_set_postexe, m_core_set_postexe, 0);
|
rb_define_method_id(klass, id_core_set_postexe, m_core_set_postexe, 0);
|
||||||
rb_define_method_id(klass, id_core_hash_merge_ptr, m_core_hash_merge_ptr, -1);
|
rb_define_method_id(klass, id_core_hash_merge_ptr, m_core_hash_merge_ptr, -1);
|
||||||
rb_define_method_id(klass, id_core_hash_merge_kwd, m_core_hash_merge_kwd, 2);
|
rb_define_method_id(klass, id_core_hash_merge_kwd, m_core_hash_merge_kwd, 2);
|
||||||
|
|
|
@ -1322,7 +1322,7 @@ eval_string_with_cref(VALUE self, VALUE src, rb_cref_t *cref, VALUE file, int li
|
||||||
|
|
||||||
/* TODO: what the code checking? */
|
/* TODO: what the code checking? */
|
||||||
if (!cref && block.as.captured.code.val) {
|
if (!cref && block.as.captured.code.val) {
|
||||||
rb_cref_t *orig_cref = rb_vm_get_cref(vm_block_ep(&block));
|
rb_cref_t *orig_cref = vm_get_cref(vm_block_ep(&block));
|
||||||
cref = vm_cref_dup(orig_cref);
|
cref = vm_cref_dup(orig_cref);
|
||||||
}
|
}
|
||||||
vm_set_eval_stack(ec, iseq, cref, &block);
|
vm_set_eval_stack(ec, iseq, cref, &block);
|
||||||
|
|
|
@ -764,9 +764,8 @@ vm_cref_replace_with_duplicated_cref(const VALUE *ep)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static rb_cref_t *
|
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);
|
rb_cref_t *cref = vm_env_cref(ep);
|
||||||
|
|
||||||
|
@ -774,14 +773,25 @@ rb_vm_get_cref(const VALUE *ep)
|
||||||
return cref;
|
return cref;
|
||||||
}
|
}
|
||||||
else {
|
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 *
|
static const rb_cref_t *
|
||||||
vm_get_const_key_cref(const VALUE *ep)
|
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;
|
const rb_cref_t *key_cref = cref;
|
||||||
|
|
||||||
while (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
|
static inline VALUE
|
||||||
vm_get_cbase(const VALUE *ep)
|
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;
|
VALUE klass = Qundef;
|
||||||
|
|
||||||
while (cref) {
|
while (cref) {
|
||||||
|
@ -852,7 +862,7 @@ vm_get_cbase(const VALUE *ep)
|
||||||
static inline VALUE
|
static inline VALUE
|
||||||
vm_get_const_base(const VALUE *ep)
|
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;
|
VALUE klass = Qundef;
|
||||||
|
|
||||||
while (cref) {
|
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) {
|
if (orig_klass == Qnil) {
|
||||||
/* in current lexical scope */
|
/* 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;
|
const rb_cref_t *cref;
|
||||||
VALUE klass = Qnil;
|
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));
|
return vm_call_zsuper(ec, cfp, calling, ci, cc, RCLASS_ORIGIN(cc->me->defined_class));
|
||||||
|
|
||||||
case VM_METHOD_TYPE_REFINED: {
|
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 refinements = cref ? CREF_REFINEMENTS(cref) : Qnil;
|
||||||
VALUE refinement;
|
VALUE refinement;
|
||||||
const rb_callable_method_entry_t *ref_me;
|
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;
|
break;
|
||||||
case DEFINED_CVAR: {
|
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());
|
klass = vm_get_cvar_base(cref, GET_CFP());
|
||||||
if (rb_cvar_defined(klass, SYM2ID(obj))) {
|
if (rb_cvar_defined(klass, SYM2ID(obj))) {
|
||||||
expr_type = DEFINED_CVAR;
|
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
|
static void
|
||||||
vm_search_method_wrap(
|
vm_search_method_wrap(
|
||||||
const struct rb_control_frame_struct *reg_cfp,
|
const struct rb_control_frame_struct *reg_cfp,
|
||||||
|
@ -3663,7 +3727,7 @@ static int
|
||||||
vm_ic_hit_p(IC ic, const VALUE *reg_ep)
|
vm_ic_hit_p(IC ic, const VALUE *reg_ep)
|
||||||
{
|
{
|
||||||
if (ic->ic_serial == GET_GLOBAL_CONSTANT_STATE()) {
|
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;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
35
vm_method.c
35
vm_method.c
|
@ -669,7 +669,7 @@ rb_add_method(VALUE klass, ID mid, rb_method_type_t type, void *opts, rb_method_
|
||||||
return me;
|
return me;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
MJIT_FUNC_EXPORTED void
|
||||||
rb_add_method_iseq(VALUE klass, ID mid, const rb_iseq_t *iseq, rb_cref_t *cref, rb_method_visibility_t visi)
|
rb_add_method_iseq(VALUE klass, ID mid, const rb_iseq_t *iseq, rb_cref_t *cref, rb_method_visibility_t visi)
|
||||||
{
|
{
|
||||||
struct { /* should be same fields with rb_method_iseq_struct */
|
struct { /* should be same fields with rb_method_iseq_struct */
|
||||||
|
@ -1117,34 +1117,6 @@ rb_method_boundp(VALUE klass, ID id, int ex)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static rb_method_visibility_t
|
|
||||||
rb_scope_visibility_get(void)
|
|
||||||
{
|
|
||||||
const rb_execution_context_t *ec = GET_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(rb_vm_cref())->method_visi;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
rb_scope_module_func_check(void)
|
|
||||||
{
|
|
||||||
const rb_execution_context_t *ec = GET_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(rb_vm_cref())->module_func;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
vm_cref_set_visibility(rb_method_visibility_t method_visi, int module_func)
|
vm_cref_set_visibility(rb_method_visibility_t method_visi, int module_func)
|
||||||
{
|
{
|
||||||
|
@ -1170,14 +1142,15 @@ rb_attr(VALUE klass, ID id, int read, int write, int ex)
|
||||||
{
|
{
|
||||||
ID attriv;
|
ID attriv;
|
||||||
rb_method_visibility_t visi;
|
rb_method_visibility_t visi;
|
||||||
|
const rb_execution_context_t *ec = GET_EC();
|
||||||
|
|
||||||
if (!ex) {
|
if (!ex) {
|
||||||
visi = METHOD_VISI_PUBLIC;
|
visi = METHOD_VISI_PUBLIC;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
switch (rb_scope_visibility_get()) {
|
switch (vm_scope_visibility_get(ec)) {
|
||||||
case METHOD_VISI_PRIVATE:
|
case METHOD_VISI_PRIVATE:
|
||||||
if (rb_scope_module_func_check()) {
|
if (vm_scope_module_func_check(ec)) {
|
||||||
rb_warning("attribute accessor as module_function");
|
rb_warning("attribute accessor as module_function");
|
||||||
}
|
}
|
||||||
visi = METHOD_VISI_PRIVATE;
|
visi = METHOD_VISI_PRIVATE;
|
||||||
|
|
Loading…
Add table
Reference in a new issue